#include #include #include "skinelem.h" #include #include #include #include #include #include #include #include xml_elementtag elementtaglist[] = { {L"bitmap", XML_ELEMENTTAG_BITMAP, 0}, {L"bitmapfont", XML_ELEMENTTAG_BITMAPFONT, 0}, {L"color", XML_ELEMENTTAG_COLOR, 0}, {L"cursor", XML_ELEMENTTAG_CURSOR, 0}, {L"elements", XML_ELEMENTTAG_ELEMENTS, 1}, {L"elementalias", XML_ELEMENTTAG_ELEMENTALIAS, 0}, {L"truetypefont", XML_ELEMENTTAG_TRUETYPEFONT, 0}, }; //------------------------- //------------------------- void SkinElementsMgr::init() { if (!quickxmltaglist.getNumItems()) { for (int i = 0;i < sizeof(elementtaglist) / sizeof(xml_elementtag);i++) quickxmltaglist.addItem(&elementtaglist[i]); } skinXML.registerCallback(L"WinampAbstractionLayer\felements\f*", &xmlreader); //back compat skinXML.registerCallback(L"WasabiXML\felements\f*", &xmlreader); } void SkinElementsMgr::deinit() { resetSkinElements(); skinXML.unregisterCallback(&xmlreader); } void SkinElementsMgr::onBeforeLoadingSkinElements(const wchar_t *_rootpath) { Skin::sendBeforeLoadingElementsCallback(); elementScriptId = WASABI_API_PALETTE->newSkinPart(); WASABI_API_PALETTE->StartTransaction(); rootpath = _rootpath; original_rootpath = rootpath; last_includepath = L""; } void SkinElementsMgr::onAfterLoadingSkinElements() { WASABI_API_PALETTE->EndTransaction(); #ifdef WASABI_COMPILE_COMPONENTS ComponentManager::broadcastNotify(WAC_NOTIFY_SKINELEMENTSLOADED, Skin::getSkinPartIterator()); #endif } void SkinElementsXmlReader::xmlReaderOnEndElementCallback(const wchar_t *xmltag) { SkinElementsMgr::xmlReaderOnEndElementCallback(xmltag); } void SkinElementsMgr::xmlReaderOnEndElementCallback(const wchar_t *xmltag) { xml_elementtag *i = quickxmltaglist.findItem(xmltag); if (!i) return ; if (i->id == XML_ELEMENTTAG_ELEMENTS) { if (inelements) inelements = 0; } } void SkinElementsXmlReader::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params) { SkinElementsMgr::xmlReaderOnStartElementCallback(xmltag, params); } void SkinElementsMgr::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params) { xml_elementtag *i = quickxmltaglist.findItem(xmltag); if (i) _xmlReaderOnStartElementCallback( i->id, xmltag, params); else _xmlReaderOnStartElementCallback( XML_ELEMENTTAG_UNKNOWN, xmltag, params); } void SkinElementsMgr::_xmlReaderOnStartElementCallback(int tagid, const wchar_t *xmltag, skin_xmlreaderparams *params) { const wchar_t *ic = skinXML.getIncludePath(); if (WCSICMP(ic, last_includepath)) { last_includepath = skinXML.getIncludePath(); rootpath = getSkinRootpathFromIncludePath(last_includepath, original_rootpath); } // If we're loading from a buffer, there should be no rootpath prefix. if (!WCSNICMP(rootpath, L"buf:", 4)) { rootpath = NULL; } if (tagid == XML_ELEMENTTAG_ELEMENTALIAS) { WASABI_API_PALETTE->AddAlias(params->getItemValue(L"id"), params->getItemValue(L"target")); } else if (tagid == XML_ELEMENTTAG_BITMAP) { StringW id; const wchar_t *fn; id = params->getItemValue(L"id"); fn = params->getItemValue(L"file"); int x = params->getItemValueInt(L"x", -1); int y = params->getItemValueInt(L"y", -1); int w = params->getItemValueInt(L"w", -1); int h = params->getItemValueInt(L"h", -1); const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id); if (aliastarget) id = aliastarget; const wchar_t *colorgroup = params->getItemValue(L"colorgroup"); if (!colorgroup || !*colorgroup) colorgroup = params->getItemValue(L"gammagroup"); WASABI_API_PALETTE->AddBitmap(id, fn, rootpath, x, y, w, h, params, colorgroup); } else if (tagid == XML_ELEMENTTAG_COLOR) { const wchar_t *colorstr = params->getItemValue(L"value"); StringW id = params->getItemValue(L"id"); const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id); if (aliastarget) id = aliastarget; const wchar_t *colorgroup = params->getItemValue(L"colorgroup"); if (!colorgroup || !*colorgroup) colorgroup = params->getItemValue(L"gammagroup"); if (!wcschr(colorstr, ',')) { ARGB32 c = WASABI_API_PALETTE->getColorElement((colorstr)); WASABI_API_PALETTE->AddColor(id, c, colorgroup, rootpath, params); } else { WASABI_API_PALETTE->AddColor((id), SkinParser::parseColor(colorstr), colorgroup, rootpath, params); } } else if (tagid == XML_ELEMENTTAG_BITMAPFONT) { Font::installBitmapFont(params->getItemValue(L"file"), rootpath, params->getItemValue(L"id"), params->getItemValueInt(L"charwidth", 0), params->getItemValueInt(L"charheight", 0), params->getItemValueInt(L"hspacing", 0), params->getItemValueInt(L"vspacing", 0), elementScriptId, params->getItemValueInt(L"allowmapping", 1)); } else if (tagid == XML_ELEMENTTAG_TRUETYPEFONT) { Font::installTrueTypeFont(params->getItemValue(L"file"), rootpath, params->getItemValue(L"id"), elementScriptId, params->getItemValueInt(L"allowmapping", 1), 0); } else if (tagid == XML_ELEMENTTAG_CURSOR) { const wchar_t *bitmap = params->getItemValue(L"bitmap"); StringW id = params->getItemValue(L"id"); const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id); int x = params->getItemValueInt(L"hotspot_x", 0); int y = params->getItemValueInt(L"hotspot_y", 0); if (aliastarget) id = aliastarget; WASABI_API_PALETTE->AddCursor(id, bitmap, x, y, rootpath, params); } else if (tagid == XML_ELEMENTTAG_UNKNOWN) { CollectionSvcEnum cse(xmltag); svc_collection *svc; if (svc = cse.getFirst()) { // got one! svc->addElement(params->getItemValue(L"id"), rootpath, elementScriptId, params); WASABI_API_SVC->service_release(svc); } } else { DebugStringW(L"SkinElementsMgr: tag %s was recognized but not handled!\n", xmltag); } } void SkinElementsMgr::resetSkinElements() { WASABI_API_PALETTE->Reset(); Font::uninstallAll(); // remove any element inserted into a hierarchical collection for (int i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++) { waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i); if (f != NULL) { svc_collection *svc = static_cast(f->getInterface(FALSE)); svc->removeAllElements(); f->releaseInterface(svc); } } } void SkinElementsMgr::onBeforeLoadingScriptElements(const wchar_t *name, int script_id) { SkinElementsMgr::rootpathstack.addItem(new StringW(rootpath)); oldid = elementScriptId; oldinel = inelements; WASABI_API_PALETTE->StartTransaction(); wchar_t buf[WA_MAX_PATH] = {0}; WCSCPYN(buf, name, WA_MAX_PATH); wchar_t *ptr = const_cast(Wasabi::Std::filename(buf)); if (ptr != NULL) *ptr = '\0'; rootpath = buf; rootpath.AddBackslash(); original_rootpath = rootpath; last_includepath = L""; inelements = 0; elementScriptId = script_id; } void SkinElementsMgr::onAfterLoadingScriptElements() { WASABI_API_PALETTE->EndTransaction(); elementScriptId = oldid; inelements = oldinel; rootpath = SkinElementsMgr::rootpathstack.getLast(); delete SkinElementsMgr::rootpathstack.getLast(); SkinElementsMgr::rootpathstack.removeLastItem(); } void SkinElementsMgr::unloadScriptElements(int scriptid) { int i; WASABI_API_PALETTE->UnloadElements(scriptid); Font::uninstallByScriptId(scriptid); // remove any element inserted into a hierarchical collection for (i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++) { waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i); if (f != NULL) { svc_collection *svc = static_cast(f->getInterface(FALSE)); svc->removeElement(scriptid); f->releaseInterface(svc); } } } int SkinElementsMgr::elementEqual(const wchar_t *file1, const wchar_t *rootpath1, const wchar_t *file2, const wchar_t *rootpath2) { StringPathCombine a(rootpath1, file1); StringPathCombine b(rootpath2, file2); return PATHEQL(a, b); } const wchar_t *SkinElementsMgr::getSkinRootpathFromIncludePath(const wchar_t *includepath, const wchar_t *def) { if (!wcsstr(includepath, L"..")) return def; PathParserW pp(includepath); if (pp.getNumStrings() < 2 || !WCSCASEEQLSAFE(pp.enumString(0), L"skins")) // UNSAFE if the skinpath isn't "skins" return def; StringW baseskin = pp.enumString(1); if (wcsstr(includepath, L"..")) { int x = 0; for (int i = 0;i < pp.getNumStrings();i++) { const wchar_t *p = pp.enumString(i); if (WCSICMP(p, L"..")) { if (x == 1) baseskin = pp.enumString(i); x++; } else x--; } } t_rootpath = pp.enumString(0); t_rootpath.AppendFolder(baseskin); return t_rootpath; } SkinElementsXmlReader SkinElementsMgr::xmlreader; int SkinElementsMgr::inelements = 0; int SkinElementsMgr::elementScriptId = -1; int SkinElementsMgr::oldid, SkinElementsMgr::oldinel; StringW SkinElementsMgr::rootpath, SkinElementsMgr::original_rootpath, SkinElementsMgr::t_rootpath, SkinElementsMgr::last_includepath; PtrList SkinElementsMgr::rootpathstack; PtrListQuickSorted SkinElementsMgr::quickxmltaglist;