Add INI file processing.

Full implementation of GetThemeDocumentationProperty.
Define string maps for parsing INI files into useable form.
Implemented (undocumented) ApplyTheme to select current theme.
This commit is contained in:
Kevin Koltzau 2004-01-16 21:25:25 +00:00 committed by Alexandre Julliard
parent 1614f91767
commit e04ff33417
9 changed files with 1668 additions and 44 deletions

View File

@ -12,7 +12,9 @@ C_SRCS = \
metric.c \
msstyles.c \
property.c \
system.c
stylemap.c \
system.c \
uxini.c
RC_SRCS = version.rc

View File

@ -39,7 +39,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDLL);
UXTHEME_InitSystem();
UXTHEME_InitSystem(hInstDLL);
break;
case DLL_PROCESS_DETACH:
break;

View File

@ -35,8 +35,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
/***********************************************************************
* Defines and global variables
*/
extern HINSTANCE hDllInst;
#define MSSTYLES_VERSION 0x0003
static const WCHAR szThemesIniResource[] = {
't','h','e','m','e','s','_','i','n','i','\0'
};
PTHEME_FILE tfActiveTheme = NULL;
/***********************************************************************/
/**********************************************************************
* MSSTYLES_OpenThemeFile
*
@ -144,12 +158,13 @@ HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWST
goto invalid_theme;
}
*tf = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_FILE));
*tf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THEME_FILE));
(*tf)->hTheme = hTheme;
(*tf)->pszAvailColors = pszColors;
(*tf)->pszAvailSizes = pszSizes;
(*tf)->pszSelectedColor = pszSelectedColor;
(*tf)->pszSelectedSize = pszSelectedSize;
(*tf)->dwRefCount = 1;
return S_OK;
invalid_theme:
@ -166,7 +181,56 @@ invalid_theme:
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
{
if(tf) {
if(tf->hTheme) FreeLibrary(tf->hTheme);
HeapFree(GetProcessHeap(), 0, tf);
tf->dwRefCount--;
if(!tf->dwRefCount) {
if(tf->hTheme) FreeLibrary(tf->hTheme);
HeapFree(GetProcessHeap(), 0, tf);
}
}
}
/***********************************************************************
* MSSTYLES_SetActiveTheme
*
* Set the current active theme
*/
HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf)
{
if(tfActiveTheme)
MSSTYLES_CloseThemeFile(tfActiveTheme);
tfActiveTheme = tf;
tfActiveTheme->dwRefCount++;
FIXME("Process theme resources\n");
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetThemeIni
*
* Retrieves themes.ini from a theme
*/
PUXINI_FILE MSSTYLES_GetThemeIni(PTHEME_FILE tf)
{
return UXINI_LoadINI(tf, szThemesIniResource);
}
/***********************************************************************
* MSSTYLES_OpenThemeClass
*
* Open a theme class
*
* PARAMS
* tf Previously opened theme file
* pszClassList List of requested classes, semicolon delimited
*/
PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszClassList)
{
FIXME("%s\n", debugstr_w(pszClassList));
return NULL;
}
HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc)
{
FIXME("%p\n", tc);
return S_OK;
}

View File

@ -21,7 +21,10 @@
#ifndef __WINE_MSSTYLES_H
#define __WINE_MSSTYLES_H
#define TMT_ENUM 200
typedef struct _THEME_FILE {
DWORD dwRefCount;
HMODULE hTheme;
LPWSTR pszAvailColors;
LPWSTR pszAvailSizes;
@ -30,8 +33,30 @@ typedef struct _THEME_FILE {
LPWSTR pszSelectedSize;
} THEME_FILE, *PTHEME_FILE;
typedef struct _THEME_CLASS {
/* TODO */
} THEME_CLASS, *PTHEME_CLASS;
typedef struct _UXINI_FILE {
LPCWSTR lpIni;
LPCWSTR lpCurLoc;
LPCWSTR lpEnd;
} UXINI_FILE, *PUXINI_FILE;
HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf);
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf);
HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf);
PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszClassList);
HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc);
BOOL MSSTYLES_LookupProperty(LPCWSTR pszPropertyName, DWORD *dwPrimitive, DWORD *dwId);
PUXINI_FILE MSSTYLES_GetThemeIni(PTHEME_FILE tf);
PUXINI_FILE UXINI_LoadINI(PTHEME_FILE tf, LPCWSTR lpName);
void UXINI_CloseINI(PUXINI_FILE uf);
void UXINI_ResetINI(PUXINI_FILE uf);
LPCWSTR UXINI_GetNextSection(PUXINI_FILE uf, DWORD *dwLen);
BOOL UXINI_FindSection(PUXINI_FILE uf, LPCWSTR lpName);
LPCWSTR UXINI_GetNextValue(PUXINI_FILE uf, DWORD *dwNameLen, LPCWSTR *lpValue, DWORD *dwValueLen);
BOOL UXINI_FindValue(PUXINI_FILE uf, LPCWSTR lpName, LPCWSTR *lpValue, DWORD *dwValueLen);
#endif

View File

@ -34,18 +34,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
/***********************************************************************
* GetThemeDocumentationProperty (UXTHEME.@)
*/
HRESULT WINAPI GetThemeDocumentationProperty(LPCWSTR pszThemeName,
LPCWSTR pszPropertyName,
LPWSTR pszValueBuff,
int cchMaxValChars)
{
FIXME("%s %s: stub\n", debugstr_w(pszThemeName), debugstr_w(pszPropertyName));
return ERROR_CALL_NOT_IMPLEMENTED;
}
/***********************************************************************
* GetThemeBool (UXTHEME.@)
*/

1102
dlls/uxtheme/stylemap.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@
#include "winreg.h"
#include "shlwapi.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "uxthemedll.h"
#include "msstyles.h"
@ -53,6 +54,10 @@ static const WCHAR szSizeName[] = {'S','i','z','e','N','a','m','e','\0'};
static const WCHAR szColorName[] = {'C','o','l','o','r','N','a','m','e','\0'};
static const WCHAR szDllName[] = {'D','l','l','N','a','m','e','\0'};
static const WCHAR szIniDocumentation[] = {'d','o','c','u','m','e','n','t','a','t','i','o','n','\0'};
HINSTANCE hDllInst;
DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
ATOM atWindowTheme;
ATOM atSubAppName;
@ -66,29 +71,18 @@ WCHAR szCurrentSize[64];
/***********************************************************************/
/***********************************************************************
* UXTHEME_InitSystem
* UXTHEME_LoadTheme
*
* Set the current active theme from the registry
*/
void UXTHEME_InitSystem()
void UXTHEME_LoadTheme()
{
const WCHAR szWindowTheme[] = {
'u','x','_','t','h','e','m','e','\0'
};
const WCHAR szSubAppName[] = {
'u','x','_','s','u','b','a','p','p','\0'
};
const WCHAR szSubIdList[] = {
'u','x','_','s','u','b','i','d','l','s','t','\0'
};
HKEY hKey;
LONG buffsize;
HRESULT hr;
WCHAR tmp[10];
PTHEME_FILE pt;
atWindowTheme = GlobalAddAtomW(szWindowTheme);
atSubAppName = GlobalAddAtomW(szSubAppName);
atSubIdList = GlobalAddAtomW(szSubIdList);
/* Get current theme configuration */
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
TRACE("Loading theme config\n");
@ -129,15 +123,84 @@ void UXTHEME_InitSystem()
/* Make sure the global color & size match the theme */
lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
MSSTYLES_SetActiveTheme(pt);
TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
MSSTYLES_CloseThemeFile(pt);
}
}
if(!bThemeActive)
if(!bThemeActive) {
MSSTYLES_SetActiveTheme(NULL);
TRACE("Themeing not active\n");
}
}
/***********************************************************************
* UXTHEME_SetActiveTheme
*
* Change the current active theme
*/
HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf)
{
HKEY hKey;
WCHAR tmp[2];
HRESULT hr;
hr = MSSTYLES_SetActiveTheme(tf);
if(FAILED(hr))
return hr;
if(tf) {
bThemeActive = TRUE;
GetModuleFileNameW(tf->hTheme, szCurrentTheme, sizeof(szCurrentTheme)/sizeof(szCurrentTheme[0]));
lstrcpynW(szCurrentColor, tf->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
lstrcpynW(szCurrentSize, tf->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
}
else {
bThemeActive = FALSE;
szCurrentTheme[0] = '\0';
szCurrentColor[0] = '\0';
szCurrentSize[0] = '\0';
return MSSTYLES_SetActiveTheme(NULL);
}
TRACE("Writing theme config to registry\n");
if(!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
tmp[0] = bThemeActive?'1':'0';
tmp[1] = '\0';
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2);
RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)szCurrentColor, lstrlenW(szCurrentColor)+1);
RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)szCurrentSize, lstrlenW(szCurrentSize)+1);
RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)szCurrentTheme, lstrlenW(szCurrentTheme)+1);
RegCloseKey(hKey);
}
else
TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
TRACE("Failed to open theme registry key\n");
return hr;
}
/***********************************************************************
* UXTHEME_InitSystem
*/
void UXTHEME_InitSystem(HINSTANCE hInst)
{
const WCHAR szWindowTheme[] = {
'u','x','_','t','h','e','m','e','\0'
};
const WCHAR szSubAppName[] = {
'u','x','_','s','u','b','a','p','p','\0'
};
const WCHAR szSubIdList[] = {
'u','x','_','s','u','b','i','d','l','s','t','\0'
};
hDllInst = hInst;
atWindowTheme = GlobalAddAtomW(szWindowTheme);
atSubAppName = GlobalAddAtomW(szSubAppName);
atSubIdList = GlobalAddAtomW(szSubIdList);
UXTHEME_LoadTheme();
}
/***********************************************************************
@ -180,15 +243,21 @@ HRESULT WINAPI EnableTheming(BOOL fEnable)
PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
}
return S_OK;
}
}
/***********************************************************************
* OpenThemeData (UXTHEME.@)
*/
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
{
FIXME("%p %s: stub\n", hwnd, debugstr_w(pszClassList));
return NULL;
HTHEME hTheme;
TRACE("(%p,%s)\n", hwnd, debugstr_w(pszClassList));
if(!bThemeActive)
return NULL;
hTheme = MSSTYLES_OpenThemeClass(pszClassList);
if(IsWindow(hwnd))
SetPropW(hwnd, MAKEINTATOMW(atWindowTheme), hTheme);
return hTheme;
}
/***********************************************************************
@ -281,10 +350,10 @@ void WINAPI SetThemeAppProperties(DWORD dwFlags)
*/
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
{
FIXME("stub\n");
TRACE("(%p)\n", hTheme);
if(!hTheme)
return E_HANDLE;
return S_OK;
return MSSTYLES_CloseThemeClass(hTheme);
}
/***********************************************************************
@ -310,6 +379,68 @@ BOOL WINAPI IsThemePartDefined(HTHEME hTheme, int iPartId, int iStateId)
return FALSE;
}
/***********************************************************************
* GetThemeDocumentationProperty (UXTHEME.@)
*
* Try and retrieve the documentation property from string resources
* if that fails, get it from the [documentation] section of themes.ini
*/
HRESULT WINAPI GetThemeDocumentationProperty(LPCWSTR pszThemeName,
LPCWSTR pszPropertyName,
LPWSTR pszValueBuff,
int cchMaxValChars)
{
const WORD wDocToRes[] = {
TMT_DISPLAYNAME,5000,
TMT_TOOLTIP,5001,
TMT_COMPANY,5002,
TMT_AUTHOR,5003,
TMT_COPYRIGHT,5004,
TMT_URL,5005,
TMT_VERSION,5006,
TMT_DESCRIPTION,5007
};
PTHEME_FILE pt;
HRESULT hr;
int i;
DWORD dwDocId;
TRACE("(%s,%s,%p,%d)\n", debugstr_w(pszThemeName), debugstr_w(pszPropertyName),
pszValueBuff, cchMaxValChars);
hr = MSSTYLES_OpenThemeFile(pszThemeName, NULL, NULL, &pt);
if(FAILED(hr)) return hr;
/* Try to load from string resources */
hr = E_PROP_ID_UNSUPPORTED;
if(MSSTYLES_LookupProperty(pszPropertyName, NULL, &dwDocId)) {
for(i=0; i<sizeof(wDocToRes)/sizeof(wDocToRes[0]); i+=2) {
if(wDocToRes[i] == dwDocId) {
if(LoadStringW(pt->hTheme, wDocToRes[i+1], pszValueBuff, cchMaxValChars)) {
hr = S_OK;
break;
}
}
}
}
/* If loading from string resource failed, try getting it from the theme.ini */
if(FAILED(hr)) {
PUXINI_FILE uf = MSSTYLES_GetThemeIni(pt);
if(UXINI_FindSection(uf, szIniDocumentation)) {
LPCWSTR lpValue;
DWORD dwLen;
if(UXINI_FindValue(uf, pszPropertyName, &lpValue, &dwLen)) {
lstrcpynW(pszValueBuff, lpValue, min(dwLen+1,cchMaxValChars));
hr = S_OK;
}
}
UXINI_CloseINI(uf);
}
MSSTYLES_CloseThemeFile(pt);
return hr;
}
/**********************************************************************
* Undocumented functions
*/
@ -385,8 +516,11 @@ HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile)
*/
HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd)
{
FIXME("%s: stub\n", unknown);
return ERROR_CALL_NOT_IMPLEMENTED;
HRESULT hr;
TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd);
hr = UXTHEME_SetActiveTheme(hThemeFile);
PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
return hr;
}
/**********************************************************************

309
dlls/uxtheme/uxini.c Normal file
View File

@ -0,0 +1,309 @@
/*
* Win32 5.1 uxtheme ini file processing
*
* Copyright (C) 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "msstyles.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
/***********************************************************************
* Defines and global variables
*/
static const WCHAR szTextFileResource[] = {
'T','E','X','T','F','I','L','E','\0'
};
/***********************************************************************/
/**********************************************************************
* UXINI_LoadINI
*
* Load a theme INI file out of resources from the specified
* theme
*
* PARAMS
* tf Theme to load INI file out of resources
* lpName Resource name of the INI file
*
* RETURNS
* INI file, or NULL if not found
*/
PUXINI_FILE UXINI_LoadINI(PTHEME_FILE tf, LPCWSTR lpName) {
HRSRC hrsc;
LPCWSTR lpThemesIni = NULL;
PUXINI_FILE uf;
DWORD dwIniSize;
if((hrsc = FindResourceW(tf->hTheme, lpName, szTextFileResource))) {
if(!(lpThemesIni = (LPCWSTR)LoadResource(tf->hTheme, hrsc))) {
TRACE("%s resource not found\n", debugstr_w(lpName));
return NULL;
}
}
dwIniSize = SizeofResource(tf->hTheme, hrsc) / sizeof(WCHAR);
uf = HeapAlloc(GetProcessHeap(), 0, sizeof(UXINI_FILE));
uf->lpIni = lpThemesIni;
uf->lpCurLoc = lpThemesIni;
uf->lpEnd = lpThemesIni + dwIniSize;
return uf;
}
/**********************************************************************
* UXINI_CloseINI
*
* Close an open theme INI file
*
* PARAMS
* uf Theme INI file to close
*/
void UXINI_CloseINI(PUXINI_FILE uf)
{
HeapFree(GetProcessHeap(), 0, uf);
}
/**********************************************************************
* UXINI_ResetINI
*
* Reset the current pointer into INI file to the beginning of the file
*
* PARAMS
* uf Theme INI file to reset
*/
void UXINI_ResetINI(PUXINI_FILE uf)
{
uf->lpCurLoc = uf->lpIni;
}
/**********************************************************************
* UXINI_eof
*
* Determines if we are at the end of the INI file
*
* PARAMS
* uf Theme INI file to test
*/
static inline BOOL UXINI_eof(PUXINI_FILE uf)
{
return uf->lpCurLoc >= uf->lpEnd;
}
/**********************************************************************
* UXINI_isspace
*
* Check if a character is a space character
*
* PARAMS
* c Character to test
*/
static inline BOOL UXINI_isspace(WCHAR c)
{
if (isspace(c)) return TRUE;
if (c=='\r') return TRUE;
return FALSE;
}
/**********************************************************************
* UXINI_GetNextLine
*
* Get the next line in the INI file, non NULL terminated
* removes whitespace at beginning and end of line, and removes comments
*
* PARAMS
* uf INI file to retrieve next line
* dwLen Location to store pointer to line length
*
* RETURNS
* The section name, non NULL terminated
*/
LPCWSTR UXINI_GetNextLine(PUXINI_FILE uf, DWORD *dwLen)
{
LPCWSTR lpLineEnd;
LPCWSTR lpLineStart;
DWORD len;
do {
if(UXINI_eof(uf)) return NULL;
/* Skip whitespace and empty lines */
while(!UXINI_eof(uf) && (UXINI_isspace(*uf->lpCurLoc) || *uf->lpCurLoc == '\n')) uf->lpCurLoc++;
lpLineStart = uf->lpCurLoc;
lpLineEnd = uf->lpCurLoc;
while(!UXINI_eof(uf) && *uf->lpCurLoc != '\n' && *uf->lpCurLoc != ';') lpLineEnd = uf->lpCurLoc++;
/* If comment was found, skip the rest of the line */
if(*uf->lpCurLoc == ';')
while(!UXINI_eof(uf) && *uf->lpCurLoc != '\n') uf->lpCurLoc++;
len = (lpLineEnd - lpLineStart);
if(len == 0)
return NULL;
} while(*lpLineStart == ';');
/* Remove whitespace from end of line */
while(UXINI_isspace(lpLineStart[len-1])) len--;
*dwLen = len;
return lpLineStart;
}
void UXINI_UnGetToLine(PUXINI_FILE uf, LPCWSTR lpLine)
{
uf->lpCurLoc = lpLine;
}
/**********************************************************************
* UXINI_GetNextSection
*
* Locate the next section in the ini file, and return pointer to
* section name, non NULL terminated. Use dwLen to determine length
*
* PARAMS
* uf INI file to search, search starts at current location
* dwLen Location to store pointer to section name length
*
* RETURNS
* The section name, non NULL terminated
*/
LPCWSTR UXINI_GetNextSection(PUXINI_FILE uf, DWORD *dwLen)
{
LPCWSTR lpLine;
while((lpLine = UXINI_GetNextLine(uf, dwLen))) {
/* Assuming a ']' ending to the section name */
if(lpLine[0] == '[') {
lpLine++;
*dwLen -= 2;
break;
}
}
return lpLine;
}
/**********************************************************************
* UXINI_FindSection
*
* Locate a section with the specified name, search starts
* at current location in ini file
* to start search from start, call UXINI_ResetINI
*
* PARAMS
* uf INI file to search, search starts at current location
* lpName Name of the section to locate
*
* RETURNS
* TRUE if section was found, FALSE otherwise
*/
BOOL UXINI_FindSection(PUXINI_FILE uf, LPCWSTR lpName)
{
LPCWSTR lpSection;
DWORD dwLen;
while((lpSection = UXINI_GetNextSection(uf, &dwLen))) {
if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpSection, dwLen, lpName, -1) == CSTR_EQUAL) {
return TRUE;
}
}
return FALSE;
}
/**********************************************************************
* UXINI_GetNextValue
*
* Locate the next value in the current section
*
* PARAMS
* uf INI file to search, search starts at current location
* dwNameLen Location to store pointer to value name length
* lpValue Location to store pointer to the value
* dwValueLen Location to store pointer to value length
*
* RETURNS
* The value name, non NULL terminated
*/
LPCWSTR UXINI_GetNextValue(PUXINI_FILE uf, DWORD *dwNameLen, LPCWSTR *lpValue, DWORD *dwValueLen)
{
LPCWSTR lpLine;
LPCWSTR lpLineEnd;
LPCWSTR name = NULL;
LPCWSTR value = NULL;
DWORD vallen = 0;
DWORD namelen = 0;
DWORD dwLen;
lpLine = UXINI_GetNextLine(uf, &dwLen);
if(!lpLine)
return NULL;
if(lpLine[0] == '[') {
UXINI_UnGetToLine(uf, lpLine);
return NULL;
}
lpLineEnd = lpLine + dwLen;
name = lpLine;
while(namelen < dwLen && *lpLine != '=') {
lpLine++;
namelen++;
}
if(*lpLine != '=') return NULL;
lpLine++;
/* Remove whitespace from end of name */
while(UXINI_isspace(name[namelen-1])) namelen--;
/* Remove whitespace from beginning of value */
while(UXINI_isspace(*lpLine) && lpLine < lpLineEnd) lpLine++;
value = lpLine;
vallen = dwLen-(value-name);
*dwNameLen = namelen;
*dwValueLen = vallen;
*lpValue = value;
return name;
}
/**********************************************************************
* UXINI_FindValue
*
* Locate a value by name
*
* PARAMS
* uf INI file to search, search starts at current location
* lpName Value name to locate
* lpValue Location to store pointer to the value
* dwValueLen Location to store pointer to value length
*
* RETURNS
* The value name, non NULL terminated
*/
BOOL UXINI_FindValue(PUXINI_FILE uf, LPCWSTR lpName, LPCWSTR *lpValue, DWORD *dwValueLen)
{
LPCWSTR name;
DWORD namelen;
while((name = UXINI_GetNextValue(uf, &namelen, lpValue, dwValueLen))) {
if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, name, namelen, lpName, -1) == CSTR_EQUAL) {
return TRUE;
}
}
return FALSE;
}

View File

@ -85,6 +85,6 @@ HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
ParseThemeIniFileProc callback, LPVOID lpData);
extern void UXTHEME_InitSystem(void);
extern void UXTHEME_InitSystem(HINSTANCE hInst);
#endif