void MSVC10Loader::HandleFilesAndExcludes(const TiXmlElement* e, ProjectFile* pf) { if (!e || !pf) return; // add it to all configurations, not just the first for (HashProjectsConfs::iterator it=m_pc.begin(); it!=m_pc.end(); ++it) pf->AddBuildTarget(it->second.sName); // handle explicit exclusions like: // <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> // <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> const TiXmlElement* excl = e->FirstChildElement("ExcludedFromBuild"); for (; excl; excl=excl->NextSiblingElement("ExcludedFromBuild")) { const TiXmlText* do_excl = excl->ToText(); if (do_excl) { const char* value = do_excl->Value(); wxString s_value = cbC2U(value); if (s_value.IsSameAs(_T("true"), false)) { const char* cond = excl->Attribute("Condition"); if (cond) { wxString sName = cbC2U(cond); sName = SubstituteConfigMacros(sName); pf->RemoveBuildTarget(sName); } } } } }
void MSVC10Loader::HandleFilesAndExcludes(const TiXmlElement* e, ProjectFile* pf) { if (!e || !pf) return; // add it to all configurations, not just the first for (size_t i=0; i<m_pcNames.Count(); ++i) pf->AddBuildTarget(m_pcNames.Item(i)); // handle explicit exclusions like: // <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> // <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> const TiXmlElement* excl = e->FirstChildElement("ExcludedFromBuild"); // Operate existing excludes while (excl) { const TiXmlText* do_excl = excl->ToText(); if (do_excl) { const char* value = do_excl->Value(); wxString s_value = cbC2U(value); if (s_value.MakeUpper().IsSameAs(_T("TRUE"))) { const char* cond = excl->Attribute("Condition"); if (cond) { wxString sName = cbC2U(cond); sName = SubstituteConfigMacros(sName); pf->RemoveBuildTarget(sName); } } } excl = excl->NextSiblingElement(); } }
bool wxsCustomWidget::OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra) { bool Ret = wxsItem::OnXmlRead(Element,IsXRC,IsExtra); if ( IsXRC ) { if ( !(GetPropertiesFlags() & flSource) ) { SetUserClass(cbC2U(Element->Attribute("class"))); m_XmlDataDoc.Clear(); for ( TiXmlElement* Child = Element->FirstChildElement(); Child; Child = Child->NextSiblingElement() ) { // Skipping all standard elements wxString Name = cbC2U(Child->Value()); if ( Name != _T("pos") && Name != _T("size") && Name != _T("style") && Name != _T("enabled") && Name != _T("focused") && Name != _T("hidden") && Name != _T("fg") && Name != _T("bg") && Name != _T("font") && Name != _T("handler") ) { m_XmlDataDoc.InsertEndChild(*Child); } } RebuildXmlData(); } } return Ret; }
bool wxsToolBarItem::OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra) { bool Ret = wxsParent::OnXmlRead(Element,IsXRC,IsExtra); if ( IsXRC ) { wxString Class = cbC2U(Element->Attribute("class")); if ( Class == _T("separator") ) { m_Type = Separator; } else { // This will handle both wxMenu and wxToolBarItem TiXmlElement* Node = Element->FirstChildElement("radio"); if ( Node && (cbC2U(Node->GetText())==_T("1")) ) { m_Type = Radio; } else if ( (Node = Element->FirstChildElement("check")) && (cbC2U(Node->GetText())==_T("1")) ) { m_Type = Check; } else { m_Type = Normal; } } } return Ret; }
bool wxsResource::ReadConfig(const TiXmlElement* Node) { m_ResourceName = cbC2U(Node->Attribute("name")); m_Language = wxsCodeMarks::Id(cbC2U(Node->Attribute("language"))); if ( GetResourceName().empty() ) return false; return OnReadConfig(Node); }
int xmlFile::GetChildList(wxArrayString& arrStr) { arrStr.Clear(); if(!m_pWorkingElement) return -1; TiXmlElement* elem = (TiXmlElement*)m_pWorkingElement->FirstChild(); while(elem) { wxString name = cbC2U(elem->Value()); if(!name.IsEmpty()) //Root?? { if(elem->Attribute("alt_title")) { name = cbC2U(elem->Attribute("alt_title")); name.Replace(_T("\""), _T("")); } if(!name.IsEmpty()) arrStr.Add(name); } elem = (TiXmlElement*)elem->NextSibling(); } return arrStr.GetCount(); }
void ProjectTemplateLoader::DoOption(TiXmlElement* parentNode) { TiXmlElement* node = parentNode->FirstChildElement("Option"); while (node) { TemplateOption to; to.useDefaultCompiler = true; if (node->Attribute("name")) to.name = cbC2U(node->Attribute("name")); if (!to.name.IsEmpty()) { TiXmlElement* tmpnode = node->FirstChildElement("Notice"); if (tmpnode) { to.notice << _T("\n") << cbC2U(tmpnode->Attribute("value")); while (to.notice.Replace(_T(" "), _T(" "))) ; to.notice.Replace(_T("\t"), _T("")); to.noticeMsgType = strncmp(tmpnode->Attribute("value"), "0", 1) == 0 ? wxICON_INFORMATION : wxICON_WARNING; } DoOptionProject(node, to); DoOptionCompiler(node, to); DoOptionLinker(node, to); m_TemplateOptions.Add(to); } node = node->NextSiblingElement("Option"); } }
wxsResource* wxWidgetsResFactory::OnBuildExternal(const wxString& FileName) { TiXmlDocument Doc; if ( !TinyXML::LoadDocument(FileName,&Doc) ) return 0; wxArrayString ResourcesFound; wxArrayElement XmlElements; TiXmlElement* Res = Doc.FirstChildElement("resource"); if ( !Res ) { // TODO: Some message box about invalid XRC resource structure return 0; } for ( TiXmlElement* Object = Res->FirstChildElement("object"); Object; Object=Object->NextSiblingElement("object") ) { wxString Class = cbC2U(Object->Attribute("class")); wxString Name = cbC2U(Object->Attribute("name")); if ( !Name.empty() && Names.Index(Class) != wxNOT_FOUND ) { ResourcesFound.Add(Name + _T(" (") + Class + _T(")")); XmlElements.Add(Object); } } if ( ResourcesFound.empty() ) { // TODO: Message box that there are no resoures which could be edited here return 0; } int Choice = 0; if ( ResourcesFound.size() > 1 ) { Choice = ::cbGetSingleChoiceIndex( _("There's more than one resource in this file.\n" "Please select which one should be edited."), _("Choose resource to edit"), ResourcesFound); if ( Choice<0 ) { return 0; } } TiXmlElement* Object = XmlElements[Choice]; if ( !Object ) return 0; wxString Class = cbC2U(Object->Attribute("class")); switch ( Names.Index(Class) ) { case wxDialogId: return new wxsDialogRes(FileName,Object); case wxScrollingDialogId: return new wxsScrollingDialogRes(FileName,Object); case wxFrameId: return new wxsFrameRes(FileName,Object); case wxPanelId: return new wxsPanelRes(FileName,Object); default: break; } return 0; }
void ProjectTemplateLoader::DoTemplateNotice(TiXmlElement* parentNode) { TiXmlElement* node = parentNode->FirstChildElement("Notice"); if (!node) return; m_Notice = cbC2U(node->Attribute("value")); while (m_Notice.Replace(_T(" "), _T(" "))) ; m_Notice.Replace(_T("\t"), _T("")); m_NoticeMsgType = cbC2U(node->Attribute("value")) == _T("0") ? wxICON_INFORMATION : wxICON_WARNING; }
wxString ConfigManager::InvalidNameMessage(const wxString& what, const wxString& sub, TiXmlElement *localPath) const { wxString s; s.Printf(_T("The %s %s (child of node \"%s\" in namespace \"%s\") does not meet the standard for path naming (must start with a letter)."), what.c_str(), sub.c_str(), cbC2U(localPath->Value()).c_str(), cbC2U(root->Value()).c_str()); return s; }
bool MSVC7Loader::Open(const wxString& filename) { LogManager* pMsg = Manager::Get()->GetLogManager(); if (!pMsg) return false; /* NOTE (mandrav#1#): not necessary to ask for switches conversion... */ m_ConvertSwitches = m_pProject->GetCompilerID().IsSameAs(_T("gcc")); m_ProjectName = wxFileName(filename).GetName(); pMsg->DebugLog(F(_T("Importing MSVC 7.xx project: %s"), filename.wx_str())); TiXmlDocument doc(filename.mb_str()); if (!doc.LoadFile()) return false; pMsg->DebugLog(_T("Parsing project file...")); TiXmlElement* root; root = doc.FirstChildElement("VisualStudioProject"); if (!root) { pMsg->DebugLog(_T("Not a valid MS Visual Studio project file...")); return false; } if (strcmp(root->Attribute("ProjectType"), "Visual C++") != 0) { pMsg->DebugLog(_T("Project is not Visual C++...")); return false; } wxString ver = cbC2U(root->Attribute("Version")); if (ver.IsSameAs(_T("7.0")) || ver.IsSameAs(_T("7.00"))) m_Version = 70; if (ver.IsSameAs(_T("7.1")) || ver.IsSameAs(_T("7.10"))) m_Version = 71; if (ver.IsSameAs(_T("8.0")) || ver.IsSameAs(_T("8.00"))) m_Version = 80; if ((m_Version!=70) && (m_Version!=71)) { // seems to work with visual 8 too ;) pMsg->DebugLog(F(_T("Project version is '%s'. Although this loader was designed for version 7.xx, will try to import..."), ver.wx_str())); } m_pProject->ClearAllProperties(); m_pProject->SetModified(true); m_pProject->SetTitle(cbC2U(root->Attribute("Name"))); // delete all targets of the project (we 'll create new ones from the imported configurations) while (m_pProject->GetBuildTargetsCount()) m_pProject->RemoveBuildTarget(0); return DoSelectConfiguration(root); }
bool wxsMenuItem::OnXmlRead(TiXmlElement* Element,bool IsXRC,bool IsExtra) { bool Ret = wxsParent::OnXmlRead(Element,IsXRC,IsExtra); if ( IsXRC ) { wxString Class = cbC2U(Element->Attribute("class")); if ( Class == _T("separator") ) { m_Type = Separator; } else if ( Class == _T("break") ) { m_Type = Break; } else { // This will handle both wxMenu and wxMenuItem TiXmlElement* Node = Element->FirstChildElement("radio"); if ( Node && (cbC2U(Node->GetText())==_T("1")) ) { m_Type = Radio; } else { Node = Element->FirstChildElement("checkable"); // Backward BUG-compatibility if ( !Node ) Node = Element->FirstChildElement("check"); if ( Node && (cbC2U(Node->GetText())==_T("1")) ) { m_Type = Check; // Now, we are going to check its state, either checked or not checked TiXmlElement* checkedNode = Element->FirstChildElement("checked"); if (checkedNode && (cbC2U(checkedNode->GetText())==_T("1"))) m_Checked = true; // otherwise, the m_Checked will default to false. } else { m_Type = Normal; } } } } return Ret; }
wxString ConfigManager::GetPath() const { TiXmlElement *e = pathNode; wxString ret; ret.Alloc(64); ret = cbC2U(e->Value()); while ((e = e->Parent()->ToElement()) && e != root) { ret.Prepend(_T('/')); ret.Prepend(cbC2U(e->Value())); } ret.Prepend(_T('/')); return ret; }
void ConfigManager::Read(const wxString& name, ConfigManagerContainer::StringToStringMap* map) { wxString key(name); TiXmlElement* e = AssertPath(key); TiXmlHandle parentHandle(e); TiXmlNode *mNode = parentHandle.FirstChild(cbU2C(key)).FirstChild("ssmap").Node(); TiXmlNode *curr = nullptr; if (mNode) { while ((curr = mNode->IterateChildren(curr))) (*map)[cbC2U(curr->Value())] = cbC2U(curr->FirstChild()->ToText()->Value()); } }
void ProjectConfiguration::XmlLoad(TiXmlElement* Node,cbProject* Project) { m_GlobalUsedLibs.Clear(); m_TargetsUsedLibs.clear(); m_DisableAuto = false; TiXmlElement* LibFinder = Node->FirstChildElement("lib_finder"); if ( !LibFinder ) return; int noauto = 0; if ( (LibFinder->QueryIntAttribute("disable_auto",&noauto) == TIXML_SUCCESS) && noauto ) { m_DisableAuto = true; } for ( TiXmlElement* Elem = LibFinder->FirstChildElement("lib"); Elem; Elem = Elem->NextSiblingElement("lib") ) { wxString LibName = cbC2U(Elem->Attribute("name")); if ( !LibName.IsEmpty() && m_GlobalUsedLibs.Index(LibName)==wxNOT_FOUND ) { m_GlobalUsedLibs.Add(LibName); } } for ( TiXmlElement* Elem = LibFinder->FirstChildElement("target"); Elem; Elem = Elem->NextSiblingElement("target") ) { wxString TargetName = cbC2U(Elem->Attribute("name")); if ( !Project->GetBuildTarget(TargetName) ) continue; wxArrayString& Libs = m_TargetsUsedLibs[TargetName]; for ( TiXmlElement* LibElem = Elem->FirstChildElement("lib"); LibElem; LibElem = LibElem->NextSiblingElement("lib") ) { wxString LibName = cbC2U(LibElem->Attribute("name")); if ( !LibName.IsEmpty() && Libs.Index(LibName)==wxNOT_FOUND ) { Libs.Add(LibName); } } } // TODO: Invoke library settings check }
/** get project name, type and GUID * \param root : the root node of the XML project file (<Project > **/ bool MSVC10Loader::GetProjectGlobals(const TiXmlElement* root) { if (!root) return false; LogManager* pMsg = Manager::Get()->GetLogManager(); if (!pMsg) return false; bool bResult = false; const char* title = root->Attribute("NoName"); if (title) m_pProject->SetTitle(cbC2U(title)); // parse all global parameters const TiXmlElement* prop = root->FirstChildElement("PropertyGroup"); while (prop) { const char* attr = prop->Attribute("Label"); if (!attr) { prop = prop->NextSiblingElement(); continue; } wxString label = cbC2U(attr); if (label.MakeUpper().IsSameAs(_T("GLOBALS"))) { const TiXmlElement* pGUID = prop->FirstChildElement("ProjectGuid"); if (pGUID) m_ProjectGUID = GetText(pGUID); const TiXmlElement* pProjectType = prop->FirstChildElement("Keyword"); if (pProjectType) m_ProjectType = GetText(pProjectType); const TiXmlElement* pProjectName = prop->FirstChildElement("RootNamespace"); if (pProjectName) m_ProjectName = GetText(pProjectName); // logging pMsg->DebugLog(wxString::Format(_("Project global properties: GUID=%s, Type=%s, Name=%s"), m_ProjectGUID.wx_str(), m_ProjectType.wx_str(), m_ProjectName.wx_str())); bResult = true; // got everything we need break; // exit loop } prop = prop->NextSiblingElement(); } if (!bResult) pMsg->DebugLog(_("Failed to find global project properties, using default one.")); m_pProject->SetTitle(m_ProjectName); return bResult; }
wxString ConfigManager::ReadBinary(const wxString& name) { wxString str; wxString key(name); TiXmlElement* e = AssertPath(key); unsigned int crc = 0; TiXmlHandle parentHandle(e); TiXmlElement* bin = parentHandle.FirstChild(cbU2C(key)).FirstChild("bin").Element(); if (!bin) return wxEmptyString; if (bin->QueryIntAttribute("crc", (int*)&crc) != TIXML_SUCCESS) return wxEmptyString; if (const TiXmlText* t = bin->FirstChild()->ToText()) { str.assign(cbC2U(t->Value())); str = wxBase64::Decode(str); if (crc == wxCrc32::FromString(str)) return str; } return wxEmptyString; }
int CodeBlocksApp::OnRun() { EnableLFH(); try { int retval = wxApp::OnRun(); // wx 2.6.3 docs says that OnRun() function's return value is used as exit code return m_Batch ? m_BatchExitCode : retval; } catch (cbException& exception) { exception.ShowErrorMessage(); } catch (SquirrelError& exception) { Manager::Get()->GetScriptingManager()->DisplayErrors(&exception); } catch (const char* message) { wxSafeShowMessage(_("Exception"), cbC2U(message)); } catch (...) { wxSafeShowMessage(_("Exception"), _("Unknown exception was raised. The application will terminate immediately...")); } // if we reached here, return error return -1; }
void AstyleConfigDlg::OnPreview(wxCommandEvent& WXUNUSED(event)) { wxString text(XRCCTRL(*this, "txtSample", wxTextCtrl)->GetValue()); wxString formattedText; astyle::ASFormatter formatter; // load settings DlgFormatterSettings settings(this); settings.ApplyTo(formatter); if (text.size() && text.Last() != _T('\r') && text.Last() != _T('\n')) text += _T('\n'); formatter.init(new ASStreamIterator(0, text)); while (formatter.hasMoreLines()) { formattedText << cbC2U(formatter.nextLine().c_str()); if (formatter.hasMoreLines()) formattedText << _T('\n'); } XRCCTRL(*this, "txtSample", wxTextCtrl)->SetValue(formattedText); }
/*! \brief Read XML data. * * \param Object wxsPropertyContainer* A pointer to a wxsPropertyContainer object. * \param Element TiXmlElement* A pointer to a TiXmlElement object. * \return bool True on success, otherwise false. * */ bool wxsImageProperty::XmlRead(wxsPropertyContainer *Object, TiXmlElement *Element) { VALUE.Clear(); if(!Element) { return false; } for(TiXmlElement *Item = Element->FirstChildElement(cbU2C(DataSubName)); Item; Item = Item->NextSiblingElement(cbU2C(DataSubName))) { const char *Text = Item->GetText(); if(Text) { VALUE.Add(cbC2U(Text)); } else { VALUE.Add(wxEmptyString); } } return true; }
void wxsCustomWidget::RebuildXmlData() { TiXmlPrinter Printer; Printer.SetIndent("\t"); m_XmlDataDoc.Accept(&Printer); m_XmlData = cbC2U(Printer.CStr()); }
wxsItem* wxsItemResDataObject::BuildItem(wxsItemResData* Data,int Index) const { if ( Index < 0 || Index >= m_ItemCount ) return 0; TiXmlElement* Root = m_XmlElem->FirstChildElement("object"); if ( !Root ) return 0; while ( Index ) { Index--; Root = Root->NextSiblingElement("object"); if ( !Root ) return 0; } const char* Class = Root->Attribute("class"); if ( !Class || !*Class ) return 0; wxsItem* Item = wxsItemFactory::Build(cbC2U(Class),Data); if ( !Item ) { Item = wxsItemFactory::Build(_T("Custom"),Data); if ( !Item ) return 0; } Item->XmlRead(Root,true,true); return Item; }
//////////////////////////////////////////////////////////////////////////////// // register the script plugin framework //////////////////////////////////////////////////////////////////////////////// void Register_ScriptPlugin() { SqPlus::RegisterGlobal(&ScriptPluginWrapper::ExecutePlugin, "ExecutePlugin"); SquirrelVM::CreateFunctionGlobal(&ScriptPluginWrapper::GetPlugin, "GetPlugin", "*"); SquirrelVM::CreateFunctionGlobal(&ScriptPluginWrapper::RegisterPlugin, "RegisterPlugin", "*"); // load base script plugin // WARNING: we CANNOT use ScriptingManager::LoadBuffer() because we have reached here // by a call from inside ScriptingManager's constructor. This would cause an infinite // loop and the app would die with a stack overflow. We got to load the script manually... // we also have to disable the printfunc for a while SQPRINTFUNCTION oldPrintFunc = sq_getprintfunc(SquirrelVM::GetVMPtr()); sq_setprintfunc(SquirrelVM::GetVMPtr(), 0); // compile and run script SquirrelObject script; try { script = SquirrelVM::CompileBuffer(s_cbScriptPlugin, "cbScriptPlugin"); SquirrelVM::RunScript(script); } catch (SquirrelError e) { cbMessageBox(wxString::Format(_("Failed to register script plugins framework.\n\n%s"), cbC2U(e.desc).c_str()), _("Script compile error"), wxICON_ERROR); } // restore the printfunc sq_setprintfunc(SquirrelVM::GetVMPtr(), oldPrintFunc); }
bool ConfigManager::Read(const wxString& name, wxString* str) { if (name.IsSameAs(CfgMgrConsts::app_path)) { str->assign(app_path); return true; } else if (name.IsSameAs(CfgMgrConsts::data_path)) { str->assign(data_path_global); return true; } wxString key(name); TiXmlElement* e = AssertPath(key); TiXmlHandle parentHandle(e); TiXmlText *t = (TiXmlText *) parentHandle.FirstChild(cbU2C(key)).FirstChild("str").FirstChild().Node(); if (t) { str->assign(cbC2U(t->Value())); return true; } return false; }
bool wxsCustomWidget::OnXmlWrite(TiXmlElement* Element,bool IsXRC,bool IsExtra) { bool Ret = wxsItem::OnXmlWrite(Element,IsXRC,IsExtra); if ( IsXRC ) { if ( !(GetPropertiesFlags() & flSource) ) { Element->SetAttribute("class",cbU2C(GetUserClass())); Element->RemoveAttribute("subclass"); Element->InsertEndChild(TiXmlElement("style"))->InsertEndChild(TiXmlText(cbU2C(m_Style))); for ( TiXmlElement* Child = m_XmlDataDoc.FirstChildElement(); Child; Child = Child->NextSiblingElement() ) { // Skipping all standard elements wxString Name = cbC2U(Child->Value()); if ( Name != _T("pos") && Name != _T("size") && Name != _T("style") && Name != _T("enabled") && Name != _T("focused") && Name != _T("hidden") && Name != _T("fg") && Name != _T("bg") && Name != _T("font") && Name != _T("handler") ) { Element->InsertEndChild(*Child); } } } } return Ret; }
bool wxsEnumProperty::XmlRead(wxsPropertyContainer* Object,TiXmlElement* Element) { if ( !Element ) { VALUE = Default; return false; } const char* Text = Element->GetText(); if ( !Text ) { VALUE = Default; return false; } if ( UseNamesInXml ) { // Searching for node text in names wxString TextS = cbC2U(Text); int i = 0; for ( const wxChar** Ptr = Names; *Ptr; Ptr++, i++ ) { if ( TextS == *Ptr ) { VALUE = Values[i]; return true; } } VALUE = Default; return false;; } else { VALUE = atoi(Text); } return true; }
wxString xmlFile::GetText() { wxString ret = _T(""); if(m_pWorkingElement) ret = cbC2U(m_pWorkingElement->GetText()); return ret; }
static void CaptureScriptOutput(HSQUIRRELVM /*v*/, const SQChar * s, ...) { static SQChar temp[2048]; va_list vl; va_start(vl,s); scvsprintf(temp,s,vl); ::capture.append(cbC2U(temp)); va_end(vl); }
// function contributed by Tim Baker void MSVC7Loader::HandleFileConfiguration(TiXmlElement* file, ProjectFile* pf) { TiXmlElement* fconf = file->FirstChildElement("FileConfiguration"); while (fconf) { if (const char* s = fconf->Attribute("ExcludedFromBuild")) { if (cbC2U(s).IsSameAs(_T("true"), false)) // can you initialize wxString from NULL? { wxString name = cbC2U(fconf->Attribute("Name")); name.Replace(_T("|"), _T(" "), true); // Replace '|' to ensure proper check pf->RemoveBuildTarget(name); Manager::Get()->GetLogManager()->DebugLog( F(_("removed %s from %s"), pf->file.GetFullPath().wx_str(), name.wx_str())); } } fconf = fconf->NextSiblingElement("FileConfiguration"); } }
void ProjectTemplateLoader::DoFileSetFile(TiXmlElement* parentNode, FileSet& fs) { TiXmlElement* node = parentNode->FirstChildElement("File"); while (node) { FileSetFile fsf; if (node->Attribute("source")) fsf.source = cbC2U(node->Attribute("source")); if (node->Attribute("destination")) fsf.destination = cbC2U(node->Attribute("destination")); if (node->Attribute("targets")) fsf.targets = cbC2U(node->Attribute("targets")); if (!fsf.source.IsEmpty() && !fsf.destination.IsEmpty()) fs.files.Add(fsf); node = node->NextSiblingElement("File"); } }