2 * Win32 5.1 uxtheme ini file processing
4 * Copyright (C) 2004 Kevin Koltzau
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(uxtheme
);
34 /***********************************************************************
35 * Defines and global variables
38 static const WCHAR szTextFileResource
[] = {
39 'T','E','X','T','F','I','L','E','\0'
42 typedef struct _UXINI_FILE
{
46 } UXINI_FILE
, *PUXINI_FILE
;
48 /***********************************************************************/
50 /**********************************************************************
53 * Load a theme INI file out of resources from the specified
57 * tf Theme to load INI file out of resources
58 * lpName Resource name of the INI file
61 * INI file, or NULL if not found
63 PUXINI_FILE
UXINI_LoadINI(HMODULE hTheme
, LPCWSTR lpName
) {
65 LPCWSTR lpThemesIni
= NULL
;
69 TRACE("Loading resource INI %s\n", debugstr_w(lpName
));
71 if((hrsc
= FindResourceW(hTheme
, lpName
, szTextFileResource
))) {
72 if(!(lpThemesIni
= (LPCWSTR
)LoadResource(hTheme
, hrsc
))) {
73 TRACE("%s resource not found\n", debugstr_w(lpName
));
78 dwIniSize
= SizeofResource(hTheme
, hrsc
) / sizeof(WCHAR
);
79 uf
= HeapAlloc(GetProcessHeap(), 0, sizeof(UXINI_FILE
));
80 uf
->lpIni
= lpThemesIni
;
81 uf
->lpCurLoc
= lpThemesIni
;
82 uf
->lpEnd
= lpThemesIni
+ dwIniSize
;
86 /**********************************************************************
89 * Close an open theme INI file
92 * uf Theme INI file to close
94 void UXINI_CloseINI(PUXINI_FILE uf
)
96 HeapFree(GetProcessHeap(), 0, uf
);
99 /**********************************************************************
102 * Reset the current pointer into INI file to the beginning of the file
105 * uf Theme INI file to reset
107 void UXINI_ResetINI(PUXINI_FILE uf
)
109 uf
->lpCurLoc
= uf
->lpIni
;
112 /**********************************************************************
115 * Determines if we are at the end of the INI file
118 * uf Theme INI file to test
120 static inline BOOL
UXINI_eof(PUXINI_FILE uf
)
122 return uf
->lpCurLoc
>= uf
->lpEnd
;
125 /**********************************************************************
128 * Check if a character is a space character
131 * c Character to test
133 static inline BOOL
UXINI_isspace(WCHAR c
)
135 if (isspace(c
)) return TRUE
;
136 if (c
=='\r') return TRUE
;
140 /**********************************************************************
143 * Get the next line in the INI file, non NULL terminated
144 * removes whitespace at beginning and end of line, and removes comments
147 * uf INI file to retrieve next line
148 * dwLen Location to store pointer to line length
151 * The section name, non NULL terminated
153 static LPCWSTR
UXINI_GetNextLine(PUXINI_FILE uf
, DWORD
*dwLen
)
159 if(UXINI_eof(uf
)) return NULL
;
160 /* Skip whitespace and empty lines */
161 while(!UXINI_eof(uf
) && (UXINI_isspace(*uf
->lpCurLoc
) || *uf
->lpCurLoc
== '\n')) uf
->lpCurLoc
++;
162 lpLineStart
= uf
->lpCurLoc
;
163 lpLineEnd
= uf
->lpCurLoc
;
164 while(!UXINI_eof(uf
) && *uf
->lpCurLoc
!= '\n' && *uf
->lpCurLoc
!= ';') lpLineEnd
= ++uf
->lpCurLoc
;
165 /* If comment was found, skip the rest of the line */
166 if(*uf
->lpCurLoc
== ';')
167 while(!UXINI_eof(uf
) && *uf
->lpCurLoc
!= '\n') uf
->lpCurLoc
++;
168 len
= (lpLineEnd
- lpLineStart
);
169 if(*lpLineStart
!= ';' && len
== 0)
171 } while(*lpLineStart
== ';');
172 /* Remove whitespace from end of line */
173 while(UXINI_isspace(lpLineStart
[len
-1])) len
--;
179 static inline void UXINI_UnGetToLine(PUXINI_FILE uf
, LPCWSTR lpLine
)
181 uf
->lpCurLoc
= lpLine
;
184 /**********************************************************************
185 * UXINI_GetNextSection
187 * Locate the next section in the ini file, and return pointer to
188 * section name, non NULL terminated. Use dwLen to determine length
191 * uf INI file to search, search starts at current location
192 * dwLen Location to store pointer to section name length
195 * The section name, non NULL terminated
197 LPCWSTR
UXINI_GetNextSection(PUXINI_FILE uf
, DWORD
*dwLen
)
200 while((lpLine
= UXINI_GetNextLine(uf
, dwLen
))) {
201 /* Assuming a ']' ending to the section name */
202 if(lpLine
[0] == '[') {
211 /**********************************************************************
214 * Locate a section with the specified name, search starts
215 * at current location in ini file
216 * to start search from start, call UXINI_ResetINI
219 * uf INI file to search, search starts at current location
220 * lpName Name of the section to locate
223 * TRUE if section was found, FALSE otherwise
225 BOOL
UXINI_FindSection(PUXINI_FILE uf
, LPCWSTR lpName
)
229 while((lpSection
= UXINI_GetNextSection(uf
, &dwLen
))) {
230 if(CompareStringW(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
, lpSection
, dwLen
, lpName
, -1) == CSTR_EQUAL
) {
237 /**********************************************************************
240 * Locate the next value in the current section
243 * uf INI file to search, search starts at current location
244 * dwNameLen Location to store pointer to value name length
245 * lpValue Location to store pointer to the value
246 * dwValueLen Location to store pointer to value length
249 * The value name, non NULL terminated
251 LPCWSTR
UXINI_GetNextValue(PUXINI_FILE uf
, DWORD
*dwNameLen
, LPCWSTR
*lpValue
, DWORD
*dwValueLen
)
256 LPCWSTR value
= NULL
;
260 lpLine
= UXINI_GetNextLine(uf
, &dwLen
);
263 if(lpLine
[0] == '[') {
264 UXINI_UnGetToLine(uf
, lpLine
);
267 lpLineEnd
= lpLine
+ dwLen
;
270 while(namelen
< dwLen
&& *lpLine
!= '=') {
274 if(*lpLine
!= '=') return NULL
;
277 /* Remove whitespace from end of name */
278 while(UXINI_isspace(name
[namelen
-1])) namelen
--;
279 /* Remove whitespace from beginning of value */
280 while(UXINI_isspace(*lpLine
) && lpLine
< lpLineEnd
) lpLine
++;
282 vallen
= dwLen
-(value
-name
);
284 *dwNameLen
= namelen
;
285 *dwValueLen
= vallen
;
291 /**********************************************************************
294 * Locate a value by name
297 * uf INI file to search, search starts at current location
298 * lpName Value name to locate
299 * lpValue Location to store pointer to the value
300 * dwValueLen Location to store pointer to value length
303 * The value name, non NULL terminated
305 BOOL
UXINI_FindValue(PUXINI_FILE uf
, LPCWSTR lpName
, LPCWSTR
*lpValue
, DWORD
*dwValueLen
)
310 while((name
= UXINI_GetNextValue(uf
, &namelen
, lpValue
, dwValueLen
))) {
311 if(CompareStringW(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
, name
, namelen
, lpName
, -1) == CSTR_EQUAL
) {