1 /* 2 * Win32 5.1 uxtheme ini file processing 3 * 4 * Copyright (C) 2004 Kevin Koltzau 5 * 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. 10 * 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. 15 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "uxthemep.h" 22 23 /*********************************************************************** 24 * Defines and global variables 25 */ 26 27 static const WCHAR szTextFileResource[] = { 28 'T','E','X','T','F','I','L','E','\0' 29 }; 30 31 typedef struct _UXINI_FILE { 32 LPCWSTR lpIni; 33 LPCWSTR lpCurLoc; 34 LPCWSTR lpEnd; 35 } UXINI_FILE, *PUXINI_FILE; 36 37 /***********************************************************************/ 38 39 /********************************************************************** 40 * UXINI_LoadINI 41 * 42 * Load a theme INI file out of resources from the specified 43 * theme 44 * 45 * PARAMS 46 * tf Theme to load INI file out of resources 47 * lpName Resource name of the INI file 48 * 49 * RETURNS 50 * INI file, or NULL if not found 51 */ 52 PUXINI_FILE UXINI_LoadINI(HMODULE hTheme, LPCWSTR lpName) { 53 HRSRC hrsc; 54 LPCWSTR lpThemesIni = NULL; 55 PUXINI_FILE uf; 56 DWORD dwIniSize; 57 58 TRACE("Loading resource INI %s\n", debugstr_w(lpName)); 59 60 if((hrsc = FindResourceW(hTheme, lpName, szTextFileResource))) { 61 if(!(lpThemesIni = LoadResource(hTheme, hrsc))) { 62 TRACE("%s resource not found\n", debugstr_w(lpName)); 63 return NULL; 64 } 65 } 66 67 dwIniSize = SizeofResource(hTheme, hrsc) / sizeof(WCHAR); 68 uf = HeapAlloc(GetProcessHeap(), 0, sizeof(UXINI_FILE)); 69 uf->lpIni = lpThemesIni; 70 uf->lpCurLoc = lpThemesIni; 71 uf->lpEnd = lpThemesIni + dwIniSize; 72 return uf; 73 } 74 75 /********************************************************************** 76 * UXINI_CloseINI 77 * 78 * Close an open theme INI file 79 * 80 * PARAMS 81 * uf Theme INI file to close 82 */ 83 void UXINI_CloseINI(PUXINI_FILE uf) 84 { 85 HeapFree(GetProcessHeap(), 0, uf); 86 } 87 88 /********************************************************************** 89 * UXINI_eof 90 * 91 * Determines if we are at the end of the INI file 92 * 93 * PARAMS 94 * uf Theme INI file to test 95 */ 96 static inline BOOL UXINI_eof(PUXINI_FILE uf) 97 { 98 return uf->lpCurLoc >= uf->lpEnd; 99 } 100 101 /********************************************************************** 102 * UXINI_isspace 103 * 104 * Check if a character is a space character 105 * 106 * PARAMS 107 * c Character to test 108 */ 109 static inline BOOL UXINI_isspace(WCHAR c) 110 { 111 if (isspace(c)) return TRUE; 112 if (c=='\r') return TRUE; 113 return FALSE; 114 } 115 116 /********************************************************************** 117 * UXINI_GetNextLine 118 * 119 * Get the next line in the INI file, non NULL terminated 120 * removes whitespace at beginning and end of line, and removes comments 121 * 122 * PARAMS 123 * uf INI file to retrieve next line 124 * dwLen Location to store pointer to line length 125 * 126 * RETURNS 127 * The section name, non NULL terminated 128 */ 129 static LPCWSTR UXINI_GetNextLine(PUXINI_FILE uf, DWORD *dwLen) 130 { 131 LPCWSTR lpLineEnd; 132 LPCWSTR lpLineStart; 133 DWORD len; 134 do { 135 if(UXINI_eof(uf)) return NULL; 136 /* Skip whitespace and empty lines */ 137 while(!UXINI_eof(uf) && (UXINI_isspace(*uf->lpCurLoc) || *uf->lpCurLoc == '\n')) uf->lpCurLoc++; 138 lpLineStart = uf->lpCurLoc; 139 lpLineEnd = uf->lpCurLoc; 140 while(!UXINI_eof(uf) && *uf->lpCurLoc != '\n' && *uf->lpCurLoc != ';') lpLineEnd = ++uf->lpCurLoc; 141 /* If comment was found, skip the rest of the line */ 142 if(*uf->lpCurLoc == ';') 143 while(!UXINI_eof(uf) && *uf->lpCurLoc != '\n') uf->lpCurLoc++; 144 len = (lpLineEnd - lpLineStart); 145 if(*lpLineStart != ';' && len == 0) 146 return NULL; 147 } while(*lpLineStart == ';'); 148 /* Remove whitespace from end of line */ 149 while(UXINI_isspace(lpLineStart[len-1])) len--; 150 *dwLen = len; 151 152 return lpLineStart; 153 } 154 155 static inline void UXINI_UnGetToLine(PUXINI_FILE uf, LPCWSTR lpLine) 156 { 157 uf->lpCurLoc = lpLine; 158 } 159 160 /********************************************************************** 161 * UXINI_GetNextSection 162 * 163 * Locate the next section in the ini file, and return pointer to 164 * section name, non NULL terminated. Use dwLen to determine length 165 * 166 * PARAMS 167 * uf INI file to search, search starts at current location 168 * dwLen Location to store pointer to section name length 169 * 170 * RETURNS 171 * The section name, non NULL terminated 172 */ 173 LPCWSTR UXINI_GetNextSection(PUXINI_FILE uf, DWORD *dwLen) 174 { 175 LPCWSTR lpLine; 176 while((lpLine = UXINI_GetNextLine(uf, dwLen))) { 177 /* Assuming a ']' ending to the section name */ 178 if(lpLine[0] == '[') { 179 lpLine++; 180 *dwLen -= 2; 181 break; 182 } 183 } 184 return lpLine; 185 } 186 187 /********************************************************************** 188 * UXINI_FindSection 189 * 190 * Locate a section with the specified name, search starts 191 * at current location in ini file 192 * 193 * PARAMS 194 * uf INI file to search, search starts at current location 195 * lpName Name of the section to locate 196 * 197 * RETURNS 198 * TRUE if section was found, FALSE otherwise 199 */ 200 BOOL UXINI_FindSection(PUXINI_FILE uf, LPCWSTR lpName) 201 { 202 LPCWSTR lpSection; 203 DWORD dwLen; 204 while((lpSection = UXINI_GetNextSection(uf, &dwLen))) { 205 if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpSection, dwLen, lpName, -1) == CSTR_EQUAL) { 206 return TRUE; 207 } 208 } 209 return FALSE; 210 } 211 212 /********************************************************************** 213 * UXINI_GetNextValue 214 * 215 * Locate the next value in the current section 216 * 217 * PARAMS 218 * uf INI file to search, search starts at current location 219 * dwNameLen Location to store pointer to value name length 220 * lpValue Location to store pointer to the value 221 * dwValueLen Location to store pointer to value length 222 * 223 * RETURNS 224 * The value name, non NULL terminated 225 */ 226 LPCWSTR UXINI_GetNextValue(PUXINI_FILE uf, DWORD *dwNameLen, LPCWSTR *lpValue, DWORD *dwValueLen) 227 { 228 LPCWSTR lpLine; 229 LPCWSTR lpLineEnd; 230 LPCWSTR name = NULL; 231 LPCWSTR value = NULL; 232 DWORD vallen = 0; 233 DWORD namelen = 0; 234 DWORD dwLen; 235 lpLine = UXINI_GetNextLine(uf, &dwLen); 236 if(!lpLine) 237 return NULL; 238 if(lpLine[0] == '[') { 239 UXINI_UnGetToLine(uf, lpLine); 240 return NULL; 241 } 242 lpLineEnd = lpLine + dwLen; 243 244 name = lpLine; 245 while(namelen < dwLen && *lpLine != '=') { 246 lpLine++; 247 namelen++; 248 } 249 if(*lpLine != '=') return NULL; 250 lpLine++; 251 252 /* Remove whitespace from end of name */ 253 while(UXINI_isspace(name[namelen-1])) namelen--; 254 /* Remove whitespace from beginning of value */ 255 while(UXINI_isspace(*lpLine) && lpLine < lpLineEnd) lpLine++; 256 value = lpLine; 257 vallen = dwLen-(value-name); 258 259 *dwNameLen = namelen; 260 *dwValueLen = vallen; 261 *lpValue = value; 262 263 return name; 264 } 265 266 /********************************************************************** 267 * UXINI_FindValue 268 * 269 * Locate a value by name 270 * 271 * PARAMS 272 * uf INI file to search, search starts at current location 273 * lpName Value name to locate 274 * lpValue Location to store pointer to the value 275 * dwValueLen Location to store pointer to value length 276 * 277 * RETURNS 278 * The value name, non NULL terminated 279 */ 280 BOOL UXINI_FindValue(PUXINI_FILE uf, LPCWSTR lpName, LPCWSTR *lpValue, DWORD *dwValueLen) 281 { 282 LPCWSTR name; 283 DWORD namelen; 284 285 while((name = UXINI_GetNextValue(uf, &namelen, lpValue, dwValueLen))) { 286 if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, name, namelen, lpName, -1) == CSTR_EQUAL) { 287 return TRUE; 288 } 289 } 290 return FALSE; 291 } 292