Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2020
- 75 participants
- 1522 messages
[PATCH 4/8] msvcrt: Share lconv data between threadlocinfo instances.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/msvcrt/locale.c | 275 ++++++++++++++++++++++++++-----------------
1 file changed, 164 insertions(+), 111 deletions(-)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index aee39a0eafbe..6370b7e3a9a7 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -58,6 +58,21 @@ BOOL initial_locale = TRUE;
static char cloc_clmap[256];
static char cloc_cumap[256];
+#if _MSVCR_VER >= 100
+static const MSVCRT_wchar_t emptyW[] = {0};
+static const MSVCRT_wchar_t cloc_dec_point[] = {'.', 0};
+#endif
+static struct MSVCRT_lconv cloc_lconv =
+{
+ ".", "", "",
+ "", "", "", "", "", "", "", CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX
+#if _MSVCR_VER >= 100
+ ,
+ cloc_dec_point, emptyW,
+ emptyW, emptyW, emptyW, emptyW, emptyW, emptyW
+#endif
+};
+
static const MSVCRT_wchar_t sun[] = {'S','u','n',0};
static const MSVCRT_wchar_t mon[] = {'M','o','n',0};
static const MSVCRT_wchar_t tue[] = {'T','u','e',0};
@@ -853,6 +868,14 @@ int CDECL __lconv_init(void)
{
/* this is used to make chars unsigned */
charmax = 255;
+ cloc_lconv.int_frac_digits = charmax;
+ cloc_lconv.frac_digits = charmax;
+ cloc_lconv.p_cs_precedes = charmax;
+ cloc_lconv.p_sep_by_space = charmax;
+ cloc_lconv.n_cs_precedes = charmax;
+ cloc_lconv.n_sep_by_space = charmax;
+ cloc_lconv.p_sign_posn = charmax;
+ cloc_lconv.n_sign_posn = charmax;
return 0;
}
@@ -913,31 +936,42 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo)
}
if(locinfo->lconv) {
- MSVCRT_free(locinfo->lconv->decimal_point);
- MSVCRT_free(locinfo->lconv->thousands_sep);
- MSVCRT_free(locinfo->lconv->grouping);
- MSVCRT_free(locinfo->lconv->int_curr_symbol);
- MSVCRT_free(locinfo->lconv->currency_symbol);
- MSVCRT_free(locinfo->lconv->mon_decimal_point);
- MSVCRT_free(locinfo->lconv->mon_thousands_sep);
- MSVCRT_free(locinfo->lconv->mon_grouping);
- MSVCRT_free(locinfo->lconv->positive_sign);
- MSVCRT_free(locinfo->lconv->negative_sign);
+ if(locinfo->lconv_num_refcount
+ && !InterlockedDecrement(locinfo->lconv_num_refcount)) {
+ MSVCRT_free(locinfo->lconv->decimal_point);
+ MSVCRT_free(locinfo->lconv->thousands_sep);
+ MSVCRT_free(locinfo->lconv->grouping);
#if _MSVCR_VER >= 100
- MSVCRT_free(locinfo->lconv->_W_decimal_point);
- MSVCRT_free(locinfo->lconv->_W_thousands_sep);
- MSVCRT_free(locinfo->lconv->_W_int_curr_symbol);
- MSVCRT_free(locinfo->lconv->_W_currency_symbol);
- MSVCRT_free(locinfo->lconv->_W_mon_decimal_point);
- MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep);
- MSVCRT_free(locinfo->lconv->_W_positive_sign);
- MSVCRT_free(locinfo->lconv->_W_negative_sign);
+ MSVCRT_free(locinfo->lconv->_W_decimal_point);
+ MSVCRT_free(locinfo->lconv->_W_thousands_sep);
#endif
+ MSVCRT_free(locinfo->lconv_num_refcount);
+ }
+ if(locinfo->lconv_mon_refcount
+ && !InterlockedDecrement(locinfo->lconv_mon_refcount)) {
+ MSVCRT_free(locinfo->lconv->int_curr_symbol);
+ MSVCRT_free(locinfo->lconv->currency_symbol);
+ MSVCRT_free(locinfo->lconv->mon_decimal_point);
+ MSVCRT_free(locinfo->lconv->mon_thousands_sep);
+ MSVCRT_free(locinfo->lconv->mon_grouping);
+ MSVCRT_free(locinfo->lconv->positive_sign);
+ MSVCRT_free(locinfo->lconv->negative_sign);
+#if _MSVCR_VER >= 100
+ MSVCRT_free(locinfo->lconv->_W_int_curr_symbol);
+ MSVCRT_free(locinfo->lconv->_W_currency_symbol);
+ MSVCRT_free(locinfo->lconv->_W_mon_decimal_point);
+ MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep);
+ MSVCRT_free(locinfo->lconv->_W_positive_sign);
+ MSVCRT_free(locinfo->lconv->_W_negative_sign);
+#endif
+ MSVCRT_free(locinfo->lconv_mon_refcount);
+ }
+ if(locinfo->lconv_intl_refcount
+ && !InterlockedDecrement(locinfo->lconv_intl_refcount)) {
+ MSVCRT_free(locinfo->lconv_intl_refcount);
+ MSVCRT_free(locinfo->lconv);
+ }
}
- MSVCRT_free(locinfo->lconv_intl_refcount);
- MSVCRT_free(locinfo->lconv_num_refcount);
- MSVCRT_free(locinfo->lconv_mon_refcount);
- MSVCRT_free(locinfo->lconv);
if(locinfo->ctype1_refcount
&& !InterlockedDecrement(locinfo->ctype1_refcount)) {
@@ -1204,13 +1238,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
memset(locinfo, 0, sizeof(MSVCRT_threadlocinfo));
locinfo->refcount = 1;
- locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv));
- if(!locinfo->lconv) {
- free_locinfo(locinfo);
- return NULL;
- }
- memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv));
-
if(locale_name[MSVCRT_LC_COLLATE] &&
!init_category_name(locale_name[MSVCRT_LC_COLLATE],
locale_len[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) {
@@ -1337,6 +1364,38 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->pcumap = cloc_cumap;
}
+ if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
+ lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])
+ && !category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
+ lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
+ locinfo->lconv = old_locinfo->lconv;
+ locinfo->lconv_intl_refcount = old_locinfo->lconv_intl_refcount;
+ if(locinfo->lconv_intl_refcount)
+ InterlockedIncrement(locinfo->lconv_intl_refcount);
+ } else if((lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY))
+ || (lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC))
+ || (!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
+ lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])
+ && old_locinfo->lc_handle[MSVCRT_LC_MONETARY])
+ || (!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
+ lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])
+ && old_locinfo->lc_handle[MSVCRT_LC_NUMERIC])) {
+ locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv));
+ locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int));
+ if(!locinfo->lconv || !locinfo->lconv_intl_refcount) {
+ MSVCRT_free(locinfo->lconv);
+ MSVCRT_free(locinfo->lconv_intl_refcount);
+ locinfo->lconv = NULL;
+ locinfo->lconv_intl_refcount = NULL;
+ free_locinfo(locinfo);
+ return NULL;
+ }
+ memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv));
+ *locinfo->lconv_intl_refcount = 1;
+ } else {
+ locinfo->lconv = &cloc_lconv;
+ }
+
if(locale_name[MSVCRT_LC_MONETARY] &&
!init_category_name(locale_name[MSVCRT_LC_MONETARY],
locale_len[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) {
@@ -1347,6 +1406,35 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) {
copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY);
+ locinfo->lconv_mon_refcount = old_locinfo->lconv_mon_refcount;
+ if(locinfo->lconv_mon_refcount)
+ InterlockedIncrement(locinfo->lconv_mon_refcount);
+ if(category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
+ lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
+ locinfo->lconv->int_curr_symbol = old_locinfo->lconv->int_curr_symbol;
+ locinfo->lconv->currency_symbol = old_locinfo->lconv->currency_symbol;
+ locinfo->lconv->mon_decimal_point = old_locinfo->lconv->mon_decimal_point;
+ locinfo->lconv->mon_thousands_sep = old_locinfo->lconv->mon_thousands_sep;
+ locinfo->lconv->mon_grouping = old_locinfo->lconv->mon_grouping;
+ locinfo->lconv->positive_sign = old_locinfo->lconv->positive_sign;
+ locinfo->lconv->negative_sign = old_locinfo->lconv->negative_sign;
+ locinfo->lconv->int_frac_digits = old_locinfo->lconv->int_frac_digits;
+ locinfo->lconv->frac_digits = old_locinfo->lconv->frac_digits;
+ locinfo->lconv->p_cs_precedes = old_locinfo->lconv->p_cs_precedes;
+ locinfo->lconv->p_sep_by_space = old_locinfo->lconv->p_sep_by_space;
+ locinfo->lconv->n_cs_precedes = old_locinfo->lconv->n_cs_precedes;
+ locinfo->lconv->n_sep_by_space = old_locinfo->lconv->n_sep_by_space;
+ locinfo->lconv->p_sign_posn = old_locinfo->lconv->p_sign_posn;
+ locinfo->lconv->n_sign_posn = old_locinfo->lconv->n_sign_posn;
+#if _MSVCR_VER >= 100
+ locinfo->lconv->_W_int_curr_symbol = old_locinfo->lconv->_W_int_curr_symbol;
+ locinfo->lconv->_W_currency_symbol = old_locinfo->lconv->_W_currency_symbol;
+ locinfo->lconv->_W_mon_decimal_point = old_locinfo->lconv->_W_mon_decimal_point;
+ locinfo->lconv->_W_mon_thousands_sep = old_locinfo->lconv->_W_mon_thousands_sep;
+ locinfo->lconv->_W_positive_sign = old_locinfo->lconv->_W_positive_sign;
+ locinfo->lconv->_W_negative_sign = old_locinfo->lconv->_W_negative_sign;
+#endif
+ }
} else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY],
cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) {
@@ -1354,14 +1442,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
- locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int));
locinfo->lconv_mon_refcount = MSVCRT_malloc(sizeof(int));
- if(!locinfo->lconv_intl_refcount || !locinfo->lconv_mon_refcount) {
+ if(!locinfo->lconv_mon_refcount) {
free_locinfo(locinfo);
return NULL;
}
- *locinfo->lconv_intl_refcount = 1;
*locinfo->lconv_mon_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SINTLSYMBOL
@@ -1558,60 +1644,33 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
} else {
- locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char));
-
- if(!locinfo->lconv->int_curr_symbol || !locinfo->lconv->currency_symbol
- || !locinfo->lconv->mon_decimal_point || !locinfo->lconv->mon_thousands_sep
- || !locinfo->lconv->mon_grouping || !locinfo->lconv->positive_sign
- || !locinfo->lconv->negative_sign) {
- free_locinfo(locinfo);
- return NULL;
- }
-
- locinfo->lconv->int_curr_symbol[0] = '\0';
- locinfo->lconv->currency_symbol[0] = '\0';
- locinfo->lconv->mon_decimal_point[0] = '\0';
- locinfo->lconv->mon_thousands_sep[0] = '\0';
- locinfo->lconv->mon_grouping[0] = '\0';
- locinfo->lconv->positive_sign[0] = '\0';
- locinfo->lconv->negative_sign[0] = '\0';
- locinfo->lconv->int_frac_digits = charmax;
- locinfo->lconv->frac_digits = charmax;
- locinfo->lconv->p_cs_precedes = charmax;
- locinfo->lconv->p_sep_by_space = charmax;
- locinfo->lconv->n_cs_precedes = charmax;
- locinfo->lconv->n_sep_by_space = charmax;
- locinfo->lconv->p_sign_posn = charmax;
- locinfo->lconv->n_sign_posn = charmax;
+ if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
+ lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
+ locinfo->lconv->int_curr_symbol = "";
+ locinfo->lconv->currency_symbol = "";
+ locinfo->lconv->mon_decimal_point = "";
+ locinfo->lconv->mon_thousands_sep = "";
+ locinfo->lconv->mon_grouping = "";
+ locinfo->lconv->positive_sign = "";
+ locinfo->lconv->negative_sign = "";
+ locinfo->lconv->int_frac_digits = charmax;
+ locinfo->lconv->frac_digits = charmax;
+ locinfo->lconv->p_cs_precedes = charmax;
+ locinfo->lconv->p_sep_by_space = charmax;
+ locinfo->lconv->n_cs_precedes = charmax;
+ locinfo->lconv->n_sep_by_space = charmax;
+ locinfo->lconv->p_sign_posn = charmax;
+ locinfo->lconv->n_sign_posn = charmax;
#if _MSVCR_VER >= 100
- locinfo->lconv->_W_int_curr_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
- locinfo->lconv->_W_currency_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
- locinfo->lconv->_W_mon_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
- locinfo->lconv->_W_mon_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
- locinfo->lconv->_W_positive_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
- locinfo->lconv->_W_negative_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
-
- if(!locinfo->lconv->_W_int_curr_symbol || !locinfo->lconv->_W_currency_symbol
- || !locinfo->lconv->_W_mon_decimal_point || !locinfo->lconv->_W_mon_thousands_sep
- || !locinfo->lconv->positive_sign || !locinfo->lconv->negative_sign) {
- free_locinfo(locinfo);
- return NULL;
- }
-
- locinfo->lconv->_W_int_curr_symbol[0] = '\0';
- locinfo->lconv->_W_currency_symbol[0] = '\0';
- locinfo->lconv->_W_mon_decimal_point[0] = '\0';
- locinfo->lconv->_W_mon_thousands_sep[0] = '\0';
- locinfo->lconv->_W_positive_sign[0] = '\0';
- locinfo->lconv->_W_negative_sign[0] = '\0';
+ locinfo->lconv->_W_int_curr_symbol = emptyW;
+ locinfo->lconv->_W_currency_symbol = emptyW;
+ locinfo->lconv->_W_mon_decimal_point = emptyW;
+ locinfo->lconv->_W_mon_thousands_sep = emptyW;
+ locinfo->lconv->_W_positive_sign = emptyW;
+ locinfo->lconv->_W_negative_sign = emptyW;
#endif
+ }
if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) {
free_locinfo(locinfo);
@@ -1629,6 +1688,19 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC);
+ locinfo->lconv_num_refcount = old_locinfo->lconv_num_refcount;
+ if(locinfo->lconv_num_refcount)
+ InterlockedIncrement(locinfo->lconv_num_refcount);
+ if(category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
+ lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) {
+ locinfo->lconv->decimal_point = old_locinfo->lconv->decimal_point;
+ locinfo->lconv->thousands_sep = old_locinfo->lconv->thousands_sep;
+ locinfo->lconv->grouping = old_locinfo->lconv->grouping;
+#if _MSVCR_VER >= 100
+ locinfo->lconv->_W_decimal_point = old_locinfo->lconv->_W_decimal_point;
+ locinfo->lconv->_W_thousands_sep = old_locinfo->lconv->_W_thousands_sep;
+#endif
+ }
} else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC],
cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) {
@@ -1636,15 +1708,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
- if(!locinfo->lconv_intl_refcount)
- locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int));
locinfo->lconv_num_refcount = MSVCRT_malloc(sizeof(int));
- if(!locinfo->lconv_intl_refcount || !locinfo->lconv_num_refcount) {
+ if(!locinfo->lconv_num_refcount) {
free_locinfo(locinfo);
return NULL;
}
- *locinfo->lconv_intl_refcount = 1;
*locinfo->lconv_num_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SDECIMAL
@@ -1705,33 +1774,17 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
} else {
- locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2]));
- locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char));
- locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char));
- if(!locinfo->lconv->decimal_point || !locinfo->lconv->thousands_sep
- || !locinfo->lconv->grouping) {
- free_locinfo(locinfo);
- return NULL;
- }
-
- locinfo->lconv->decimal_point[0] = '.';
- locinfo->lconv->decimal_point[1] = '\0';
- locinfo->lconv->thousands_sep[0] = '\0';
- locinfo->lconv->grouping[0] = '\0';
+ if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
+ lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) {
+ locinfo->lconv->decimal_point = ".";
+ locinfo->lconv->thousands_sep = "";
+ locinfo->lconv->grouping = "";
#if _MSVCR_VER >= 100
- locinfo->lconv->_W_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t[2]));
- locinfo->lconv->_W_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t));
-
- if(!locinfo->lconv->_W_decimal_point || !locinfo->lconv->_W_thousands_sep) {
- free_locinfo(locinfo);
- return NULL;
- }
-
- locinfo->lconv->_W_decimal_point[0] = '.';
- locinfo->lconv->_W_decimal_point[1] = '\0';
- locinfo->lconv->_W_thousands_sep[0] = '\0';
+ locinfo->lconv->_W_decimal_point = cloc_dec_point;
+ locinfo->lconv->_W_thousands_sep = emptyW;
#endif
+ }
if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) {
free_locinfo(locinfo);
--
2.24.0
Jan. 31, 2020
[PATCH 3/8] msvcrt: Share ctype tables between threadlocinfo instances.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/msvcr90/tests/msvcr90.c | 16 +++++-----
dlls/msvcrt/locale.c | 59 +++++++++++++++++++++---------------
2 files changed, 42 insertions(+), 33 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index b030c113853f..4e28cafea0d8 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -2114,10 +2114,10 @@ static void test__get_current_locale(void)
l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
}
- ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
todo_wine {
- ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
@@ -2189,10 +2189,10 @@ static void test__get_current_locale(void)
l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
}
- ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
todo_wine {
- ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
@@ -2270,10 +2270,10 @@ static void test__get_current_locale(void)
l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
}
- ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
todo_wine {
- ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
@@ -2346,10 +2346,10 @@ static void test__get_current_locale(void)
l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
}
- ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
todo_wine {
- ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index b12559549a9c..aee39a0eafbe 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -55,6 +55,9 @@ BOOL initial_locale = TRUE;
#define MSVCRT_LEADBYTE 0x8000
#define MSVCRT_C1_DEFINED 0x200
+static char cloc_clmap[256];
+static char cloc_cumap[256];
+
static const MSVCRT_wchar_t sun[] = {'S','u','n',0};
static const MSVCRT_wchar_t mon[] = {'M','o','n',0};
static const MSVCRT_wchar_t tue[] = {'T','u','e',0};
@@ -163,6 +166,15 @@ static const char * const _country_synonyms[] =
"spanish-modern", "esn"
};
+static BOOL WINAPI init_cloc_casemap(PINIT_ONCE once, void *param, void **context)
+{
+ int i;
+ for(i=0; i<256; i++) {
+ cloc_clmap[i] = (i>='A' && i<='Z' ? i-'A'+'a' : i);
+ cloc_cumap[i] = (i>='a' && i<='z' ? i-'a'+'A' : i);
+ }
+}
+
/* INTERNAL: Map a synonym to an ISO code */
static void remap_synonym(char *name)
{
@@ -927,11 +939,11 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo)
MSVCRT_free(locinfo->lconv_mon_refcount);
MSVCRT_free(locinfo->lconv);
- MSVCRT_free(locinfo->ctype1_refcount);
- MSVCRT_free(locinfo->ctype1);
-
- MSVCRT_free(locinfo->pclmap);
- MSVCRT_free(locinfo->pcumap);
+ if(locinfo->ctype1_refcount
+ && !InterlockedDecrement(locinfo->ctype1_refcount)) {
+ MSVCRT_free(locinfo->ctype1_refcount);
+ MSVCRT_free(locinfo->ctype1);
+ }
if(locinfo->lc_time_curr != &cloc_time_data)
MSVCRT_free(locinfo->lc_time_curr);
@@ -1199,13 +1211,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
}
memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv));
- locinfo->pclmap = MSVCRT_malloc(sizeof(char[256]));
- locinfo->pcumap = MSVCRT_malloc(sizeof(char[256]));
- if(!locinfo->pclmap || !locinfo->pcumap) {
- free_locinfo(locinfo);
- return NULL;
- }
-
if(locale_name[MSVCRT_LC_COLLATE] &&
!init_category_name(locale_name[MSVCRT_LC_COLLATE],
locale_len[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) {
@@ -1246,6 +1251,16 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_CTYPE, category, old_locinfo,
lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE])) {
copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_CTYPE);
+ locinfo->lc_codepage = old_locinfo->lc_codepage;
+ locinfo->lc_clike = old_locinfo->lc_clike;
+ locinfo->mb_cur_max = old_locinfo->mb_cur_max;
+ locinfo->ctype1 = old_locinfo->ctype1;
+ locinfo->ctype1_refcount = old_locinfo->ctype1_refcount;
+ locinfo->pctype = old_locinfo->pctype;
+ locinfo->pclmap = old_locinfo->pclmap;
+ locinfo->pcumap = old_locinfo->pcumap;
+ if(locinfo->ctype1_refcount)
+ InterlockedIncrement(locinfo->ctype1_refcount);
} else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) {
CPINFO cp_info;
int j;
@@ -1266,7 +1281,9 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->ctype1_refcount = MSVCRT_malloc(sizeof(int));
locinfo->ctype1 = MSVCRT_malloc(sizeof(short[257]));
- if(!locinfo->ctype1_refcount || !locinfo->ctype1) {
+ locinfo->pclmap = MSVCRT_malloc(sizeof(char[256]));
+ locinfo->pcumap = MSVCRT_malloc(sizeof(char[256]));
+ if(!locinfo->ctype1_refcount || !locinfo->ctype1 || !locinfo->pclmap || !locinfo->pcumap) {
free_locinfo(locinfo);
return NULL;
}
@@ -1307,7 +1324,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, buf, 256,
(char*)locinfo->pcumap, 256);
} else {
- locinfo->lc_clike = 1;
+ static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
locinfo->mb_cur_max = 1;
locinfo->pctype = MSVCRT__ctype+1;
if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) {
@@ -1315,17 +1332,9 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
- for(i=0; i<256; i++) {
- if(locinfo->pctype[i] & MSVCRT__LEADBYTE)
- buf[i] = ' ';
- else
- buf[i] = i;
- }
-
- for(i=0; i<256; i++) {
- locinfo->pclmap[i] = (i>='A' && i<='Z' ? i-'A'+'a' : i);
- locinfo->pcumap[i] = (i>='a' && i<='z' ? i-'a'+'A' : i);
- }
+ InitOnceExecuteOnce(&once, init_cloc_casemap, NULL, NULL);
+ locinfo->pclmap = cloc_clmap;
+ locinfo->pcumap = cloc_cumap;
}
if(locale_name[MSVCRT_LC_MONETARY] &&
--
2.24.0
Jan. 31, 2020
[PATCH 2/8] msvcrt: Share locale names between threadlocinfo instances.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/msvcr90/tests/msvcr90.c | 64 +++++++++++++-----------------------
dlls/msvcrt/locale.c | 58 +++++++++++++++++++++++---------
2 files changed, 64 insertions(+), 58 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index f8e68ed2f630..b030c113853f 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -2024,15 +2024,11 @@ static void test__get_current_locale(void)
"same locale name pointers for LC_COLLATE\n");
ok(l->locinfo->lc_category[LC_COLLATE].refcount != l2->locinfo->lc_category[LC_COLLATE].refcount,
"same refcount pointers for LC_COLLATE\n");
- ok(l->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
- if(l->locinfo->lc_category[LC_COLLATE].refcount)
- ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n",
- *l->locinfo->lc_category[LC_COLLATE].refcount);
- ok(l2->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
- if(l2->locinfo->lc_category[LC_COLLATE].refcount)
- ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n",
- *l2->locinfo->lc_category[LC_COLLATE].refcount);
}
+ ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n",
+ *l->locinfo->lc_category[LC_COLLATE].refcount);
+ todo_wine ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n",
+ *l2->locinfo->lc_category[LC_COLLATE].refcount);
for(i = LC_CTYPE; i <= LC_MAX; i++) {
ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
"different locale name pointers for category %d\n", i);
@@ -2095,15 +2091,11 @@ static void test__get_current_locale(void)
"same locale name pointers for category %d\n", i);
ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
"same refcount pointers for category %d\n", i);
- ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l->locinfo->lc_category[i].refcount)
- ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
- *l->locinfo->lc_category[i].refcount, i);
- ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l2->locinfo->lc_category[i].refcount)
- ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
- *l2->locinfo->lc_category[i].refcount, i);
}
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
}
for(i = LC_MONETARY; i <= LC_MAX; i++) {
ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
@@ -2174,15 +2166,11 @@ static void test__get_current_locale(void)
"same locale name pointers for category %d\n", i);
ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
"same refcount pointers for category %d\n", i);
- ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l->locinfo->lc_category[i].refcount)
- ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
- *l->locinfo->lc_category[i].refcount, i);
- ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l2->locinfo->lc_category[i].refcount)
- ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
- *l2->locinfo->lc_category[i].refcount, i);
}
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
}
for(i = LC_NUMERIC; i <= LC_MAX; i++) {
ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
@@ -2261,15 +2249,11 @@ static void test__get_current_locale(void)
"same locale name pointers for category %d\n", i);
ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
"same refcount pointers for category %d\n", i);
- ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l->locinfo->lc_category[i].refcount)
- ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
- *l->locinfo->lc_category[i].refcount, i);
- ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l2->locinfo->lc_category[i].refcount)
- ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
- *l2->locinfo->lc_category[i].refcount, i);
}
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
}
ok(l->locinfo->lc_category[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale,
"different locale name pointers for LC_TIME\n");
@@ -2341,21 +2325,17 @@ static void test__get_current_locale(void)
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
}
- todo_wine {
- for(i = LC_MIN+1; i <= LC_MAX; i++) {
+ for(i = LC_MIN+1; i <= LC_MAX; i++) {
+ todo_wine {
ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
"same locale name pointers for category %d\n", i);
ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
"same refcount pointers for category %d\n", i);
- ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l->locinfo->lc_category[i].refcount)
- ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
- *l->locinfo->lc_category[i].refcount, i);
- ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
- if(l2->locinfo->lc_category[i].refcount)
- ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
- *l2->locinfo->lc_category[i].refcount, i);
}
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
}
todo_wine {
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index f6e7631b4f50..b12559549a9c 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -418,6 +418,18 @@ static BOOL init_category_name(const char *name, int len,
return TRUE;
}
+/* INTERNAL: Copy lc_handle, lc_id, and lc_category from one threadlocinfo to another */
+static void copy_threadlocinfo_category(MSVCRT_pthreadlocinfo locinfo, MSVCRT_pthreadlocinfo old_locinfo, int category)
+{
+ locinfo->lc_handle[category] = old_locinfo->lc_handle[category];
+ locinfo->lc_id[category] = old_locinfo->lc_id[category];
+ locinfo->lc_category[category] = old_locinfo->lc_category[category];
+#if _MSVCR_VER >= 110
+ locinfo->lc_name[category] = old_locinfo->lc_name[category];
+#endif
+ InterlockedIncrement(locinfo->lc_category[category].refcount);
+}
+
/* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */
static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp,
MSVCRT_pthreadlocinfo locinfo, int category)
@@ -878,6 +890,9 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo)
return;
for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) {
+ if(!locinfo->lc_category[i].refcount
+ || InterlockedDecrement(locinfo->lc_category[i].refcount))
+ continue;
MSVCRT_free(locinfo->lc_category[i].locale);
MSVCRT_free(locinfo->lc_category[i].refcount);
#if _MSVCR_VER >= 110
@@ -1200,8 +1215,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_COLLATE, category, old_locinfo,
lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE])) {
- locinfo->lc_handle[MSVCRT_LC_COLLATE] = old_locinfo->lc_handle[MSVCRT_LC_COLLATE];
- locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage;
+ copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_COLLATE);
} else if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE],
cp[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) {
@@ -1215,8 +1229,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
free_locinfo(locinfo);
return NULL;
}
- } else
- locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C");
+ } else {
+ if(!init_category_name("C", 1, locinfo, MSVCRT_LC_COLLATE)) {
+ free_locinfo(locinfo);
+ return NULL;
+ }
+ }
if(locale_name[MSVCRT_LC_CTYPE] &&
!init_category_name(locale_name[MSVCRT_LC_CTYPE],
@@ -1227,8 +1245,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_CTYPE, category, old_locinfo,
lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE])) {
- locinfo->lc_handle[MSVCRT_LC_CTYPE] = old_locinfo->lc_handle[MSVCRT_LC_CTYPE];
- locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+ copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_CTYPE);
} else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) {
CPINFO cp_info;
int j;
@@ -1293,7 +1310,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->lc_clike = 1;
locinfo->mb_cur_max = 1;
locinfo->pctype = MSVCRT__ctype+1;
- locinfo->lc_category[MSVCRT_LC_CTYPE].locale = MSVCRT__strdup("C");
+ if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) {
+ free_locinfo(locinfo);
+ return NULL;
+ }
for(i=0; i<256; i++) {
if(locinfo->pctype[i] & MSVCRT__LEADBYTE)
@@ -1317,8 +1337,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) {
- locinfo->lc_handle[MSVCRT_LC_MONETARY] = old_locinfo->lc_handle[MSVCRT_LC_MONETARY];
- locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage = old_locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage;
+ copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY);
} else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY],
cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) {
@@ -1585,7 +1604,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->lconv->_W_negative_sign[0] = '\0';
#endif
- locinfo->lc_category[MSVCRT_LC_MONETARY].locale = MSVCRT__strdup("C");
+ if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) {
+ free_locinfo(locinfo);
+ return NULL;
+ }
}
if(locale_name[MSVCRT_LC_NUMERIC] &&
@@ -1597,8 +1619,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
- locinfo->lc_handle[MSVCRT_LC_NUMERIC] = old_locinfo->lc_handle[MSVCRT_LC_NUMERIC];
- locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage = old_locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage;
+ copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC);
} else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC],
cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) {
@@ -1703,7 +1724,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->lconv->_W_thousands_sep[0] = '\0';
#endif
- locinfo->lc_category[MSVCRT_LC_NUMERIC].locale = MSVCRT__strdup("C");
+ if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) {
+ free_locinfo(locinfo);
+ return NULL;
+ }
}
if(locale_name[MSVCRT_LC_TIME] &&
@@ -1715,8 +1739,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_TIME, category, old_locinfo,
lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME])) {
- locinfo->lc_handle[MSVCRT_LC_TIME] = old_locinfo->lc_handle[MSVCRT_LC_TIME];
- locinfo->lc_id[MSVCRT_LC_TIME].wCodePage = old_locinfo->lc_id[MSVCRT_LC_TIME].wCodePage;
+ copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_TIME);
} else if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) {
if(!update_threadlocinfo_category(lcid[MSVCRT_LC_TIME],
cp[MSVCRT_LC_TIME], locinfo, MSVCRT_LC_TIME)) {
@@ -1735,7 +1758,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
return NULL;
}
} else {
- locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C");
+ if(!init_category_name("C", 1, locinfo, MSVCRT_LC_TIME)) {
+ free_locinfo(locinfo);
+ return NULL;
+ }
locinfo->lc_time_curr = &cloc_time_data;
}
--
2.24.0
Jan. 31, 2020
[PATCH 1/8] msvcr90/tests: Test _get_current_locale()/setlocale() interaction.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/msvcr90/tests/msvcr90.c | 460 +++++++++++++++++++++++++++++++++++
1 file changed, 460 insertions(+)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index c8a49f25492d..f8e68ed2f630 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -139,6 +139,22 @@ static int (__cdecl *p_swscanf)(const wchar_t *str, const wchar_t* format, ...);
static int (__cdecl *p____mb_cur_max_l_func)(_locale_t locale);
static _locale_t (__cdecl *p__create_locale)(int, const char*);
static void (__cdecl *p__free_locale)(_locale_t);
+static _locale_t (__cdecl *p__get_current_locale)(void);
+
+struct __lc_time_data {
+ const char *short_wday[7];
+ const char *wday[7];
+ const char *short_mon[12];
+ const char *mon[12];
+ const char *am;
+ const char *pm;
+ const char *short_date;
+ const char *date;
+ const char *time;
+ LCID lcid;
+ int unk;
+ int refcount;
+};
/* make sure we use the correct errno */
#undef errno
@@ -408,6 +424,7 @@ static BOOL init(void)
SET(p____mb_cur_max_l_func, "___mb_cur_max_l_func");
SET(p__create_locale, "_create_locale");
SET(p__free_locale, "_free_locale");
+ SET(p__get_current_locale, "_get_current_locale");
if (sizeof(void *) == 8)
{
@@ -1961,6 +1978,448 @@ static void test____mb_cur_max_l_func(void)
p__free_locale(l);
}
+static void test__get_current_locale(void)
+{
+ _locale_t l = p__get_current_locale(), l2 = p__get_current_locale();
+ int i;
+#define lc_str(lc, s) \
+ ok(!strcmp(l->locinfo->lc_category[lc].locale, s), #lc " = \"%s\"\n", \
+ l->locinfo->lc_category[lc].locale)
+ lc_str(LC_COLLATE, "C");
+ lc_str(LC_CTYPE, "C");
+ lc_str(LC_MONETARY, "C");
+ lc_str(LC_NUMERIC, "C");
+ lc_str(LC_TIME, "C");
+
+ ok(l->locinfo->refcount == 3, "refcount = %d\n", l->locinfo->refcount);
+
+ p_setlocale(LC_ALL, "english");
+ todo_wine {
+ lc_str(LC_COLLATE, "C");
+ lc_str(LC_CTYPE, "C");
+ lc_str(LC_MONETARY, "C");
+ lc_str(LC_NUMERIC, "C");
+ lc_str(LC_TIME, "C");
+ }
+#undef lc_str
+
+ todo_wine ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount);
+ ok(l->locinfo == l2->locinfo, "different locinfo pointers\n");
+ ok(l->mbcinfo == l2->mbcinfo, "different mbcinfo pointers\n");
+
+ p__free_locale(l);
+ p__free_locale(l2);
+
+ l = p__get_current_locale();
+ p_setlocale(LC_COLLATE, "C");
+ l2 = p__get_current_locale();
+
+ todo_wine {
+ ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
+ ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
+ }
+
+ todo_wine {
+ ok(l->locinfo->lc_category[LC_COLLATE].locale != l2->locinfo->lc_category[LC_COLLATE].locale,
+ "same locale name pointers for LC_COLLATE\n");
+ ok(l->locinfo->lc_category[LC_COLLATE].refcount != l2->locinfo->lc_category[LC_COLLATE].refcount,
+ "same refcount pointers for LC_COLLATE\n");
+ ok(l->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
+ if(l->locinfo->lc_category[LC_COLLATE].refcount)
+ ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n",
+ *l->locinfo->lc_category[LC_COLLATE].refcount);
+ ok(l2->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
+ if(l2->locinfo->lc_category[LC_COLLATE].refcount)
+ ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n",
+ *l2->locinfo->lc_category[LC_COLLATE].refcount);
+ }
+ for(i = LC_CTYPE; i <= LC_MAX; i++) {
+ ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
+ "different locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
+ "different refcount pointers for category %d\n", i);
+ todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ }
+
+ todo_wine ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
+ l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
+
+ ok(l->locinfo->lc_codepage == l2->locinfo->lc_codepage, "different lc_codepages %u, %u\n",
+ l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
+ ok(l->locinfo->lc_clike == l2->locinfo->lc_clike, "different lc_clike values %d, %d\n",
+ l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ /* The meaning of this member seems to be reversed--go figure */
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ ok(l->locinfo->ctype1 == l2->locinfo->ctype1, "different ctype1 pointers\n");
+ ok(l->locinfo->pclmap == l2->locinfo->pclmap, "different clmap pointers\n");
+ ok(l->locinfo->pcumap == l2->locinfo->pcumap, "different cumap pointers\n");
+ ok(l->locinfo->ctype1_refcount == l2->locinfo->ctype1_refcount, "different ctype1_refcount pointers\n");
+ todo_wine ok(*l->locinfo->ctype1_refcount == 3, "refcount = %d\n", *l->locinfo->ctype1_refcount);
+
+ ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n");
+ ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_intl_refcount)
+ todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
+
+ ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
+ ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_num_refcount)
+ todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
+
+ ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n");
+ ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_mon_refcount)
+ todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
+
+ ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
+ todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
+ todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
+
+ p__free_locale(l2);
+
+ p_setlocale(LC_CTYPE, "C");
+ l2 = p__get_current_locale();
+
+ todo_wine {
+ ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
+ ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
+ }
+
+ for(i = LC_COLLATE; i < LC_MONETARY; i++) {
+ todo_wine {
+ ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
+ "same locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
+ "same refcount pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l->locinfo->lc_category[i].refcount)
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l2->locinfo->lc_category[i].refcount)
+ ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
+ }
+ }
+ for(i = LC_MONETARY; i <= LC_MAX; i++) {
+ ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
+ "different locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
+ "different refcount pointers for category %d\n", i);
+ todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ }
+
+ todo_wine {
+ ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
+ l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
+
+ ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
+ l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
+ ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
+ l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ }
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ todo_wine {
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
+ ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
+ ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
+ ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
+ ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
+ ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
+ if(l->locinfo->ctype1_refcount)
+ ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
+ }
+ ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
+
+ ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n");
+ ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_intl_refcount)
+ todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
+
+ ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
+ ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_num_refcount)
+ todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
+
+ ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n");
+ ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_mon_refcount)
+ todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
+
+ ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
+ todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
+ todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
+
+ p__free_locale(l2);
+
+ p_setlocale(LC_MONETARY, "C");
+ l2 = p__get_current_locale();
+
+ todo_wine {
+ ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
+ ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
+ }
+
+ for(i = LC_COLLATE; i <= LC_MONETARY; i++) {
+ todo_wine {
+ ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
+ "same locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
+ "same refcount pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l->locinfo->lc_category[i].refcount)
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l2->locinfo->lc_category[i].refcount)
+ ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
+ }
+ }
+ for(i = LC_NUMERIC; i <= LC_MAX; i++) {
+ ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
+ "different locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
+ "different refcount pointers for category %d\n", i);
+ todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ }
+
+ todo_wine {
+ ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
+ l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
+
+ ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
+ l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
+ ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
+ l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ }
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ todo_wine {
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
+ ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
+ ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
+ ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
+ ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
+ ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
+ if(l->locinfo->ctype1_refcount)
+ ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
+ }
+ ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
+ ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
+ ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_intl_refcount)
+ ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
+ ok(l2->locinfo->lconv_intl_refcount, "null refcount pointer for C locale\n");
+ if(l2->locinfo->lconv_intl_refcount)
+ ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount);
+ }
+
+ ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
+ ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
+ todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_num_refcount)
+ todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
+
+ todo_wine {
+ ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
+ ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
+ ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_mon_refcount)
+ ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
+ }
+ ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
+
+ ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
+ todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
+ todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
+
+ p__free_locale(l2);
+
+ p_setlocale(LC_NUMERIC, "C");
+ l2 = p__get_current_locale();
+
+ todo_wine {
+ ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
+ ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
+ }
+
+ for(i = LC_COLLATE; i <= LC_NUMERIC; i++) {
+ todo_wine {
+ ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
+ "same locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
+ "same refcount pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l->locinfo->lc_category[i].refcount)
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l2->locinfo->lc_category[i].refcount)
+ ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
+ }
+ }
+ ok(l->locinfo->lc_category[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale,
+ "different locale name pointers for LC_TIME\n");
+ ok(l->locinfo->lc_category[LC_TIME].refcount == l2->locinfo->lc_category[LC_TIME].refcount,
+ "different refcount pointers for LC_TIME\n");
+ todo_wine ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n",
+ *l->locinfo->lc_category[LC_TIME].refcount);
+
+ todo_wine {
+ ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
+ l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
+
+ ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
+ l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
+ ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
+ l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ }
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ todo_wine {
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
+ ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
+ ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
+ ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
+ ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
+ ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
+ if(l->locinfo->ctype1_refcount)
+ ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
+ }
+ ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
+ ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
+ ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_intl_refcount)
+ ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
+ }
+ ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n");
+ ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n");
+ ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_num_refcount)
+ ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
+ }
+ ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
+ ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
+ ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_mon_refcount)
+ ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
+ }
+ ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
+
+ ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
+ todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
+ todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
+
+ p__free_locale(l2);
+
+ p_setlocale(LC_TIME, "C");
+ l2 = p__get_current_locale();
+
+ todo_wine {
+ ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
+ ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
+ }
+
+ todo_wine {
+ for(i = LC_MIN+1; i <= LC_MAX; i++) {
+ ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
+ "same locale name pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
+ "same refcount pointers for category %d\n", i);
+ ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l->locinfo->lc_category[i].refcount)
+ ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+ *l->locinfo->lc_category[i].refcount, i);
+ ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
+ if(l2->locinfo->lc_category[i].refcount)
+ ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+ *l2->locinfo->lc_category[i].refcount, i);
+ }
+ }
+
+ todo_wine {
+ ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
+ l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
+
+ ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
+ l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
+ ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n",
+ l->locinfo->lc_clike, l2->locinfo->lc_clike);
+ }
+ ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
+ todo_wine {
+ ok(!l2->locinfo->lc_clike, "C locale is not C-like\n");
+ ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n");
+ ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n");
+ ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n");
+ ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
+ ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
+ if(l->locinfo->ctype1_refcount)
+ ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
+ }
+ ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
+ ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
+ ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_intl_refcount)
+ ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
+ }
+ ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n");
+ ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n");
+ ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_num_refcount)
+ ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
+ }
+ ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine {
+ ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
+ ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
+ ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
+ if(l->locinfo->lconv_mon_refcount)
+ ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
+ }
+ ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
+
+ todo_wine ok(l->locinfo->lc_time_curr != l2->locinfo->lc_time_curr, "same lc_time_curr pointers\n");
+ ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
+ todo_wine ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
+ ok(l2->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l2->locinfo->lc_time_curr->unk);
+ todo_wine ok(l2->locinfo->lc_time_curr->refcount == 3 || l2->locinfo->lc_time_curr->refcount == 2,
+ "refcount = %d\n", l2->locinfo->lc_time_curr->refcount);
+
+ p__free_locale(l2);
+
+ p__free_locale(l);
+ p_setlocale(LC_ALL, "C");
+}
+
START_TEST(msvcr90)
{
if(!init())
@@ -2001,4 +2460,5 @@ START_TEST(msvcr90)
test___strncnt();
test_swscanf();
test____mb_cur_max_l_func();
+ test__get_current_locale();
}
--
2.24.0
Jan. 31, 2020
Re: [PATCH 3/3] mscms: Add stub for WcsGetDefaultRenderingIntent
by Hans Leidekker
On Fri, 2020-01-31 at 02:11 +0100, Vijay Kiran Kamuju wrote:
> +/******************************************************************************
> + * WcsGetDefaultColorProfileSize [MSCMS.@]
> + */
> +BOOL WINAPI WcsGetDefaultRenderingIntent( WCS_PROFILE_MANAGEMENT_SCOPE scope, PDWORD intent)
Typo.
Jan. 31, 2020
Re: [PATCH 2/3] mscms: Add stub for WcsGetDefaultColorProfileSize
by Hans Leidekker
On Fri, 2020-01-31 at 02:10 +0100, Vijay Kiran Kamuju wrote:
> +/******************************************************************************
> + * WcsGetDefaultColorProfileSize [MSCMS.@]
> + */
> +BOOL WINAPI WcsGetDefaultColorProfileSize( WCS_PROFILE_MANAGEMENT_SCOPE scope, PCWSTR device_name,
> + COLORPROFILETYPE type, COLORPROFILESUBTYPE subtype,
> + DWORD profile_id, PDWORD profile_name)
> +{
profile_size would be better name for the last parameter.
Jan. 31, 2020
Re: [PATCH 1/3] include: add missing defines to icm.h
by Hans Leidekker
On Fri, 2020-01-31 at 02:09 +0100, Vijay Kiran Kamuju wrote:
> + BM_R10G10B10A2 = 0x0701,
> + BM_R10G10B10A2_XR,
> + BM_R10G10B10A2_FLOAT
That should be BM_R16G16B16A16_FLOAT.
> +#define DONT_USE_EMBEDDED_WCS_PROFILES 0x00000001
> +
> +#define PROOF_MODE 0x00000001
> +#define NORMAL_MODE 0x00000002
> +#define BEST_MODE 0x00000004
BEST_MODE is 3 in the SDK.
> +typedef enum
> +{
> + CPST_PERCEPTUAL = INTENT_PERCEPTUAL,
> + CPST_RELATIVE_COLORIMETRIC = INTENT_RELATIVE_COLORIMETRIC,
> + CPST_SATURATION = INTENT_SATURATION,
> + CPST_ABSOLUTE_COLORIMETRIC = INTENT_ABSOLUTE_COLORIMETRIC,
> + CPST_NONE,
> + CPST_RGB_WORKING_SPACE,
> + CPST_CUSTOM_WORKING_SPACE,
> + CPST_STANDARD_DISPLAY_COLOR_SPACE,
> + CPST_EXTENDED_DISPLAY_COLOR_SPACE
CPST_STANDARD_DISPLAY_COLOR_MODE and CPST_EXTENDED_DISPLAY_COLOR_MODE.
Jan. 31, 2020
Re: [PATCH v6 2/2] include: Add xact3.idl
by Alexandre Julliard
Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com> writes:
> +typedef struct XACT_RENDERER_DETAILS
> +{
> + WCHAR rendererID[0xFF];
> + WCHAR displayName[0xFF];
Please use the appropriate constants, here and in similar places.
--
Alexandre Julliard
julliard(a)winehq.org
Jan. 31, 2020
[PATCH 2/2] gdiplus: Create FontFamily objects only once for the FontCollection.
by Dmitry Timoshkov
.Net 4.7+ depends on this behaviour and expects to be able to do pointer
equality tests for FontFamily objects.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/gdiplus/font.c | 208 ++++++++++++++++----------------------
dlls/gdiplus/tests/font.c | 6 --
2 files changed, 89 insertions(+), 125 deletions(-)
diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index eee272082f..a7719a9458 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -115,8 +115,6 @@ typedef struct
#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
-static GpStatus clone_font_family(const GpFontFamily *, GpFontFamily **);
-
static GpFontCollection installedFontCollection = {0};
/*******************************************************************************
@@ -183,13 +181,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
(*font)->unit = unit;
(*font)->emSize = emSize;
(*font)->otm = otm;
-
- stat = clone_font_family(fontFamily, &(*font)->family);
- if (stat != Ok)
- {
- heap_free(*font);
- return stat;
- }
+ (*font)->family = (GpFontFamily *)fontFamily;
TRACE("<-- %p\n", *font);
@@ -322,7 +314,8 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
if (!(font && family))
return InvalidParameter;
- return GdipCloneFontFamily(font->family, family);
+ *family = font->family;
+ return Ok;
}
static REAL get_font_size(const GpFont *font)
@@ -518,8 +511,6 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
*/
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
{
- GpStatus stat;
-
TRACE("(%p, %p)\n", font, cloneFont);
if(!font || !cloneFont)
@@ -529,10 +520,7 @@ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
if(!*cloneFont) return OutOfMemory;
**cloneFont = *font;
- stat = GdipCloneFontFamily(font->family, &(*cloneFont)->family);
- if (stat != Ok) heap_free(*cloneFont);
-
- return stat;
+ return Ok;
}
/*******************************************************************************
@@ -699,29 +687,6 @@ static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
return TRUE;
}
-static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
-{
- LOGFONTW lf;
- HDC hdc = CreateCompatibleDC(0);
- GpStatus ret = FontFamilyNotFound;
-
- if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
- {
- HFONT hfont, old_font;
-
- lstrcpyW(fm->facename, lf.lfFaceName);
-
- hfont = CreateFontIndirectW(&lf);
- old_font = SelectObject(hdc, hfont);
- ret = get_font_metrics(hdc, fm) ? Ok : NotTrueTypeFont;
- SelectObject(hdc, old_font);
- DeleteObject(hfont);
- }
-
- DeleteDC(hdc);
- return ret;
-}
-
/*******************************************************************************
* GdipCreateFontFamilyFromName [GDIPLUS.@]
*
@@ -743,48 +708,45 @@ static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
*/
GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
- GpFontCollection *fontCollection,
- GpFontFamily **FontFamily)
+ GpFontCollection *collection,
+ GpFontFamily **family)
{
- GpStatus stat;
- GpFontFamily* ffamily;
- struct font_metrics fm;
+ HDC hdc;
+ LOGFONTW lf;
+ GpStatus status;
+ int i;
- TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
+ TRACE("%s, %p %p\n", debugstr_w(name), collection, family);
- if (!(name && FontFamily))
+ if (!name || !family)
return InvalidParameter;
- if (fontCollection)
- FIXME("No support for FontCollections yet!\n");
-
- stat = find_installed_font(name, &fm);
- if (stat != Ok) return stat;
-
- ffamily = heap_alloc_zero(sizeof (GpFontFamily));
- if (!ffamily) return OutOfMemory;
-
- lstrcpyW(ffamily->FamilyName, fm.facename);
- ffamily->em_height = fm.em_height;
- ffamily->ascent = fm.ascent;
- ffamily->descent = fm.descent;
- ffamily->line_spacing = fm.line_spacing;
- ffamily->dpi = fm.dpi;
- *FontFamily = ffamily;
-
- TRACE("<-- %p\n", ffamily);
+ if (!collection)
+ {
+ status = GdipNewInstalledFontCollection(&collection);
+ if (status != Ok) return status;
+ }
- return Ok;
-}
+ status = FontFamilyNotFound;
-static GpStatus clone_font_family(const GpFontFamily *family, GpFontFamily **clone)
-{
- *clone = heap_alloc_zero(sizeof(GpFontFamily));
- if (!*clone) return OutOfMemory;
+ hdc = CreateCompatibleDC(0);
- **clone = *family;
+ if (!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
+ {
+ for (i = 0; i < collection->count; i++)
+ {
+ if (!wcsicmp(lf.lfFaceName, collection->FontFamilies[i]->FamilyName))
+ {
+ *family = collection->FontFamilies[i];
+ TRACE("<-- %p\n", *family);
+ status = Ok;
+ break;
+ }
+ }
+ }
- return Ok;
+ DeleteDC(hdc);
+ return status;
}
/*******************************************************************************
@@ -799,20 +761,14 @@ static GpStatus clone_font_family(const GpFontFamily *family, GpFontFamily **clo
* RETURNS
* SUCCESS: Ok
*/
-GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily)
+GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily *family, GpFontFamily **clone)
{
- GpStatus status;
-
- if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
-
- TRACE("%p (%s), %p\n", FontFamily,
- debugstr_w(FontFamily->FamilyName), clonedFontFamily);
-
- status = clone_font_family(FontFamily, clonedFontFamily);
- if (status != Ok) return status;
+ if (!family || !clone)
+ return InvalidParameter;
- TRACE("<-- %p\n", *clonedFontFamily);
+ TRACE("%p (%s), %p\n", family, debugstr_w(family->FamilyName), clone);
+ *clone = family;
return Ok;
}
@@ -869,9 +825,6 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily)
{
if (!FontFamily)
return InvalidParameter;
- TRACE("Deleting %p (%s)\n", FontFamily, debugstr_w(FontFamily->FamilyName));
-
- heap_free (FontFamily);
return Ok;
}
@@ -1498,6 +1451,7 @@ struct add_font_param
GpFontCollection *collection;
BOOL is_system;
GpStatus stat;
+ HDC hdc;
};
static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam);
@@ -1528,10 +1482,9 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
else
{
struct add_font_param param;
- HDC hdc;
LOGFONTW lfw;
- hdc = CreateCompatibleDC(0);
+ param.hdc = CreateCompatibleDC(0);
/* Truncate name if necessary, GDI32 can't deal with long names */
if(lstrlenW(name) > LF_FACESIZE - 1)
@@ -1543,10 +1496,10 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
param.collection = fontCollection;
param.is_system = FALSE;
- if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
+ if (!EnumFontFamiliesExW(param.hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
ret = param.stat;
- DeleteDC(hdc);
+ DeleteDC(param.hdc);
}
heap_free(name);
return ret;
@@ -1575,7 +1528,6 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
GpFontFamily* gpfamilies[], INT* numFound)
{
INT i;
- GpStatus stat=Ok;
TRACE("%p, %d, %p, %p\n", fontCollection, numSought, gpfamilies, numFound);
@@ -1584,31 +1536,24 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
memset(gpfamilies, 0, sizeof(*gpfamilies) * numSought);
- for (i = 0; i < numSought && i < fontCollection->count && stat == Ok; i++)
+ for (i = 0; i < numSought && i < fontCollection->count; i++)
{
- stat = GdipCloneFontFamily(fontCollection->FontFamilies[i], &gpfamilies[i]);
+ gpfamilies[i] = fontCollection->FontFamilies[i];
}
- if (stat == Ok)
- *numFound = i;
- else
- {
- int numToFree=i;
- for (i=0; i<numToFree; i++)
- {
- GdipDeleteFontFamily(gpfamilies[i]);
- gpfamilies[i] = NULL;
- }
- }
+ *numFound = i;
- return stat;
+ return Ok;
}
void free_installed_fonts(void)
{
- while (installedFontCollection.count)
- GdipDeleteFontFamily(installedFontCollection.FontFamilies[--installedFontCollection.count]);
+ INT i;
+
+ for (i = 0; i < installedFontCollection.count; i++)
+ heap_free(installedFontCollection.FontFamilies[i]);
heap_free(installedFontCollection.FontFamilies);
+
installedFontCollection.FontFamilies = NULL;
installedFontCollection.allocated = 0;
}
@@ -1618,8 +1563,9 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
{
struct add_font_param *param = (struct add_font_param *)lParam;
GpFontCollection *fonts = param->collection;
- GpFontFamily* family;
- GpStatus stat;
+ GpFontFamily *family;
+ HFONT hfont, old_hfont;
+ struct font_metrics fm;
int i;
param->stat = Ok;
@@ -1651,25 +1597,50 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
fonts->allocated = new_alloc_count;
}
- if ((stat = GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &family)) != Ok)
+ family = heap_alloc(sizeof(*family));
+ if (!family)
{
- WARN("Failed to create font family for %s, status %d.\n", debugstr_w(lfw->lfFaceName), stat);
if (param->is_system)
return 1;
- param->stat = stat;
+
+ param->stat = OutOfMemory;
return 0;
}
/* skip duplicates */
for (i=0; i<fonts->count; i++)
{
- if (wcsicmp(family->FamilyName, fonts->FontFamilies[i]->FamilyName) == 0)
+ if (wcsicmp(lfw->lfFaceName, fonts->FontFamilies[i]->FamilyName) == 0)
{
- GdipDeleteFontFamily(family);
+ heap_free(family);
return 1;
}
}
+ hfont = CreateFontIndirectW(lfw);
+ old_hfont = SelectObject(param->hdc, hfont);
+
+ if (!get_font_metrics(param->hdc, &fm))
+ {
+ SelectObject(param->hdc, old_hfont);
+ DeleteObject(hfont);
+
+ heap_free(family);
+ param->stat = OutOfMemory;
+ return 0;
+ }
+
+ SelectObject(param->hdc, old_hfont);
+ DeleteObject(hfont);
+
+ family->em_height = fm.em_height;
+ family->ascent = fm.ascent;
+ family->descent = fm.descent;
+ family->line_spacing = fm.line_spacing;
+ family->dpi = fm.dpi;
+
+ lstrcpyW(family->FamilyName, lfw->lfFaceName);
+
fonts->FontFamilies[fonts->count++] = family;
return 1;
@@ -1686,10 +1657,9 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
if (installedFontCollection.count == 0)
{
struct add_font_param param;
- HDC hdc;
LOGFONTW lfw;
- hdc = CreateCompatibleDC(0);
+ param.hdc = CreateCompatibleDC(0);
lfw.lfCharSet = DEFAULT_CHARSET;
lfw.lfFaceName[0] = 0;
@@ -1697,14 +1667,14 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
param.collection = &installedFontCollection;
param.is_system = TRUE;
- if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
+ if (!EnumFontFamiliesExW(param.hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
{
free_installed_fonts();
- DeleteDC(hdc);
+ DeleteDC(param.hdc);
return param.stat;
}
- DeleteDC(hdc);
+ DeleteDC(param.hdc);
}
*fontCollection = &installedFontCollection;
diff --git a/dlls/gdiplus/tests/font.c b/dlls/gdiplus/tests/font.c
index 36079fa7ad..9abb80faaf 100644
--- a/dlls/gdiplus/tests/font.c
+++ b/dlls/gdiplus/tests/font.c
@@ -141,7 +141,6 @@ static void test_createfont(void)
expect(Ok, stat);
stat = GdipGetFamilyName(fontfamily2, familyname, 0);
expect(Ok, stat);
-todo_wine
ok (fontfamily == fontfamily2, "Unexpected family instance.\n");
ok (lstrcmpiW(Tahoma, familyname) == 0, "Expected Tahoma, got %s\n",
wine_dbgstr_w(familyname));
@@ -345,7 +344,6 @@ static void test_fontfamily (void)
ZeroMemory (itsName, sizeof(itsName));
stat = GdipCloneFontFamily(family, &clonedFontFamily);
expect (Ok, stat);
-todo_wine
ok (family == clonedFontFamily, "Unexpected family instance.\n");
GdipDeleteFontFamily(family);
stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
@@ -1238,7 +1236,6 @@ static void test_GdipGetFontCollectionFamilyList(void)
status = GdipGetFontCollectionFamilyList(collection, 1, &family2, &found);
ok(status == Ok, "Failed to get family list, status %d.\n", status);
ok(found == 1, "Unexpected list count %d.\n", found);
-todo_wine
ok(family2 == family, "Unexpected family instance.\n");
status = GdipDeleteFontFamily(family);
@@ -1338,7 +1335,6 @@ static void test_CloneFont(void)
expect(Ok, status);
ret = is_family_in_collection(collection, family);
-todo_wine
ok(ret, "family is not in collection\n");
status = GdipCreateFont(family, 30.0f, FontStyleRegular, UnitPixel, &font);
@@ -1358,7 +1354,6 @@ todo_wine
status = GdipGetFamily(font, &family2);
expect(Ok, status);
-todo_wine
ok(family == family2, "got %p\n", family2);
status = GdipCloneFont(font, &font2);
@@ -1378,7 +1373,6 @@ todo_wine
status = GdipGetFamily(font2, &family2);
expect(Ok, status);
-todo_wine
ok(family == family2, "got %p\n", family2);
GdipDeleteFont(font2);
--
2.20.1
Jan. 31, 2020
[PATCH 1/2] gdiplus/tests: Add tests for FontFamily object management.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/gdiplus/tests/font.c | 105 ++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/dlls/gdiplus/tests/font.c b/dlls/gdiplus/tests/font.c
index 33b75c5bc5..36079fa7ad 100644
--- a/dlls/gdiplus/tests/font.c
+++ b/dlls/gdiplus/tests/font.c
@@ -1282,6 +1282,110 @@ static void test_GdipGetFontCollectionFamilyCount(void)
ok(status == InvalidParameter, "Unexpected status %d.\n", status);
}
+static BOOL is_family_in_collection(GpFontCollection *collection, GpFontFamily *family)
+{
+ GpStatus status;
+ GpFontFamily **list;
+ int count, i;
+ BOOL found = FALSE;
+
+ status = GdipGetFontCollectionFamilyCount(collection, &count);
+ expect(Ok, status);
+
+ list = GdipAlloc(count * sizeof(GpFontFamily *));
+ status = GdipGetFontCollectionFamilyList(collection, count, list, &count);
+ expect(Ok, status);
+
+ for (i = 0; i < count; i++)
+ {
+ if (list[i] == family)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ GdipFree(list);
+
+ return found;
+}
+
+static void test_CloneFont(void)
+{
+ GpStatus status;
+ GpFontCollection *collection, *collection2;
+ GpFont *font, *font2;
+ GpFontFamily *family, *family2;
+ REAL height;
+ Unit unit;
+ int style;
+ BOOL ret;
+
+ status = GdipNewInstalledFontCollection(&collection);
+ expect(Ok, status);
+
+ status = GdipNewInstalledFontCollection(&collection2);
+ expect(Ok, status);
+ ok(collection == collection2, "got %p\n", collection2);
+
+ status = GdipCreateFontFamilyFromName(nonexistent, NULL, &family);
+ expect(FontFamilyNotFound, status);
+
+ status = GdipCreateFontFamilyFromName(nonexistent, collection, &family);
+ expect(FontFamilyNotFound, status);
+
+ status = GdipCreateFontFamilyFromName(Tahoma, NULL, &family);
+ expect(Ok, status);
+
+ ret = is_family_in_collection(collection, family);
+todo_wine
+ ok(ret, "family is not in collection\n");
+
+ status = GdipCreateFont(family, 30.0f, FontStyleRegular, UnitPixel, &font);
+ expect(Ok, status);
+
+ status = GdipGetFontUnit(font, &unit);
+ expect(Ok, status);
+ ok(unit == UnitPixel, "got %u\n", unit);
+
+ status = GdipGetFontSize(font, &height);
+ expect(Ok, status);
+ ok(height == 30.0f, "got %f\n", height);
+
+ status = GdipGetFontStyle(font, &style);
+ expect(Ok, status);
+ ok(style == FontStyleRegular, "got %d\n", style);
+
+ status = GdipGetFamily(font, &family2);
+ expect(Ok, status);
+todo_wine
+ ok(family == family2, "got %p\n", family2);
+
+ status = GdipCloneFont(font, &font2);
+ expect(Ok, status);
+
+ status = GdipGetFontUnit(font2, &unit);
+ expect(Ok, status);
+ ok(unit == UnitPixel, "got %u\n", unit);
+
+ status = GdipGetFontSize(font2, &height);
+ expect(Ok, status);
+ ok(height == 30.0f, "got %f\n", height);
+
+ status = GdipGetFontStyle(font2, &style);
+ expect(Ok, status);
+ ok(style == FontStyleRegular, "got %d\n", style);
+
+ status = GdipGetFamily(font2, &family2);
+ expect(Ok, status);
+todo_wine
+ ok(family == family2, "got %p\n", family2);
+
+ GdipDeleteFont(font2);
+ GdipDeleteFont(font);
+ GdipDeleteFontFamily(family);
+}
+
START_TEST(font)
{
struct GdiplusStartupInput gdiplusStartupInput;
@@ -1301,6 +1405,7 @@ START_TEST(font)
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
+ test_CloneFont();
test_long_name();
test_font_transform();
test_font_substitution();
--
2.20.1
Jan. 31, 2020