Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsstyles.c
Go to the documentation of this file.
00001 /* 00002 * Win32 5.1 msstyles theme format 00003 * 00004 * Copyright (C) 2003 Kevin Koltzau 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "uxthemep.h" 00022 #include "wine/debug.h" 00023 #include "wine/unicode.h" 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); 00026 00027 /*********************************************************************** 00028 * Defines and global variables 00029 */ 00030 00031 static BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value); 00032 static BOOL MSSTYLES_GetNextToken(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LPWSTR lpBuff, DWORD buffSize); 00033 static void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics); 00034 static HRESULT MSSTYLES_GetFont (LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LOGFONTW* logfont); 00035 00036 extern HINSTANCE hDllInst; 00037 extern int alphaBlendMode; 00038 00039 #define MSSTYLES_VERSION 0x0003 00040 00041 static const WCHAR szThemesIniResource[] = { 00042 't','h','e','m','e','s','_','i','n','i','\0' 00043 }; 00044 00045 static PTHEME_FILE tfActiveTheme; 00046 00047 /***********************************************************************/ 00048 00049 /********************************************************************** 00050 * MSSTYLES_OpenThemeFile 00051 * 00052 * Load and validate a theme 00053 * 00054 * PARAMS 00055 * lpThemeFile Path to theme file to load 00056 * pszColorName Color name wanted, can be NULL 00057 * pszSizeName Size name wanted, can be NULL 00058 * 00059 * NOTES 00060 * If pszColorName or pszSizeName are NULL, the default color/size will be used. 00061 * If one/both are provided, they are validated against valid color/sizes and if 00062 * a match is not found, the function fails. 00063 */ 00064 HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf) 00065 { 00066 HMODULE hTheme; 00067 HRSRC hrsc; 00068 HRESULT hr = S_OK; 00069 static const WCHAR szPackThemVersionResource[] = { 00070 'P','A','C','K','T','H','E','M','_','V','E','R','S','I','O','N', '\0' 00071 }; 00072 static const WCHAR szColorNamesResource[] = { 00073 'C','O','L','O','R','N','A','M','E','S','\0' 00074 }; 00075 static const WCHAR szSizeNamesResource[] = { 00076 'S','I','Z','E','N','A','M','E','S','\0' 00077 }; 00078 00079 WORD version; 00080 DWORD versize; 00081 LPWSTR pszColors; 00082 LPWSTR pszSelectedColor = NULL; 00083 LPWSTR pszSizes; 00084 LPWSTR pszSelectedSize = NULL; 00085 LPWSTR tmp; 00086 00087 TRACE("Opening %s\n", debugstr_w(lpThemeFile)); 00088 00089 hTheme = LoadLibraryExW(lpThemeFile, NULL, LOAD_LIBRARY_AS_DATAFILE); 00090 00091 /* Validate that this is really a theme */ 00092 if(!hTheme) { 00093 hr = HRESULT_FROM_WIN32(GetLastError()); 00094 goto invalid_theme; 00095 } 00096 if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szPackThemVersionResource))) { 00097 TRACE("No version resource found\n"); 00098 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); 00099 goto invalid_theme; 00100 } 00101 if((versize = SizeofResource(hTheme, hrsc)) != 2) 00102 { 00103 TRACE("Version resource found, but wrong size: %d\n", versize); 00104 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); 00105 goto invalid_theme; 00106 } 00107 version = *(WORD*)LoadResource(hTheme, hrsc); 00108 if(version != MSSTYLES_VERSION) 00109 { 00110 TRACE("Version of theme file is unsupported: 0x%04x\n", version); 00111 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); 00112 goto invalid_theme; 00113 } 00114 00115 if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szColorNamesResource))) { 00116 TRACE("Color names resource not found\n"); 00117 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); 00118 goto invalid_theme; 00119 } 00120 pszColors = LoadResource(hTheme, hrsc); 00121 00122 if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szSizeNamesResource))) { 00123 TRACE("Size names resource not found\n"); 00124 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); 00125 goto invalid_theme; 00126 } 00127 pszSizes = LoadResource(hTheme, hrsc); 00128 00129 /* Validate requested color against what's available from the theme */ 00130 if(pszColorName) { 00131 tmp = pszColors; 00132 while(*tmp) { 00133 if(!lstrcmpiW(pszColorName, tmp)) { 00134 pszSelectedColor = tmp; 00135 break; 00136 } 00137 tmp += lstrlenW(tmp)+1; 00138 } 00139 } 00140 else 00141 pszSelectedColor = pszColors; /* Use the default color */ 00142 00143 /* Validate requested size against what's available from the theme */ 00144 if(pszSizeName) { 00145 tmp = pszSizes; 00146 while(*tmp) { 00147 if(!lstrcmpiW(pszSizeName, tmp)) { 00148 pszSelectedSize = tmp; 00149 break; 00150 } 00151 tmp += lstrlenW(tmp)+1; 00152 } 00153 } 00154 else 00155 pszSelectedSize = pszSizes; /* Use the default size */ 00156 00157 if(!pszSelectedColor || !pszSelectedSize) { 00158 TRACE("Requested color/size (%s/%s) not found in theme\n", 00159 debugstr_w(pszColorName), debugstr_w(pszSizeName)); 00160 hr = E_PROP_ID_UNSUPPORTED; 00161 goto invalid_theme; 00162 } 00163 00164 *tf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THEME_FILE)); 00165 (*tf)->hTheme = hTheme; 00166 00167 GetFullPathNameW(lpThemeFile, MAX_PATH, (*tf)->szThemeFile, NULL); 00168 00169 (*tf)->pszAvailColors = pszColors; 00170 (*tf)->pszAvailSizes = pszSizes; 00171 (*tf)->pszSelectedColor = pszSelectedColor; 00172 (*tf)->pszSelectedSize = pszSelectedSize; 00173 (*tf)->dwRefCount = 1; 00174 return S_OK; 00175 00176 invalid_theme: 00177 if(hTheme) FreeLibrary(hTheme); 00178 return hr; 00179 } 00180 00181 /*********************************************************************** 00182 * MSSTYLES_CloseThemeFile 00183 * 00184 * Close theme file and free resources 00185 */ 00186 void MSSTYLES_CloseThemeFile(PTHEME_FILE tf) 00187 { 00188 if(tf) { 00189 tf->dwRefCount--; 00190 if(!tf->dwRefCount) { 00191 if(tf->hTheme) FreeLibrary(tf->hTheme); 00192 if(tf->classes) { 00193 while(tf->classes) { 00194 PTHEME_CLASS pcls = tf->classes; 00195 tf->classes = pcls->next; 00196 while(pcls->partstate) { 00197 PTHEME_PARTSTATE ps = pcls->partstate; 00198 pcls->partstate = ps->next; 00199 HeapFree(GetProcessHeap(), 0, ps); 00200 } 00201 HeapFree(GetProcessHeap(), 0, pcls); 00202 } 00203 } 00204 while (tf->images) 00205 { 00206 PTHEME_IMAGE img = tf->images; 00207 tf->images = img->next; 00208 DeleteObject (img->image); 00209 HeapFree (GetProcessHeap(), 0, img); 00210 } 00211 HeapFree(GetProcessHeap(), 0, tf); 00212 } 00213 } 00214 } 00215 00216 /*********************************************************************** 00217 * MSSTYLES_SetActiveTheme 00218 * 00219 * Set the current active theme 00220 */ 00221 HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf, BOOL setMetrics) 00222 { 00223 if(tfActiveTheme) 00224 MSSTYLES_CloseThemeFile(tfActiveTheme); 00225 tfActiveTheme = tf; 00226 if (tfActiveTheme) 00227 { 00228 tfActiveTheme->dwRefCount++; 00229 if(!tfActiveTheme->classes) 00230 MSSTYLES_ParseThemeIni(tfActiveTheme, setMetrics); 00231 } 00232 return S_OK; 00233 } 00234 00235 /*********************************************************************** 00236 * MSSTYLES_GetThemeIni 00237 * 00238 * Retrieves themes.ini from a theme 00239 */ 00240 PUXINI_FILE MSSTYLES_GetThemeIni(PTHEME_FILE tf) 00241 { 00242 return UXINI_LoadINI(tf->hTheme, szThemesIniResource); 00243 } 00244 00245 /*********************************************************************** 00246 * MSSTYLES_GetActiveThemeIni 00247 * 00248 * Retrieve the ini file for the selected color/style 00249 */ 00250 static PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf) 00251 { 00252 static const WCHAR szFileResNamesResource[] = { 00253 'F','I','L','E','R','E','S','N','A','M','E','S','\0' 00254 }; 00255 DWORD dwColorCount = 0; 00256 DWORD dwSizeCount = 0; 00257 DWORD dwColorNum = 0; 00258 DWORD dwSizeNum = 0; 00259 DWORD i; 00260 DWORD dwResourceIndex; 00261 LPWSTR tmp; 00262 HRSRC hrsc; 00263 00264 /* Count the number of available colors & styles, and determine the index number 00265 of the color/style we are interested in 00266 */ 00267 tmp = tf->pszAvailColors; 00268 while(*tmp) { 00269 if(!lstrcmpiW(tf->pszSelectedColor, tmp)) 00270 dwColorNum = dwColorCount; 00271 tmp += lstrlenW(tmp)+1; 00272 dwColorCount++; 00273 } 00274 tmp = tf->pszAvailSizes; 00275 while(*tmp) { 00276 if(!lstrcmpiW(tf->pszSelectedSize, tmp)) 00277 dwSizeNum = dwSizeCount; 00278 tmp += lstrlenW(tmp)+1; 00279 dwSizeCount++; 00280 } 00281 00282 if(!(hrsc = FindResourceW(tf->hTheme, MAKEINTRESOURCEW(1), szFileResNamesResource))) { 00283 TRACE("FILERESNAMES map not found\n"); 00284 return NULL; 00285 } 00286 tmp = LoadResource(tf->hTheme, hrsc); 00287 dwResourceIndex = (dwSizeCount * dwColorNum) + dwSizeNum; 00288 for(i=0; i < dwResourceIndex; i++) { 00289 tmp += lstrlenW(tmp)+1; 00290 } 00291 return UXINI_LoadINI(tf->hTheme, tmp); 00292 } 00293 00294 00295 /*********************************************************************** 00296 * MSSTYLES_ParseIniSectionName 00297 * 00298 * Parse an ini section name into its component parts 00299 * Valid formats are: 00300 * [classname] 00301 * [classname(state)] 00302 * [classname.part] 00303 * [classname.part(state)] 00304 * [application::classname] 00305 * [application::classname(state)] 00306 * [application::classname.part] 00307 * [application::classname.part(state)] 00308 * 00309 * PARAMS 00310 * lpSection Section name 00311 * dwLen Length of section name 00312 * szAppName Location to store application name 00313 * szClassName Location to store class name 00314 * iPartId Location to store part id 00315 * iStateId Location to store state id 00316 */ 00317 static BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD dwLen, LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int *iStateId) 00318 { 00319 WCHAR sec[255]; 00320 WCHAR part[60] = {'\0'}; 00321 WCHAR state[60] = {'\0'}; 00322 LPWSTR tmp; 00323 LPWSTR comp; 00324 lstrcpynW(sec, lpSection, min(dwLen+1, sizeof(sec)/sizeof(sec[0]))); 00325 00326 *szAppName = 0; 00327 *szClassName = 0; 00328 *iPartId = 0; 00329 *iStateId = 0; 00330 comp = sec; 00331 /* Get the application name */ 00332 tmp = strchrW(comp, ':'); 00333 if(tmp) { 00334 *tmp++ = 0; 00335 tmp++; 00336 lstrcpynW(szAppName, comp, MAX_THEME_APP_NAME); 00337 comp = tmp; 00338 } 00339 00340 tmp = strchrW(comp, '.'); 00341 if(tmp) { 00342 *tmp++ = 0; 00343 lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME); 00344 comp = tmp; 00345 /* now get the part & state */ 00346 tmp = strchrW(comp, '('); 00347 if(tmp) { 00348 *tmp++ = 0; 00349 lstrcpynW(part, comp, sizeof(part)/sizeof(part[0])); 00350 comp = tmp; 00351 /* now get the state */ 00352 tmp = strchrW(comp, ')'); 00353 if (!tmp) 00354 return FALSE; 00355 *tmp = 0; 00356 lstrcpynW(state, comp, sizeof(state)/sizeof(state[0])); 00357 } 00358 else { 00359 lstrcpynW(part, comp, sizeof(part)/sizeof(part[0])); 00360 } 00361 } 00362 else { 00363 tmp = strchrW(comp, '('); 00364 if(tmp) { 00365 *tmp++ = 0; 00366 lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME); 00367 comp = tmp; 00368 /* now get the state */ 00369 tmp = strchrW(comp, ')'); 00370 if (!tmp) 00371 return FALSE; 00372 *tmp = 0; 00373 lstrcpynW(state, comp, sizeof(state)/sizeof(state[0])); 00374 } 00375 else { 00376 lstrcpynW(szClassName, comp, MAX_THEME_CLASS_NAME); 00377 } 00378 } 00379 if(!*szClassName) return FALSE; 00380 return MSSTYLES_LookupPartState(szClassName, part[0]?part:NULL, state[0]?state:NULL, iPartId, iStateId); 00381 } 00382 00383 /*********************************************************************** 00384 * MSSTYLES_FindClass 00385 * 00386 * Find a class 00387 * 00388 * PARAMS 00389 * tf Theme file 00390 * pszAppName App name to find 00391 * pszClassName Class name to find 00392 * 00393 * RETURNS 00394 * The class found, or NULL 00395 */ 00396 static PTHEME_CLASS MSSTYLES_FindClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName) 00397 { 00398 PTHEME_CLASS cur = tf->classes; 00399 while(cur) { 00400 if(!pszAppName) { 00401 if(!*cur->szAppName && !lstrcmpiW(pszClassName, cur->szClassName)) 00402 return cur; 00403 } 00404 else { 00405 if(!lstrcmpiW(pszAppName, cur->szAppName) && !lstrcmpiW(pszClassName, cur->szClassName)) 00406 return cur; 00407 } 00408 cur = cur->next; 00409 } 00410 return NULL; 00411 } 00412 00413 /*********************************************************************** 00414 * MSSTYLES_AddClass 00415 * 00416 * Add a class to a theme file 00417 * 00418 * PARAMS 00419 * tf Theme file 00420 * pszAppName App name to add 00421 * pszClassName Class name to add 00422 * 00423 * RETURNS 00424 * The class added, or a class previously added with the same name 00425 */ 00426 static PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName) 00427 { 00428 PTHEME_CLASS cur = MSSTYLES_FindClass(tf, pszAppName, pszClassName); 00429 if(cur) return cur; 00430 00431 cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_CLASS)); 00432 cur->hTheme = tf->hTheme; 00433 lstrcpyW(cur->szAppName, pszAppName); 00434 lstrcpyW(cur->szClassName, pszClassName); 00435 cur->next = tf->classes; 00436 cur->partstate = NULL; 00437 cur->overrides = NULL; 00438 tf->classes = cur; 00439 return cur; 00440 } 00441 00442 /*********************************************************************** 00443 * MSSTYLES_FindPartState 00444 * 00445 * Find a part/state 00446 * 00447 * PARAMS 00448 * tc Class to search 00449 * iPartId Part ID to find 00450 * iStateId State ID to find 00451 * tcNext Receives the next class in the override chain 00452 * 00453 * RETURNS 00454 * The part/state found, or NULL 00455 */ 00456 PTHEME_PARTSTATE MSSTYLES_FindPartState(PTHEME_CLASS tc, int iPartId, int iStateId, PTHEME_CLASS *tcNext) 00457 { 00458 PTHEME_PARTSTATE cur = tc->partstate; 00459 while(cur) { 00460 if(cur->iPartId == iPartId && cur->iStateId == iStateId) { 00461 if(tcNext) *tcNext = tc->overrides; 00462 return cur; 00463 } 00464 cur = cur->next; 00465 } 00466 if(tc->overrides) return MSSTYLES_FindPartState(tc->overrides, iPartId, iStateId, tcNext); 00467 return NULL; 00468 } 00469 00470 /*********************************************************************** 00471 * MSSTYLES_AddPartState 00472 * 00473 * Add a part/state to a class 00474 * 00475 * PARAMS 00476 * tc Theme class 00477 * iPartId Part ID to add 00478 * iStateId State ID to add 00479 * 00480 * RETURNS 00481 * The part/state added, or a part/state previously added with the same IDs 00482 */ 00483 static PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int iPartId, int iStateId) 00484 { 00485 PTHEME_PARTSTATE cur = MSSTYLES_FindPartState(tc, iPartId, iStateId, NULL); 00486 if(cur) return cur; 00487 00488 cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PARTSTATE)); 00489 cur->iPartId = iPartId; 00490 cur->iStateId = iStateId; 00491 cur->properties = NULL; 00492 cur->next = tc->partstate; 00493 tc->partstate = cur; 00494 return cur; 00495 } 00496 00497 /*********************************************************************** 00498 * MSSTYLES_LFindProperty 00499 * 00500 * Find a property within a property list 00501 * 00502 * PARAMS 00503 * tp property list to scan 00504 * iPropertyPrimitive Type of value expected 00505 * iPropertyId ID of the required value 00506 * 00507 * RETURNS 00508 * The property found, or NULL 00509 */ 00510 static PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int iPropertyPrimitive, int iPropertyId) 00511 { 00512 PTHEME_PROPERTY cur = tp; 00513 while(cur) { 00514 if(cur->iPropertyId == iPropertyId) { 00515 if(cur->iPrimitiveType == iPropertyPrimitive) { 00516 return cur; 00517 } 00518 else { 00519 if(!iPropertyPrimitive) 00520 return cur; 00521 return NULL; 00522 } 00523 } 00524 cur = cur->next; 00525 } 00526 return NULL; 00527 } 00528 00529 /*********************************************************************** 00530 * MSSTYLES_PSFindProperty 00531 * 00532 * Find a value within a part/state 00533 * 00534 * PARAMS 00535 * ps Part/state to search 00536 * iPropertyPrimitive Type of value expected 00537 * iPropertyId ID of the required value 00538 * 00539 * RETURNS 00540 * The property found, or NULL 00541 */ 00542 static inline PTHEME_PROPERTY MSSTYLES_PSFindProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId) 00543 { 00544 return MSSTYLES_LFindProperty(ps->properties, iPropertyPrimitive, iPropertyId); 00545 } 00546 00547 /*********************************************************************** 00548 * MSSTYLES_FFindMetric 00549 * 00550 * Find a metric property for a theme file 00551 * 00552 * PARAMS 00553 * tf Theme file 00554 * iPropertyPrimitive Type of value expected 00555 * iPropertyId ID of the required value 00556 * 00557 * RETURNS 00558 * The property found, or NULL 00559 */ 00560 static inline PTHEME_PROPERTY MSSTYLES_FFindMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId) 00561 { 00562 return MSSTYLES_LFindProperty(tf->metrics, iPropertyPrimitive, iPropertyId); 00563 } 00564 00565 /*********************************************************************** 00566 * MSSTYLES_FindMetric 00567 * 00568 * Find a metric property for the current installed theme 00569 * 00570 * PARAMS 00571 * tf Theme file 00572 * iPropertyPrimitive Type of value expected 00573 * iPropertyId ID of the required value 00574 * 00575 * RETURNS 00576 * The property found, or NULL 00577 */ 00578 PTHEME_PROPERTY MSSTYLES_FindMetric(int iPropertyPrimitive, int iPropertyId) 00579 { 00580 if(!tfActiveTheme) return NULL; 00581 return MSSTYLES_FFindMetric(tfActiveTheme, iPropertyPrimitive, iPropertyId); 00582 } 00583 00584 /*********************************************************************** 00585 * MSSTYLES_AddProperty 00586 * 00587 * Add a property to a part/state 00588 * 00589 * PARAMS 00590 * ps Part/state 00591 * iPropertyPrimitive Primitive type of the property 00592 * iPropertyId ID of the property 00593 * lpValue Raw value (non-NULL terminated) 00594 * dwValueLen Length of the value 00595 * 00596 * RETURNS 00597 * The property added, or a property previously added with the same IDs 00598 */ 00599 static PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen, BOOL isGlobal) 00600 { 00601 PTHEME_PROPERTY cur = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId); 00602 /* Should duplicate properties overwrite the original, or be ignored? */ 00603 if(cur) return cur; 00604 00605 cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PROPERTY)); 00606 cur->iPrimitiveType = iPropertyPrimitive; 00607 cur->iPropertyId = iPropertyId; 00608 cur->lpValue = lpValue; 00609 cur->dwValueLen = dwValueLen; 00610 00611 if(ps->iStateId) 00612 cur->origin = PO_STATE; 00613 else if(ps->iPartId) 00614 cur->origin = PO_PART; 00615 else if(isGlobal) 00616 cur->origin = PO_GLOBAL; 00617 else 00618 cur->origin = PO_CLASS; 00619 00620 cur->next = ps->properties; 00621 ps->properties = cur; 00622 return cur; 00623 } 00624 00625 /*********************************************************************** 00626 * MSSTYLES_AddMetric 00627 * 00628 * Add a property to a part/state 00629 * 00630 * PARAMS 00631 * tf Theme file 00632 * iPropertyPrimitive Primitive type of the property 00633 * iPropertyId ID of the property 00634 * lpValue Raw value (non-NULL terminated) 00635 * dwValueLen Length of the value 00636 * 00637 * RETURNS 00638 * The property added, or a property previously added with the same IDs 00639 */ 00640 static PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen) 00641 { 00642 PTHEME_PROPERTY cur = MSSTYLES_FFindMetric(tf, iPropertyPrimitive, iPropertyId); 00643 /* Should duplicate properties overwrite the original, or be ignored? */ 00644 if(cur) return cur; 00645 00646 cur = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_PROPERTY)); 00647 cur->iPrimitiveType = iPropertyPrimitive; 00648 cur->iPropertyId = iPropertyId; 00649 cur->lpValue = lpValue; 00650 cur->dwValueLen = dwValueLen; 00651 00652 cur->origin = PO_GLOBAL; 00653 00654 cur->next = tf->metrics; 00655 tf->metrics = cur; 00656 return cur; 00657 } 00658 00659 /* Color-related state for theme ini parsing */ 00660 struct PARSECOLORSTATE 00661 { 00662 int colorCount; 00663 int colorElements[TMT_LASTCOLOR-TMT_FIRSTCOLOR]; 00664 COLORREF colorRgb[TMT_LASTCOLOR-TMT_FIRSTCOLOR]; 00665 int captionColors; 00666 }; 00667 00668 static inline void parse_init_color (struct PARSECOLORSTATE* state) 00669 { 00670 memset (state, 0, sizeof (*state)); 00671 } 00672 00673 static BOOL parse_handle_color_property (struct PARSECOLORSTATE* state, 00674 int iPropertyId, LPCWSTR lpValue, 00675 DWORD dwValueLen) 00676 { 00677 int r,g,b; 00678 LPCWSTR lpValueEnd = lpValue + dwValueLen; 00679 if(MSSTYLES_GetNextInteger(lpValue, lpValueEnd, &lpValue, &r) && 00680 MSSTYLES_GetNextInteger(lpValue, lpValueEnd, &lpValue, &g) && 00681 MSSTYLES_GetNextInteger(lpValue, lpValueEnd, &lpValue, &b)) { 00682 state->colorElements[state->colorCount] = iPropertyId - TMT_FIRSTCOLOR; 00683 state->colorRgb[state->colorCount++] = RGB(r,g,b); 00684 switch (iPropertyId) 00685 { 00686 case TMT_ACTIVECAPTION: 00687 state->captionColors |= 0x1; 00688 break; 00689 case TMT_INACTIVECAPTION: 00690 state->captionColors |= 0x2; 00691 break; 00692 case TMT_GRADIENTACTIVECAPTION: 00693 state->captionColors |= 0x4; 00694 break; 00695 case TMT_GRADIENTINACTIVECAPTION: 00696 state->captionColors |= 0x8; 00697 break; 00698 } 00699 return TRUE; 00700 } 00701 else { 00702 return FALSE; 00703 } 00704 } 00705 00706 static void parse_apply_color (struct PARSECOLORSTATE* state) 00707 { 00708 if (state->colorCount > 0) 00709 SetSysColors(state->colorCount, state->colorElements, state->colorRgb); 00710 if (state->captionColors == 0xf) 00711 SystemParametersInfoW (SPI_SETGRADIENTCAPTIONS, 0, (PVOID)TRUE, 0); 00712 } 00713 00714 /* Non-client-metrics-related state for theme ini parsing */ 00715 struct PARSENONCLIENTSTATE 00716 { 00717 NONCLIENTMETRICSW metrics; 00718 BOOL metricsDirty; 00719 LOGFONTW iconTitleFont; 00720 }; 00721 00722 static inline void parse_init_nonclient (struct PARSENONCLIENTSTATE* state) 00723 { 00724 memset (state, 0, sizeof (*state)); 00725 state->metrics.cbSize = sizeof (NONCLIENTMETRICSW); 00726 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof (NONCLIENTMETRICSW), 00727 &state->metrics, 0); 00728 SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof (LOGFONTW), 00729 &state->iconTitleFont, 0); 00730 } 00731 00732 static BOOL parse_handle_nonclient_font (struct PARSENONCLIENTSTATE* state, 00733 int iPropertyId, LPCWSTR lpValue, 00734 DWORD dwValueLen) 00735 { 00736 LOGFONTW font; 00737 00738 memset (&font, 0, sizeof (font)); 00739 if (SUCCEEDED (MSSTYLES_GetFont (lpValue, lpValue + dwValueLen, &lpValue, 00740 &font))) 00741 { 00742 switch (iPropertyId) 00743 { 00744 case TMT_CAPTIONFONT: 00745 state->metrics.lfCaptionFont = font; 00746 state->metricsDirty = TRUE; 00747 break; 00748 case TMT_SMALLCAPTIONFONT: 00749 state->metrics.lfSmCaptionFont = font; 00750 state->metricsDirty = TRUE; 00751 break; 00752 case TMT_MENUFONT: 00753 state->metrics.lfMenuFont = font; 00754 state->metricsDirty = TRUE; 00755 break; 00756 case TMT_STATUSFONT: 00757 state->metrics.lfStatusFont = font; 00758 state->metricsDirty = TRUE; 00759 break; 00760 case TMT_MSGBOXFONT: 00761 state->metrics.lfMessageFont = font; 00762 state->metricsDirty = TRUE; 00763 break; 00764 case TMT_ICONTITLEFONT: 00765 state->iconTitleFont = font; 00766 state->metricsDirty = TRUE; 00767 break; 00768 } 00769 return TRUE; 00770 } 00771 else 00772 return FALSE; 00773 } 00774 00775 static BOOL parse_handle_nonclient_size (struct PARSENONCLIENTSTATE* state, 00776 int iPropertyId, LPCWSTR lpValue, 00777 DWORD dwValueLen) 00778 { 00779 int size; 00780 LPCWSTR lpValueEnd = lpValue + dwValueLen; 00781 if(MSSTYLES_GetNextInteger(lpValue, lpValueEnd, &lpValue, &size)) { 00782 switch (iPropertyId) 00783 { 00784 case TMT_SIZINGBORDERWIDTH: 00785 state->metrics.iBorderWidth = size; 00786 state->metricsDirty = TRUE; 00787 break; 00788 case TMT_SCROLLBARWIDTH: 00789 state->metrics.iScrollWidth = size; 00790 state->metricsDirty = TRUE; 00791 break; 00792 case TMT_SCROLLBARHEIGHT: 00793 state->metrics.iScrollHeight = size; 00794 state->metricsDirty = TRUE; 00795 break; 00796 case TMT_CAPTIONBARWIDTH: 00797 state->metrics.iCaptionWidth = size; 00798 state->metricsDirty = TRUE; 00799 break; 00800 case TMT_CAPTIONBARHEIGHT: 00801 state->metrics.iCaptionHeight = size; 00802 state->metricsDirty = TRUE; 00803 break; 00804 case TMT_SMCAPTIONBARWIDTH: 00805 state->metrics.iSmCaptionWidth = size; 00806 state->metricsDirty = TRUE; 00807 break; 00808 case TMT_SMCAPTIONBARHEIGHT: 00809 state->metrics.iSmCaptionHeight = size; 00810 state->metricsDirty = TRUE; 00811 break; 00812 case TMT_MENUBARWIDTH: 00813 state->metrics.iMenuWidth = size; 00814 state->metricsDirty = TRUE; 00815 break; 00816 case TMT_MENUBARHEIGHT: 00817 state->metrics.iMenuHeight = size; 00818 state->metricsDirty = TRUE; 00819 break; 00820 } 00821 return TRUE; 00822 } 00823 else 00824 return FALSE; 00825 } 00826 00827 static void parse_apply_nonclient (struct PARSENONCLIENTSTATE* state) 00828 { 00829 if (state->metricsDirty) 00830 { 00831 SystemParametersInfoW (SPI_SETNONCLIENTMETRICS, sizeof (state->metrics), 00832 &state->metrics, 0); 00833 SystemParametersInfoW (SPI_SETICONTITLELOGFONT, sizeof (state->iconTitleFont), 00834 &state->iconTitleFont, 0); 00835 } 00836 } 00837 00838 /*********************************************************************** 00839 * MSSTYLES_ParseThemeIni 00840 * 00841 * Parse the theme ini for the selected color/style 00842 * 00843 * PARAMS 00844 * tf Theme to parse 00845 */ 00846 static void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) 00847 { 00848 static const WCHAR szSysMetrics[] = {'S','y','s','M','e','t','r','i','c','s','\0'}; 00849 static const WCHAR szGlobals[] = {'g','l','o','b','a','l','s','\0'}; 00850 PTHEME_CLASS cls; 00851 PTHEME_CLASS globals; 00852 PTHEME_PARTSTATE ps; 00853 PUXINI_FILE ini; 00854 WCHAR szAppName[MAX_THEME_APP_NAME]; 00855 WCHAR szClassName[MAX_THEME_CLASS_NAME]; 00856 WCHAR szPropertyName[MAX_THEME_VALUE_NAME]; 00857 int iPartId; 00858 int iStateId; 00859 int iPropertyPrimitive; 00860 int iPropertyId; 00861 DWORD dwLen; 00862 LPCWSTR lpName; 00863 DWORD dwValueLen; 00864 LPCWSTR lpValue; 00865 00866 ini = MSSTYLES_GetActiveThemeIni(tf); 00867 00868 while((lpName=UXINI_GetNextSection(ini, &dwLen))) { 00869 if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpName, dwLen, szSysMetrics, -1) == CSTR_EQUAL) { 00870 struct PARSECOLORSTATE colorState; 00871 struct PARSENONCLIENTSTATE nonClientState; 00872 00873 parse_init_color (&colorState); 00874 parse_init_nonclient (&nonClientState); 00875 00876 while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen))) { 00877 lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0]))); 00878 if(MSSTYLES_LookupProperty(szPropertyName, &iPropertyPrimitive, &iPropertyId)) { 00879 if(iPropertyId >= TMT_FIRSTCOLOR && iPropertyId <= TMT_LASTCOLOR) { 00880 if (!parse_handle_color_property (&colorState, iPropertyId, 00881 lpValue, dwValueLen)) 00882 FIXME("Invalid color value for %s\n", 00883 debugstr_w(szPropertyName)); 00884 } 00885 else if (setMetrics && (iPropertyId == TMT_FLATMENUS)) { 00886 BOOL flatMenus = (*lpValue == 'T') || (*lpValue == 't'); 00887 SystemParametersInfoW (SPI_SETFLATMENU, 0, (PVOID)(INT_PTR)flatMenus, 0); 00888 } 00889 else if ((iPropertyId >= TMT_FIRSTFONT) 00890 && (iPropertyId <= TMT_LASTFONT)) 00891 { 00892 if (!parse_handle_nonclient_font (&nonClientState, 00893 iPropertyId, lpValue, dwValueLen)) 00894 FIXME("Invalid font value for %s\n", 00895 debugstr_w(szPropertyName)); 00896 } 00897 else if ((iPropertyId >= TMT_FIRSTSIZE) 00898 && (iPropertyId <= TMT_LASTSIZE)) 00899 { 00900 if (!parse_handle_nonclient_size (&nonClientState, 00901 iPropertyId, lpValue, dwValueLen)) 00902 FIXME("Invalid size value for %s\n", 00903 debugstr_w(szPropertyName)); 00904 } 00905 /* Catch all metrics, including colors */ 00906 MSSTYLES_AddMetric(tf, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen); 00907 } 00908 else { 00909 TRACE("Unknown system metric %s\n", debugstr_w(szPropertyName)); 00910 } 00911 } 00912 if (setMetrics) 00913 { 00914 parse_apply_color (&colorState); 00915 parse_apply_nonclient (&nonClientState); 00916 } 00917 continue; 00918 } 00919 if(MSSTYLES_ParseIniSectionName(lpName, dwLen, szAppName, szClassName, &iPartId, &iStateId)) { 00920 BOOL isGlobal = FALSE; 00921 if(!lstrcmpiW(szClassName, szGlobals)) { 00922 isGlobal = TRUE; 00923 } 00924 cls = MSSTYLES_AddClass(tf, szAppName, szClassName); 00925 ps = MSSTYLES_AddPartState(cls, iPartId, iStateId); 00926 00927 while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen))) { 00928 lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0]))); 00929 if(MSSTYLES_LookupProperty(szPropertyName, &iPropertyPrimitive, &iPropertyId)) { 00930 MSSTYLES_AddProperty(ps, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen, isGlobal); 00931 } 00932 else { 00933 TRACE("Unknown property %s\n", debugstr_w(szPropertyName)); 00934 } 00935 } 00936 } 00937 } 00938 00939 /* App/Class combos override values defined by the base class, map these overrides */ 00940 globals = MSSTYLES_FindClass(tf, NULL, szGlobals); 00941 cls = tf->classes; 00942 while(cls) { 00943 if(*cls->szAppName) { 00944 cls->overrides = MSSTYLES_FindClass(tf, NULL, cls->szClassName); 00945 if(!cls->overrides) { 00946 TRACE("No overrides found for app %s class %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName)); 00947 } 00948 else { 00949 cls->overrides = globals; 00950 } 00951 } 00952 else { 00953 /* Everything overrides globals..except globals */ 00954 if(cls != globals) cls->overrides = globals; 00955 } 00956 cls = cls->next; 00957 } 00958 UXINI_CloseINI(ini); 00959 00960 if(!tf->classes) { 00961 ERR("Failed to parse theme ini\n"); 00962 } 00963 } 00964 00965 /*********************************************************************** 00966 * MSSTYLES_OpenThemeClass 00967 * 00968 * Open a theme class, uses the current active theme 00969 * 00970 * PARAMS 00971 * pszAppName Application name, for theme styles specific 00972 * to a particular application 00973 * pszClassList List of requested classes, semicolon delimited 00974 */ 00975 PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList) 00976 { 00977 PTHEME_CLASS cls = NULL; 00978 WCHAR szClassName[MAX_THEME_CLASS_NAME]; 00979 LPCWSTR start; 00980 LPCWSTR end; 00981 DWORD len; 00982 00983 if(!tfActiveTheme) { 00984 TRACE("there is no active theme\n"); 00985 return NULL; 00986 } 00987 if(!tfActiveTheme->classes) { 00988 return NULL; 00989 } 00990 00991 start = pszClassList; 00992 while((end = strchrW(start, ';'))) { 00993 len = end-start; 00994 lstrcpynW(szClassName, start, min(len+1, sizeof(szClassName)/sizeof(szClassName[0]))); 00995 start = end+1; 00996 cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); 00997 if(cls) break; 00998 } 00999 if(!cls && *start) { 01000 lstrcpynW(szClassName, start, sizeof(szClassName)/sizeof(szClassName[0])); 01001 cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); 01002 } 01003 if(cls) { 01004 TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList)); 01005 cls->tf = tfActiveTheme; 01006 cls->tf->dwRefCount++; 01007 } 01008 return cls; 01009 } 01010 01011 /*********************************************************************** 01012 * MSSTYLES_CloseThemeClass 01013 * 01014 * Close a theme class 01015 * 01016 * PARAMS 01017 * tc Theme class to close 01018 * 01019 * NOTES 01020 * The MSSTYLES_CloseThemeFile decreases the refcount of the owning 01021 * theme file and cleans it up, if needed. 01022 */ 01023 HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc) 01024 { 01025 MSSTYLES_CloseThemeFile (tc->tf); 01026 return S_OK; 01027 } 01028 01029 /*********************************************************************** 01030 * MSSTYLES_FindProperty 01031 * 01032 * Locate a property in a class. Part and state IDs will be used as a 01033 * preference, but may be ignored in the attempt to locate the property. 01034 * Will scan the entire chain of overrides for this class. 01035 */ 01036 PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId, int iPropertyPrimitive, int iPropertyId) 01037 { 01038 PTHEME_CLASS next = tc; 01039 PTHEME_PARTSTATE ps; 01040 PTHEME_PROPERTY tp; 01041 01042 TRACE("(%p, %d, %d, %d)\n", tc, iPartId, iStateId, iPropertyId); 01043 /* Try and find an exact match on part & state */ 01044 while(next && (ps = MSSTYLES_FindPartState(next, iPartId, iStateId, &next))) { 01045 if((tp = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId))) { 01046 return tp; 01047 } 01048 } 01049 /* If that fails, and we didn't already try it, search for just part */ 01050 if(iStateId != 0) 01051 iStateId = 0; 01052 /* As a last ditch attempt..go for just class */ 01053 else if(iPartId != 0) 01054 iPartId = 0; 01055 else 01056 return NULL; 01057 01058 if((tp = MSSTYLES_FindProperty(tc, iPartId, iStateId, iPropertyPrimitive, iPropertyId))) 01059 return tp; 01060 return NULL; 01061 } 01062 01063 /* Prepare a bitmap to be used for alpha blending */ 01064 static BOOL prepare_alpha (HBITMAP bmp, BOOL* hasAlpha) 01065 { 01066 DIBSECTION dib; 01067 int n; 01068 BYTE* p; 01069 01070 *hasAlpha = FALSE; 01071 01072 if (!bmp || GetObjectW( bmp, sizeof(dib), &dib ) != sizeof(dib)) 01073 return FALSE; 01074 01075 if(dib.dsBm.bmBitsPixel != 32) 01076 /* nothing to do */ 01077 return TRUE; 01078 01079 *hasAlpha = TRUE; 01080 p = dib.dsBm.bmBits; 01081 n = dib.dsBmih.biHeight * dib.dsBmih.biWidth; 01082 /* AlphaBlend() wants premultiplied alpha, so do that now */ 01083 while (n-- > 0) 01084 { 01085 int a = p[3]+1; 01086 p[0] = (p[0] * a) >> 8; 01087 p[1] = (p[1] * a) >> 8; 01088 p[2] = (p[2] * a) >> 8; 01089 p += 4; 01090 } 01091 01092 return TRUE; 01093 } 01094 01095 HBITMAP MSSTYLES_LoadBitmap (PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha) 01096 { 01097 WCHAR szFile[MAX_PATH]; 01098 LPWSTR tmp; 01099 PTHEME_IMAGE img; 01100 lstrcpynW(szFile, lpFilename, sizeof(szFile)/sizeof(szFile[0])); 01101 tmp = szFile; 01102 do { 01103 if(*tmp == '\\') *tmp = '_'; 01104 if(*tmp == '/') *tmp = '_'; 01105 if(*tmp == '.') *tmp = '_'; 01106 } while(*tmp++); 01107 01108 /* Try to locate in list of loaded images */ 01109 img = tc->tf->images; 01110 while (img) 01111 { 01112 if (lstrcmpiW (szFile, img->name) == 0) 01113 { 01114 TRACE ("found %p %s: %p\n", img, debugstr_w (img->name), img->image); 01115 *hasAlpha = img->hasAlpha; 01116 return img->image; 01117 } 01118 img = img->next; 01119 } 01120 /* Not found? Load from resources */ 01121 img = HeapAlloc (GetProcessHeap(), 0, sizeof (THEME_IMAGE)); 01122 img->image = LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 01123 prepare_alpha (img->image, hasAlpha); 01124 img->hasAlpha = *hasAlpha; 01125 /* ...and stow away for later reuse. */ 01126 lstrcpyW (img->name, szFile); 01127 img->next = tc->tf->images; 01128 tc->tf->images = img; 01129 TRACE ("new %p %s: %p\n", img, debugstr_w (img->name), img->image); 01130 return img->image; 01131 } 01132 01133 static BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value) 01134 { 01135 LPCWSTR cur = lpStringStart; 01136 int total = 0; 01137 BOOL gotNeg = FALSE; 01138 01139 while(cur < lpStringEnd && (*cur < '0' || *cur > '9' || *cur == '-')) cur++; 01140 if(cur >= lpStringEnd) { 01141 return FALSE; 01142 } 01143 if(*cur == '-') { 01144 cur++; 01145 gotNeg = TRUE; 01146 } 01147 while(cur < lpStringEnd && (*cur >= '0' && *cur <= '9')) { 01148 total = total * 10 + (*cur - '0'); 01149 cur++; 01150 } 01151 if(gotNeg) total = -total; 01152 *value = total; 01153 if(lpValEnd) *lpValEnd = cur; 01154 return TRUE; 01155 } 01156 01157 static BOOL MSSTYLES_GetNextToken(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LPWSTR lpBuff, DWORD buffSize) { 01158 LPCWSTR cur = lpStringStart; 01159 LPCWSTR start; 01160 LPCWSTR end; 01161 01162 while(cur < lpStringEnd && (isspace(*cur) || *cur == ',')) cur++; 01163 if(cur >= lpStringEnd) { 01164 return FALSE; 01165 } 01166 start = cur; 01167 while(cur < lpStringEnd && *cur != ',') cur++; 01168 end = cur; 01169 while(isspace(*end)) end--; 01170 01171 lstrcpynW(lpBuff, start, min(buffSize, end-start+1)); 01172 01173 if(lpValEnd) *lpValEnd = cur; 01174 return TRUE; 01175 } 01176 01177 /*********************************************************************** 01178 * MSSTYLES_GetPropertyBool 01179 * 01180 * Retrieve a color value for a property 01181 */ 01182 HRESULT MSSTYLES_GetPropertyBool(PTHEME_PROPERTY tp, BOOL *pfVal) 01183 { 01184 *pfVal = FALSE; 01185 if(*tp->lpValue == 't' || *tp->lpValue == 'T') 01186 *pfVal = TRUE; 01187 return S_OK; 01188 } 01189 01190 /*********************************************************************** 01191 * MSSTYLES_GetPropertyColor 01192 * 01193 * Retrieve a color value for a property 01194 */ 01195 HRESULT MSSTYLES_GetPropertyColor(PTHEME_PROPERTY tp, COLORREF *pColor) 01196 { 01197 LPCWSTR lpEnd; 01198 LPCWSTR lpCur; 01199 int red, green, blue; 01200 01201 lpCur = tp->lpValue; 01202 lpEnd = tp->lpValue + tp->dwValueLen; 01203 01204 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &red)) { 01205 TRACE("Could not parse color property\n"); 01206 return E_PROP_ID_UNSUPPORTED; 01207 } 01208 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &green)) { 01209 TRACE("Could not parse color property\n"); 01210 return E_PROP_ID_UNSUPPORTED; 01211 } 01212 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &blue)) { 01213 TRACE("Could not parse color property\n"); 01214 return E_PROP_ID_UNSUPPORTED; 01215 } 01216 *pColor = RGB(red,green,blue); 01217 return S_OK; 01218 } 01219 01220 /*********************************************************************** 01221 * MSSTYLES_GetPropertyColor 01222 * 01223 * Retrieve a color value for a property 01224 */ 01225 static HRESULT MSSTYLES_GetFont (LPCWSTR lpCur, LPCWSTR lpEnd, 01226 LPCWSTR *lpValEnd, LOGFONTW* pFont) 01227 { 01228 static const WCHAR szBold[] = {'b','o','l','d','\0'}; 01229 static const WCHAR szItalic[] = {'i','t','a','l','i','c','\0'}; 01230 static const WCHAR szUnderline[] = {'u','n','d','e','r','l','i','n','e','\0'}; 01231 static const WCHAR szStrikeOut[] = {'s','t','r','i','k','e','o','u','t','\0'}; 01232 int pointSize; 01233 WCHAR attr[32]; 01234 01235 if(!MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, pFont->lfFaceName, LF_FACESIZE)) { 01236 TRACE("Property is there, but failed to get face name\n"); 01237 *lpValEnd = lpCur; 01238 return E_PROP_ID_UNSUPPORTED; 01239 } 01240 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pointSize)) { 01241 TRACE("Property is there, but failed to get point size\n"); 01242 *lpValEnd = lpCur; 01243 return E_PROP_ID_UNSUPPORTED; 01244 } 01245 if(pointSize > 0) 01246 { 01247 HDC hdc = GetDC(0); 01248 pointSize = -MulDiv(pointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72); 01249 ReleaseDC(0, hdc); 01250 } 01251 01252 pFont->lfHeight = pointSize; 01253 pFont->lfWeight = FW_REGULAR; 01254 pFont->lfCharSet = DEFAULT_CHARSET; 01255 while(MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, attr, sizeof(attr)/sizeof(attr[0]))) { 01256 if(!lstrcmpiW(szBold, attr)) pFont->lfWeight = FW_BOLD; 01257 else if(!lstrcmpiW(szItalic, attr)) pFont->lfItalic = TRUE; 01258 else if(!lstrcmpiW(szUnderline, attr)) pFont->lfUnderline = TRUE; 01259 else if(!lstrcmpiW(szStrikeOut, attr)) pFont->lfStrikeOut = TRUE; 01260 } 01261 *lpValEnd = lpCur; 01262 return S_OK; 01263 } 01264 01265 HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont) 01266 { 01267 LPCWSTR lpCur = tp->lpValue; 01268 LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; 01269 HRESULT hr; 01270 01271 ZeroMemory(pFont, sizeof(LOGFONTW)); 01272 hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont); 01273 01274 return hr; 01275 } 01276 01277 /*********************************************************************** 01278 * MSSTYLES_GetPropertyInt 01279 * 01280 * Retrieve an int value for a property 01281 */ 01282 HRESULT MSSTYLES_GetPropertyInt(PTHEME_PROPERTY tp, int *piVal) 01283 { 01284 if(!MSSTYLES_GetNextInteger(tp->lpValue, (tp->lpValue + tp->dwValueLen), NULL, piVal)) { 01285 TRACE("Could not parse int property\n"); 01286 return E_PROP_ID_UNSUPPORTED; 01287 } 01288 return S_OK; 01289 } 01290 01291 /*********************************************************************** 01292 * MSSTYLES_GetPropertyIntList 01293 * 01294 * Retrieve an int list value for a property 01295 */ 01296 HRESULT MSSTYLES_GetPropertyIntList(PTHEME_PROPERTY tp, INTLIST *pIntList) 01297 { 01298 int i; 01299 LPCWSTR lpCur = tp->lpValue; 01300 LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; 01301 01302 for(i=0; i < MAX_INTLIST_COUNT; i++) { 01303 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pIntList->iValues[i])) 01304 break; 01305 } 01306 pIntList->iValueCount = i; 01307 return S_OK; 01308 } 01309 01310 /*********************************************************************** 01311 * MSSTYLES_GetPropertyPosition 01312 * 01313 * Retrieve a position value for a property 01314 */ 01315 HRESULT MSSTYLES_GetPropertyPosition(PTHEME_PROPERTY tp, POINT *pPoint) 01316 { 01317 int x,y; 01318 LPCWSTR lpCur = tp->lpValue; 01319 LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; 01320 01321 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &x)) { 01322 TRACE("Could not parse position property\n"); 01323 return E_PROP_ID_UNSUPPORTED; 01324 } 01325 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &y)) { 01326 TRACE("Could not parse position property\n"); 01327 return E_PROP_ID_UNSUPPORTED; 01328 } 01329 pPoint->x = x; 01330 pPoint->y = y; 01331 return S_OK; 01332 } 01333 01334 /*********************************************************************** 01335 * MSSTYLES_GetPropertyString 01336 * 01337 * Retrieve a string value for a property 01338 */ 01339 HRESULT MSSTYLES_GetPropertyString(PTHEME_PROPERTY tp, LPWSTR pszBuff, int cchMaxBuffChars) 01340 { 01341 lstrcpynW(pszBuff, tp->lpValue, min(tp->dwValueLen+1, cchMaxBuffChars)); 01342 return S_OK; 01343 } 01344 01345 /*********************************************************************** 01346 * MSSTYLES_GetPropertyRect 01347 * 01348 * Retrieve a rect value for a property 01349 */ 01350 HRESULT MSSTYLES_GetPropertyRect(PTHEME_PROPERTY tp, RECT *pRect) 01351 { 01352 LPCWSTR lpCur = tp->lpValue; 01353 LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; 01354 01355 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->left); 01356 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->top); 01357 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->right); 01358 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pRect->bottom)) { 01359 TRACE("Could not parse rect property\n"); 01360 return E_PROP_ID_UNSUPPORTED; 01361 } 01362 return S_OK; 01363 } 01364 01365 /*********************************************************************** 01366 * MSSTYLES_GetPropertyMargins 01367 * 01368 * Retrieve a margins value for a property 01369 */ 01370 HRESULT MSSTYLES_GetPropertyMargins(PTHEME_PROPERTY tp, RECT *prc, MARGINS *pMargins) 01371 { 01372 LPCWSTR lpCur = tp->lpValue; 01373 LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; 01374 01375 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxLeftWidth); 01376 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxRightWidth); 01377 MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyTopHeight); 01378 if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyBottomHeight)) { 01379 TRACE("Could not parse margins property\n"); 01380 return E_PROP_ID_UNSUPPORTED; 01381 } 01382 return S_OK; 01383 } Generated on Sun May 27 2012 04:26:45 for ReactOS by
1.7.6.1
|