reactos/dll/win32/uxtheme/msstyles.c

1185 lines
36 KiB
C
Raw Normal View History

/*
* Win32 5.1 msstyles theme format
*
* Copyright (C) 2003 Kevin Koltzau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "uxthemep.h"
#include <wine/unicode.h>
/***********************************************************************
* Defines and global variables
*/
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
extern int alphaBlendMode;
#define MSSTYLES_VERSION 0x0003
static const WCHAR szThemesIniResource[] = {
't','h','e','m','e','s','_','i','n','i','\0'
};
/***********************************************************************/
/**********************************************************************
* MSSTYLES_OpenThemeFile
*
* Load and validate a theme
*
* PARAMS
* lpThemeFile Path to theme file to load
* pszColorName Color name wanted, can be NULL
* pszSizeName Size name wanted, can be NULL
*
* NOTES
* If pszColorName or pszSizeName are NULL, the default color/size will be used.
* If one/both are provided, they are validated against valid color/sizes and if
* a match is not found, the function fails.
*/
HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf)
{
HMODULE hTheme;
HRSRC hrsc;
HRESULT hr = S_OK;
static const WCHAR szPackThemVersionResource[] = {
'P','A','C','K','T','H','E','M','_','V','E','R','S','I','O','N', '\0'
};
static const WCHAR szColorNamesResource[] = {
'C','O','L','O','R','N','A','M','E','S','\0'
};
static const WCHAR szSizeNamesResource[] = {
'S','I','Z','E','N','A','M','E','S','\0'
};
WORD version;
DWORD versize;
LPWSTR pszColors;
LPWSTR pszSelectedColor = NULL;
LPWSTR pszSizes;
LPWSTR pszSelectedSize = NULL;
LPWSTR tmp;
TRACE("Opening %s\n", debugstr_w(lpThemeFile));
hTheme = LoadLibraryExW(lpThemeFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
/* Validate that this is really a theme */
if(!hTheme) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto invalid_theme;
}
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szPackThemVersionResource))) {
TRACE("No version resource found\n");
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto invalid_theme;
}
if((versize = SizeofResource(hTheme, hrsc)) != 2)
{
TRACE("Version resource found, but wrong size: %d\n", versize);
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto invalid_theme;
}
version = *(WORD*)LoadResource(hTheme, hrsc);
if(version != MSSTYLES_VERSION)
{
TRACE("Version of theme file is unsupported: 0x%04x\n", version);
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto invalid_theme;
}
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szColorNamesResource))) {
TRACE("Color names resource not found\n");
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto invalid_theme;
}
pszColors = LoadResource(hTheme, hrsc);
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szSizeNamesResource))) {
TRACE("Size names resource not found\n");
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto invalid_theme;
}
pszSizes = LoadResource(hTheme, hrsc);
/* Validate requested color against what's available from the theme */
if(pszColorName) {
tmp = pszColors;
while(*tmp) {
if(!lstrcmpiW(pszColorName, tmp)) {
pszSelectedColor = tmp;
break;
}
tmp += lstrlenW(tmp)+1;
}
}
else
pszSelectedColor = pszColors; /* Use the default color */
/* Validate requested size against what's available from the theme */
if(pszSizeName) {
tmp = pszSizes;
while(*tmp) {
if(!lstrcmpiW(pszSizeName, tmp)) {
pszSelectedSize = tmp;
break;
}
tmp += lstrlenW(tmp)+1;
}
}
else
pszSelectedSize = pszSizes; /* Use the default size */
if(!pszSelectedColor || !pszSelectedSize) {
TRACE("Requested color/size (%s/%s) not found in theme\n",
debugstr_w(pszColorName), debugstr_w(pszSizeName));
hr = E_PROP_ID_UNSUPPORTED;
goto invalid_theme;
}
*tf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THEME_FILE));
(*tf)->hTheme = hTheme;
GetFullPathNameW(lpThemeFile, MAX_PATH, (*tf)->szThemeFile, NULL);
(*tf)->pszAvailColors = pszColors;
(*tf)->pszAvailSizes = pszSizes;
(*tf)->pszSelectedColor = pszSelectedColor;
(*tf)->pszSelectedSize = pszSelectedSize;
(*tf)->dwRefCount = 1;
TRACE("Theme %p refcount: %d\n", *tf, (*tf)->dwRefCount);
return S_OK;
invalid_theme:
if(hTheme) FreeLibrary(hTheme);
return hr;
}
/***********************************************************************
* MSSTYLES_CloseThemeFile
*
* Close theme file and free resources
*/
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
{
if(tf) {
tf->dwRefCount--;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
if(!tf->dwRefCount) {
if(tf->hTheme) FreeLibrary(tf->hTheme);
if(tf->classes) {
while(tf->classes) {
PTHEME_CLASS pcls = tf->classes;
tf->classes = pcls->next;
while(pcls->partstate) {
PTHEME_PARTSTATE ps = pcls->partstate;
while(ps->properties) {
PTHEME_PROPERTY prop = ps->properties;
ps->properties = prop->next;
HeapFree(GetProcessHeap(), 0, prop);
}
pcls->partstate = ps->next;
HeapFree(GetProcessHeap(), 0, ps);
}
HeapFree(GetProcessHeap(), 0, pcls);
}
}
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
while (tf->images)
{
PTHEME_IMAGE img = tf->images;
tf->images = img->next;
DeleteObject (img->image);
HeapFree (GetProcessHeap(), 0, img);
}
HeapFree(GetProcessHeap(), 0, tf);
}
}
}
/***********************************************************************
* MSSTYLES_ReferenceTheme
*
* Increase the reference count of the theme file
*/
HRESULT MSSTYLES_ReferenceTheme(PTHEME_FILE tf)
{
tf->dwRefCount++;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetThemeIni
*
* Retrieves themes.ini from a theme
*/
PUXINI_FILE MSSTYLES_GetThemeIni(PTHEME_FILE tf)
{
return UXINI_LoadINI(tf->hTheme, szThemesIniResource);
}
/***********************************************************************
* MSSTYLES_GetActiveThemeIni
*
* Retrieve the ini file for the selected color/style
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf)
{
static const WCHAR szFileResNamesResource[] = {
'F','I','L','E','R','E','S','N','A','M','E','S','\0'
};
DWORD dwColorCount = 0;
DWORD dwSizeCount = 0;
DWORD dwColorNum = 0;
DWORD dwSizeNum = 0;
DWORD i;
DWORD dwResourceIndex;
LPWSTR tmp;
HRSRC hrsc;
/* Count the number of available colors & styles, and determine the index number
of the color/style we are interested in
*/
tmp = tf->pszAvailColors;
while(*tmp) {
if(!lstrcmpiW(tf->pszSelectedColor, tmp))
dwColorNum = dwColorCount;
tmp += lstrlenW(tmp)+1;
dwColorCount++;
}
tmp = tf->pszAvailSizes;
while(*tmp) {
if(!lstrcmpiW(tf->pszSelectedSize, tmp))
dwSizeNum = dwSizeCount;
tmp += lstrlenW(tmp)+1;
dwSizeCount++;
}
if(!(hrsc = FindResourceW(tf->hTheme, MAKEINTRESOURCEW(1), szFileResNamesResource))) {
TRACE("FILERESNAMES map not found\n");
return NULL;
}
tmp = LoadResource(tf->hTheme, hrsc);
dwResourceIndex = (dwSizeCount * dwColorNum) + dwSizeNum;
for(i=0; i < dwResourceIndex; i++) {
tmp += lstrlenW(tmp)+1;
}
return UXINI_LoadINI(tf->hTheme, tmp);
}
/***********************************************************************
* MSSTYLES_ParseIniSectionName
*
* Parse an ini section name into its component parts
* Valid formats are:
* [classname]
* [classname(state)]
* [classname.part]
* [classname.part(state)]
* [application::classname]
* [application::classname(state)]
* [application::classname.part]
* [application::classname.part(state)]
*
* PARAMS
* lpSection Section name
* dwLen Length of section name
* szAppName Location to store application name
* szClassName Location to store class name
* iPartId Location to store part id
* iStateId Location to store state id
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD dwLen, LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int *iStateId)
{
WCHAR sec[255];
WCHAR part[60] = {'\0'};
WCHAR state[60] = {'\0'};
LPWSTR tmp;
LPWSTR comp;
lstrcpynW(sec, lpSection, min(dwLen+1, sizeof(sec)/sizeof(sec[0])));
*szAppName = 0;
*szClassName = 0;
*iPartId = 0;
*iStateId = 0;
comp = sec;
/* Get the application name */
tmp = strchrW(comp, ':');
if(tmp) {
*tmp++ = 0;
tmp++;
lstrcpynW(szAppName, comp, MAX_THEME_APP_NAME);
comp = tmp;
}
tmp = strchrW(comp, '.');
if(tmp) {
*tmp++ = 0;
lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME);
comp = tmp;
/* now get the part & state */
tmp = strchrW(comp, '(');
if(tmp) {
*tmp++ = 0;
lstrcpynW(part, comp, sizeof(part)/sizeof(part[0]));
comp = tmp;
/* now get the state */
tmp = strchrW(comp, ')');
if (!tmp)
return FALSE;
*tmp = 0;
lstrcpynW(state, comp, sizeof(state)/sizeof(state[0]));
}
else {
lstrcpynW(part, comp, sizeof(part)/sizeof(part[0]));
}
}
else {
tmp = strchrW(comp, '(');
if(tmp) {
*tmp++ = 0;
lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME);
comp = tmp;
/* now get the state */
tmp = strchrW(comp, ')');
if (!tmp)
return FALSE;
*tmp = 0;
lstrcpynW(state, comp, sizeof(state)/sizeof(state[0]));
}
else {
lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME);
}
}
if(!*szClassName) return FALSE;
return MSSTYLES_LookupPartState(szClassName, part[0]?part:NULL, state[0]?state:NULL, iPartId, iStateId);
}
/***********************************************************************
* MSSTYLES_FindClass
*
* Find a class
*
* PARAMS
* tf Theme file
* pszAppName App name to find
* pszClassName Class name to find
*
* RETURNS
* The class found, or NULL
*/
static PTHEME_CLASS MSSTYLES_FindClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName)
{
PTHEME_CLASS cur = tf->classes;
while(cur) {
if(!pszAppName) {
if(!*cur->szAppName && !lstrcmpiW(pszClassName, cur->szClassName))
return cur;
}
else {
if(!lstrcmpiW(pszAppName, cur->szAppName) && !lstrcmpiW(pszClassName, cur->szClassName))
return cur;
}
cur = cur->next;
}
return NULL;
}
/***********************************************************************
* MSSTYLES_AddClass
*
* Add a class to a theme file
*
* PARAMS
* tf Theme file
* pszAppName App name to add
* pszClassName Class name to add
*
* RETURNS
* The class added, or a class previously added with the same name
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName)
{
PTHEME_CLASS cur = MSSTYLES_FindClass(tf, pszAppName, pszClassName);
if(cur) return cur;
cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_CLASS));
cur->hTheme = tf->hTheme;
lstrcpyW(cur->szAppName, pszAppName);
lstrcpyW(cur->szClassName, pszClassName);
cur->next = tf->classes;
cur->partstate = NULL;
cur->overrides = NULL;
tf->classes = cur;
return cur;
}
/***********************************************************************
* MSSTYLES_FindPartState
*
* Find a part/state
*
* PARAMS
* tc Class to search
* iPartId Part ID to find
* iStateId State ID to find
* tcNext Receives the next class in the override chain
*
* RETURNS
* The part/state found, or NULL
*/
PTHEME_PARTSTATE MSSTYLES_FindPartState(PTHEME_CLASS tc, int iPartId, int iStateId, PTHEME_CLASS *tcNext)
{
PTHEME_PARTSTATE cur = tc->partstate;
while(cur) {
if(cur->iPartId == iPartId && cur->iStateId == iStateId) {
if(tcNext) *tcNext = tc->overrides;
return cur;
}
cur = cur->next;
}
if(tc->overrides) return MSSTYLES_FindPartState(tc->overrides, iPartId, iStateId, tcNext);
return NULL;
}
/***********************************************************************
* MSSTYLES_AddPartState
*
* Add a part/state to a class
*
* PARAMS
* tc Theme class
* iPartId Part ID to add
* iStateId State ID to add
*
* RETURNS
* The part/state added, or a part/state previously added with the same IDs
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int iPartId, int iStateId)
{
PTHEME_PARTSTATE cur = MSSTYLES_FindPartState(tc, iPartId, iStateId, NULL);
if(cur) return cur;
cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PARTSTATE));
cur->iPartId = iPartId;
cur->iStateId = iStateId;
cur->properties = NULL;
cur->next = tc->partstate;
tc->partstate = cur;
return cur;
}
/***********************************************************************
* MSSTYLES_LFindProperty
*
* Find a property within a property list
*
* PARAMS
* tp property list to scan
* iPropertyPrimitive Type of value expected
* iPropertyId ID of the required value
*
* RETURNS
* The property found, or NULL
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int iPropertyPrimitive, int iPropertyId)
{
PTHEME_PROPERTY cur = tp;
while(cur) {
if(cur->iPropertyId == iPropertyId) {
if(cur->iPrimitiveType == iPropertyPrimitive) {
return cur;
}
else {
if(!iPropertyPrimitive)
return cur;
return NULL;
}
}
cur = cur->next;
}
return NULL;
}
/***********************************************************************
* MSSTYLES_PSFindProperty
*
* Find a value within a part/state
*
* PARAMS
* ps Part/state to search
* iPropertyPrimitive Type of value expected
* iPropertyId ID of the required value
*
* RETURNS
* The property found, or NULL
*/
static inline PTHEME_PROPERTY MSSTYLES_PSFindProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId)
{
return MSSTYLES_LFindProperty(ps->properties, iPropertyPrimitive, iPropertyId);
}
/***********************************************************************
* MSSTYLES_FindMetric
*
* Find a metric property for a theme file
*
* PARAMS
* tf Theme file
* iPropertyPrimitive Type of value expected
* iPropertyId ID of the required value
*
* RETURNS
* The property found, or NULL
*/
PTHEME_PROPERTY MSSTYLES_FindMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId)
{
return MSSTYLES_LFindProperty(tf->metrics, iPropertyPrimitive, iPropertyId);
}
/***********************************************************************
* MSSTYLES_AddProperty
*
* Add a property to a part/state
*
* PARAMS
* ps Part/state
* iPropertyPrimitive Primitive type of the property
* iPropertyId ID of the property
* lpValue Raw value (non-NULL terminated)
* dwValueLen Length of the value
*
* RETURNS
* The property added, or a property previously added with the same IDs
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen, BOOL isGlobal)
{
PTHEME_PROPERTY cur = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId);
/* Should duplicate properties overwrite the original, or be ignored? */
if(cur) return cur;
cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PROPERTY));
cur->iPrimitiveType = iPropertyPrimitive;
cur->iPropertyId = iPropertyId;
cur->lpValue = lpValue;
cur->dwValueLen = dwValueLen;
if(ps->iStateId)
cur->origin = PO_STATE;
else if(ps->iPartId)
cur->origin = PO_PART;
else if(isGlobal)
cur->origin = PO_GLOBAL;
else
cur->origin = PO_CLASS;
cur->next = ps->properties;
ps->properties = cur;
return cur;
}
/***********************************************************************
* MSSTYLES_AddMetric
*
* Add a property to a part/state
*
* PARAMS
* tf Theme file
* iPropertyPrimitive Primitive type of the property
* iPropertyId ID of the property
* lpValue Raw value (non-NULL terminated)
* dwValueLen Length of the value
*
* RETURNS
* The property added, or a property previously added with the same IDs
*/
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
static PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen)
{
PTHEME_PROPERTY cur = MSSTYLES_FindMetric(tf, iPropertyPrimitive, iPropertyId);
/* Should duplicate properties overwrite the original, or be ignored? */
if(cur) return cur;
cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PROPERTY));
cur->iPrimitiveType = iPropertyPrimitive;
cur->iPropertyId = iPropertyId;
cur->lpValue = lpValue;
cur->dwValueLen = dwValueLen;
cur->origin = PO_GLOBAL;
cur->next = tf->metrics;
tf->metrics = cur;
return cur;
}
/***********************************************************************
* MSSTYLES_ParseThemeIni
*
* Parse the theme ini for the selected color/style
*
* PARAMS
* tf Theme to parse
*/
void MSSTYLES_ParseThemeIni(PTHEME_FILE tf)
{
static const WCHAR szSysMetrics[] = {'S','y','s','M','e','t','r','i','c','s','\0'};
static const WCHAR szGlobals[] = {'g','l','o','b','a','l','s','\0'};
PTHEME_CLASS cls;
PTHEME_CLASS globals;
PTHEME_PARTSTATE ps;
PUXINI_FILE ini;
WCHAR szAppName[MAX_THEME_APP_NAME];
WCHAR szClassName[MAX_THEME_CLASS_NAME];
WCHAR szPropertyName[MAX_THEME_VALUE_NAME];
int iPartId;
int iStateId;
int iPropertyPrimitive;
int iPropertyId;
DWORD dwLen;
LPCWSTR lpName;
DWORD dwValueLen;
LPCWSTR lpValue;
if(tf->classes)
return;
ini = MSSTYLES_GetActiveThemeIni(tf);
while((lpName=UXINI_GetNextSection(ini, &dwLen)))
{
if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpName, dwLen, szSysMetrics, -1) == CSTR_EQUAL)
{
while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen)))
{
lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0])));
if(MSSTYLES_LookupProperty(szPropertyName, &iPropertyPrimitive, &iPropertyId))
{
/* Catch all metrics, including colors */
MSSTYLES_AddMetric(tf, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen);
}
else
{
TRACE("Unknown system metric %s\n", debugstr_w(szPropertyName));
}
}
continue;
}
if(MSSTYLES_ParseIniSectionName(lpName, dwLen, szAppName, szClassName, &iPartId, &iStateId))
{
BOOL isGlobal = FALSE;
if(!lstrcmpiW(szClassName, szGlobals))
{
isGlobal = TRUE;
}
cls = MSSTYLES_AddClass(tf, szAppName, szClassName);
ps = MSSTYLES_AddPartState(cls, iPartId, iStateId);
while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen)))
{
lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0])));
if(MSSTYLES_LookupProperty(szPropertyName, &iPropertyPrimitive, &iPropertyId))
{
MSSTYLES_AddProperty(ps, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen, isGlobal);
}
else
{
TRACE("Unknown property %s\n", debugstr_w(szPropertyName));
}
}
}
}
/* App/Class combos override values defined by the base class, map these overrides */
globals = MSSTYLES_FindClass(tf, NULL, szGlobals);
cls = tf->classes;
while(cls)
{
if(*cls->szAppName)
{
cls->overrides = MSSTYLES_FindClass(tf, NULL, cls->szClassName);
if(!cls->overrides)
{
TRACE("No overrides found for app %s class %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName));
}
else
{
cls->overrides = globals;
}
}
else
{
/* Everything overrides globals..except globals */
if(cls != globals)
cls->overrides = globals;
}
cls = cls->next;
}
UXINI_CloseINI(ini);
if(!tf->classes) {
ERR("Failed to parse theme ini\n");
}
}
/***********************************************************************
* MSSTYLES_OpenThemeClass
*
* Open a theme class, uses the current active theme
*
* PARAMS
* pszAppName Application name, for theme styles specific
* to a particular application
* pszClassList List of requested classes, semicolon delimited
*/
PTHEME_CLASS MSSTYLES_OpenThemeClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassList)
{
PTHEME_CLASS cls = NULL;
#ifdef __REACTOS__
PTHEME_CLASS defaultCls = NULL;
#endif
WCHAR szClassName[MAX_THEME_CLASS_NAME];
LPCWSTR start;
LPCWSTR end;
DWORD len;
if(!tf->classes) {
return NULL;
}
start = pszClassList;
while((end = strchrW(start, ';'))) {
len = end-start;
lstrcpynW(szClassName, start, min(len+1, sizeof(szClassName)/sizeof(szClassName[0])));
start = end+1;
cls = MSSTYLES_FindClass(tf, pszAppName, szClassName);
if(cls) break;
#ifdef __REACTOS__
if (!defaultCls)
defaultCls = MSSTYLES_FindClass(tf, NULL, szClassName);
#endif
}
if(!cls && *start) {
lstrcpynW(szClassName, start, sizeof(szClassName)/sizeof(szClassName[0]));
cls = MSSTYLES_FindClass(tf, pszAppName, szClassName);
#ifdef __REACTOS__
if (!defaultCls)
defaultCls = MSSTYLES_FindClass(tf, NULL, szClassName);
#endif
}
if(cls) {
TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList));
cls->tf = tf;
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
cls->tf->dwRefCount++;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
}
#ifdef __REACTOS__
else if (defaultCls)
{
cls = defaultCls;
TRACE("Opened default class %s from list %s\n", debugstr_w(cls->szClassName), debugstr_w(pszClassList));
cls->tf = tf;
cls->tf->dwRefCount++;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
}
#endif
return cls;
}
/***********************************************************************
* MSSTYLES_CloseThemeClass
*
* Close a theme class
*
* PARAMS
* tc Theme class to close
*
* NOTES
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
* The MSSTYLES_CloseThemeFile decreases the refcount of the owning
* theme file and cleans it up, if needed.
*/
HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc)
{
Sync to Wine-20050725: Thomas Weidenmueller <wine-patches@reactsoft.com> - IsThemeDialogTextureEnabled should have one parameter to match the prototype in the official headers. Mike McCormack <mike@codeweavers.com> - gcc 4.0 -Wpointer-sign fixes (Reg* functions). Stefan Huehner <stefan@huehner.org> - Make some function static. - Fix -Wmissing-declarations warnings. Frank Richter <frank.richter@gmail.com> - Enable/disable "flat menus" based on the setting from the active theme. - Have the theme INI file parsed upon theme activation and not just when the first theme data is requested; that way, the themed system colors are set correctly from the start, and not just after some theme data was requested. - GetThemeBackgroundContentRect() does not use the content margins alone, it also falls back to the border size or sizing margins, and if it can't find any possible margins at all, it returns the original rectangle. - Make dialog theme texture setting non-global (ie a per-window setting). - Better viewport origin in DrawThemeParentBackground(). - OpenThemeData() now always sets the window theme to the handle returned (even if that is NULL) - previously, it could happen that when no theme was active or the theme data could not be opened that the window theme remained became then-dangling (and hence subsequent calls to GetWindowTheme() would return that bogus theme). - Correct border rectangle drawing. - Don't crash if NULL is passed as the class list to OpenThemeData(). - UXTHEME_LoadImage(): Set default image count to 1 to avoid division by zero in case image count property is not given. Properly support 0 state IDs. - Every window needs to receive WM_THEMECHANGED (esp. controls), so also send it to child windows. - Changed the default transparent color in case none was explicitly specified from the upper left pixel color to magenta. Empirically gives better results. - Write WCHAR strings to registry with correct size. - Opening some theme class data now also increases the reference count of the theme file, so as long as theme class data is still opened somewhere, the theme file won't get freed. Otherwise, it could happen that invalid class data was used, which could lead to problems. svn path=/trunk/; revision=17342
2005-08-12 18:22:47 +00:00
MSSTYLES_CloseThemeFile (tc->tf);
return S_OK;
}
/***********************************************************************
* MSSTYLES_FindProperty
*
* Locate a property in a class. Part and state IDs will be used as a
* preference, but may be ignored in the attempt to locate the property.
* Will scan the entire chain of overrides for this class.
*/
PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId, int iPropertyPrimitive, int iPropertyId)
{
PTHEME_CLASS next = tc;
PTHEME_PARTSTATE ps;
PTHEME_PROPERTY tp;
TRACE("(%p, %d, %d, %d)\n", tc, iPartId, iStateId, iPropertyId);
/* Try and find an exact match on part & state */
while(next && (ps = MSSTYLES_FindPartState(next, iPartId, iStateId, &next))) {
if((tp = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId))) {
return tp;
}
}
/* If that fails, and we didn't already try it, search for just part */
if(iStateId != 0)
iStateId = 0;
/* As a last ditch attempt..go for just class */
else if(iPartId != 0)
iPartId = 0;
else
return NULL;
if((tp = MSSTYLES_FindProperty(tc, iPartId, iStateId, iPropertyPrimitive, iPropertyId)))
return tp;
return NULL;
}
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
/* Prepare a bitmap to be used for alpha blending */
static BOOL prepare_alpha (HBITMAP bmp, BOOL* hasAlpha)
{
DIBSECTION dib;
int n;
BYTE* p;
*hasAlpha = FALSE;
if (!bmp || GetObjectW( bmp, sizeof(dib), &dib ) != sizeof(dib))
return FALSE;
if(dib.dsBm.bmBitsPixel != 32)
/* nothing to do */
return TRUE;
p = dib.dsBm.bmBits;
n = dib.dsBmih.biHeight * dib.dsBmih.biWidth;
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
/* AlphaBlend() wants premultiplied alpha, so do that now */
while (n-- > 0)
{
int a = p[3]+1;
p[0] = (p[0] * a) >> 8;
p[1] = (p[1] * a) >> 8;
p[2] = (p[2] * a) >> 8;
p += 4;
if (a != 256)
*hasAlpha = TRUE;
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
}
return TRUE;
}
HBITMAP MSSTYLES_LoadBitmap (PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha)
{
WCHAR szFile[MAX_PATH];
LPWSTR tmp;
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
PTHEME_IMAGE img;
lstrcpynW(szFile, lpFilename, sizeof(szFile)/sizeof(szFile[0]));
tmp = szFile;
do {
if(*tmp == '\\') *tmp = '_';
if(*tmp == '/') *tmp = '_';
if(*tmp == '.') *tmp = '_';
} while(*tmp++);
Sync to Wine-20050830: Kevin Koltzau <kevin@plop.org> - Fix 'cast to pointer from integer of different size' warnings in 64bit. Frank Richter <frank.richter@gmail.com> - Add support for the BT_NONE background type. - Better computations to have uniformly sized parts scaled in both directions. - Implement GetThemeBackgroundExtent(). - Implement DrawThemeEdge(). - Implement support for the ST_TILE background stretching mode. - Implementation for GetThemePartSize() (not entirely equivalent to native uxtheme, but sensibly useable). - Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. - Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. - Make GetThemeMargins() return default values (0 margin) if the function does not succeed. - More elaborate IsThemeBackgroundPartiallyTransparent() implementation; also returns TRUE for theme parts with 32bpp images. - Since theme images are reused now it's not really a good idea to delete them in drawing functions. - Pass around what kind of transparency an image actually needs. Use alpha-blending for 32bpp images. - Set some default values for truesize sizing that seem closer to Windows. - If a MINSIZEn property is not present, fall back to actual size of nth image to determine whether it is suitable. - EnumThemeColors() and EnumThemeSizes() actually do not return a single string with the color/size name, but rather a struct containing three strings - name, display name and tooltip. - The default image layout is HORIZONTAL, not VERTICAL. - Take a common computation out of two if-branches in UXTHEME_LoadImage(). - Compare result of RegQueryValueExW() with ERROR_SUCCESS. - Another fix to use magenta as the default transparent color. - Implement "manual" image sharing(as opposed to using LoadImage() with LR_SHARED) by keeping the loaded images in a list. This is needed for proper alpha support later on since once-per-image preparations will be needed then. - Add support for horizontal & vertical alignment when doing truesize sizing. - Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used it for. Native uxtheme always stretches "truesize" parts when the destination is smaller than the part image size, but TrueSizeStretchMark doesn't seem to have an influence. svn path=/trunk/; revision=17719
2005-09-07 16:22:51 +00:00
/* Try to locate in list of loaded images */
img = tc->tf->images;
while (img)
{
if (lstrcmpiW (szFile, img->name) == 0)
{
TRACE ("found %p %s: %p\n", img, debugstr_w (img->name), img->image);
*hasAlpha = img->hasAlpha;
return img->image;
}
img = img->next;
}
/* Not found? Load from resources */
img = HeapAlloc (GetProcessHeap(), 0, sizeof (THEME_IMAGE));
img->image = LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
prepare_alpha (img->image, hasAlpha);
img->hasAlpha = *hasAlpha;
/* ...and stow away for later reuse. */
lstrcpyW (img->name, szFile);
img->next = tc->tf->images;
tc->tf->images = img;
TRACE ("new %p %s: %p\n", img, debugstr_w (img->name), img->image);
return img->image;
}
static BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value)
{
LPCWSTR cur = lpStringStart;
int total = 0;
BOOL gotNeg = FALSE;
while(cur < lpStringEnd && ((*cur < '0' || *cur > '9') && *cur != '-')) cur++;
if(cur >= lpStringEnd) {
return FALSE;
}
if(*cur == '-') {
cur++;
gotNeg = TRUE;
}
while(cur < lpStringEnd && (*cur >= '0' && *cur <= '9')) {
total = total * 10 + (*cur - '0');
cur++;
}
if(gotNeg) total = -total;
*value = total;
if(lpValEnd) *lpValEnd = cur;
return TRUE;
}
static BOOL MSSTYLES_GetNextToken(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LPWSTR lpBuff, DWORD buffSize) {
LPCWSTR cur = lpStringStart;
LPCWSTR start;
LPCWSTR end;
while(cur < lpStringEnd && (isspace(*cur) || *cur == ',')) cur++;
if(cur >= lpStringEnd) {
return FALSE;
}
start = cur;
while(cur < lpStringEnd && *cur != '\n'&& *cur != ',') cur++;
end = cur;
while(isspace(*(end-1))) end--;
lstrcpynW(lpBuff, start, min(buffSize, end-start+1));
if(lpValEnd) *lpValEnd = cur;
return TRUE;
}
/***********************************************************************
* MSSTYLES_GetPropertyBool
*
* Retrieve a color value for a property
*/
HRESULT MSSTYLES_GetPropertyBool(PTHEME_PROPERTY tp, BOOL *pfVal)
{
*pfVal = FALSE;
if(*tp->lpValue == 't' || *tp->lpValue == 'T')
*pfVal = TRUE;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyColor
*
* Retrieve a color value for a property
*/
HRESULT MSSTYLES_GetPropertyColor(PTHEME_PROPERTY tp, COLORREF *pColor)
{
LPCWSTR lpEnd;
LPCWSTR lpCur;
int red, green, blue;
lpCur = tp->lpValue;
lpEnd = tp->lpValue + tp->dwValueLen;
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &red)) {
TRACE("Could not parse color property\n");
return E_PROP_ID_UNSUPPORTED;
}
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &green)) {
TRACE("Could not parse color property\n");
return E_PROP_ID_UNSUPPORTED;
}
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &blue)) {
TRACE("Could not parse color property\n");
return E_PROP_ID_UNSUPPORTED;
}
*pColor = RGB(red,green,blue);
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyColor
*
* Retrieve a color value for a property
*/
static HRESULT MSSTYLES_GetFont (LPCWSTR lpCur, LPCWSTR lpEnd,
LPCWSTR *lpValEnd, LOGFONTW* pFont)
{
static const WCHAR szBold[] = {'b','o','l','d','\0'};
static const WCHAR szItalic[] = {'i','t','a','l','i','c','\0'};
static const WCHAR szUnderline[] = {'u','n','d','e','r','l','i','n','e','\0'};
static const WCHAR szStrikeOut[] = {'s','t','r','i','k','e','o','u','t','\0'};
int pointSize;
WCHAR attr[32];
if(!MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, pFont->lfFaceName, LF_FACESIZE)) {
TRACE("Property is there, but failed to get face name\n");
*lpValEnd = lpCur;
return E_PROP_ID_UNSUPPORTED;
}
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pointSize)) {
TRACE("Property is there, but failed to get point size\n");
*lpValEnd = lpCur;
return E_PROP_ID_UNSUPPORTED;
}
if(pointSize > 0)
{
HDC hdc = GetDC(0);
pointSize = -MulDiv(pointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(0, hdc);
}
pFont->lfHeight = pointSize;
pFont->lfWeight = FW_REGULAR;
pFont->lfCharSet = DEFAULT_CHARSET;
while(MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, attr, sizeof(attr)/sizeof(attr[0]))) {
if(!lstrcmpiW(szBold, attr)) pFont->lfWeight = FW_BOLD;
else if(!lstrcmpiW(szItalic, attr)) pFont->lfItalic = TRUE;
else if(!lstrcmpiW(szUnderline, attr)) pFont->lfUnderline = TRUE;
else if(!lstrcmpiW(szStrikeOut, attr)) pFont->lfStrikeOut = TRUE;
}
*lpValEnd = lpCur;
return S_OK;
}
HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
HRESULT hr;
ZeroMemory(pFont, sizeof(LOGFONTW));
hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont);
return hr;
}
/***********************************************************************
* MSSTYLES_GetPropertyInt
*
* Retrieve an int value for a property
*/
HRESULT MSSTYLES_GetPropertyInt(PTHEME_PROPERTY tp, int *piVal)
{
if(!MSSTYLES_GetNextInteger(tp->lpValue, (tp->lpValue + tp->dwValueLen), NULL, piVal)) {
TRACE("Could not parse int property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyIntList
*
* Retrieve an int list value for a property
*/
HRESULT MSSTYLES_GetPropertyIntList(PTHEME_PROPERTY tp, INTLIST *pIntList)
{
int i;
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
for(i=0; i < MAX_INTLIST_COUNT; i++) {
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pIntList->iValues[i]))
break;
}
pIntList->iValueCount = i;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyPosition
*
* Retrieve a position value for a property
*/
HRESULT MSSTYLES_GetPropertyPosition(PTHEME_PROPERTY tp, POINT *pPoint)
{
int x,y;
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &x)) {
TRACE("Could not parse position property\n");
return E_PROP_ID_UNSUPPORTED;
}
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &y)) {
TRACE("Could not parse position property\n");
return E_PROP_ID_UNSUPPORTED;
}
pPoint->x = x;
pPoint->y = y;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyString
*
* Retrieve a string value for a property
*/
HRESULT MSSTYLES_GetPropertyString(PTHEME_PROPERTY tp, LPWSTR pszBuff, int cchMaxBuffChars)
{
lstrcpynW(pszBuff, tp->lpValue, min(tp->dwValueLen+1, cchMaxBuffChars));
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyRect
*
* Retrieve a rect value for a property
*/
HRESULT MSSTYLES_GetPropertyRect(PTHEME_PROPERTY tp, RECT *pRect)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->left);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->top);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->right);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->bottom)) {
TRACE("Could not parse rect property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyMargins
*
* Retrieve a margins value for a property
*/
HRESULT MSSTYLES_GetPropertyMargins(PTHEME_PROPERTY tp, RECT *prc, MARGINS *pMargins)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxLeftWidth);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxRightWidth);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyTopHeight);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyBottomHeight)) {
TRACE("Could not parse margins property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}