ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

msstyles.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.