#include "wx/xml/xml.h"
+
class wxXmlResourceDataRecord
{
public:
#endif
};
-class wxXmlResourceDataRecords : public wxVector<wxXmlResourceDataRecord>
+class wxXmlResourceDataRecords : public wxVector<wxXmlResourceDataRecord*>
{
// this is a class so that it can be forward-declared
};
{
ClearHandlers();
+ for ( wxXmlResourceDataRecords::iterator i = m_data->begin();
+ i != m_data->end(); ++i )
+ {
+ delete *i;
+ }
delete m_data;
}
bool wxXmlResource::Load(const wxString& filemask)
{
- wxString fnd;
- bool iswild = wxIsWild(filemask);
- bool rt = true;
-
#if wxUSE_FILESYSTEM
wxFileSystem fsys;
# define wxXmlFindFirst fsys.FindFirst(filemask, wxFILE)
# define wxXmlFindFirst wxFindFirstFile(filemask, wxFILE)
# define wxXmlFindNext wxFindNextFile()
#endif
- if (iswild)
- fnd = wxXmlFindFirst;
- else
- fnd = filemask;
+ wxString fnd = wxXmlFindFirst;
+ if ( fnd.empty() )
+ {
+ wxLogError(_("Cannot load resources from '%s'."), filemask);
+ return false;
+ }
+
while (!fnd.empty())
{
fnd = ConvertFileNameToURL(fnd);
#if wxUSE_FILESYSTEM
if ( IsArchive(fnd) )
{
- rt = rt && Load(fnd + wxT("#zip:*.xrc"));
+ if ( !Load(fnd + wxT("#zip:*.xrc")) )
+ return false;
}
else // a single resource URL
#endif // wxUSE_FILESYSTEM
{
- wxXmlResourceDataRecord drec;
- drec.File = fnd;
+ wxXmlResourceDataRecord *drec = new wxXmlResourceDataRecord;
+ drec->File = fnd;
Data().push_back(drec);
}
- if (iswild)
- fnd = wxXmlFindNext;
- else
- fnd = wxEmptyString;
+ fnd = wxXmlFindNext;
}
# undef wxXmlFindFirst
# undef wxXmlFindNext
- return rt && UpdateResources();
+
+ return UpdateResources();
}
bool wxXmlResource::Unload(const wxString& filename)
#if wxUSE_FILESYSTEM
if ( isArchive )
{
- if ( i->File.StartsWith(fnd) )
+ if ( (*i)->File.StartsWith(fnd) )
unloaded = true;
// don't break from the loop, we can have other matching files
}
else // a single resource URL
#endif // wxUSE_FILESYSTEM
{
- if ( i->File == fnd )
+ if ( (*i)->File == fnd )
{
+ delete *i;
Data().erase(i);
unloaded = true;
for ( wxXmlResourceDataRecords::iterator i = Data().begin();
i != Data().end(); ++i )
{
- modif = (i->Doc == NULL);
+ wxXmlResourceDataRecord* const rec = *i;
+
+ modif = (rec->Doc == NULL);
if (!modif && !(m_flags & wxXRC_NO_RELOADING))
{
# if wxUSE_FILESYSTEM
- file = fsys.OpenFile(i->File);
+ file = fsys.OpenFile(rec->File);
# if wxUSE_DATETIME
- modif = file && file->GetModificationTime() > i->Time;
+ modif = file && file->GetModificationTime() > rec->Time;
# else // wxUSE_DATETIME
modif = true;
# endif // wxUSE_DATETIME
if (!file)
{
- wxLogError(_("Cannot open file '%s'."), i->File.c_str());
+ wxLogError(_("Cannot open file '%s'."), rec->File);
rt = false;
}
wxDELETE(file);
wxUnusedVar(file);
# else // wxUSE_FILESYSTEM
# if wxUSE_DATETIME
- modif = wxDateTime(wxFileModificationTime(i->File)) > i->Time;
+ modif = wxDateTime(wxFileModificationTime(rec->File)) > rec->Time;
# else // wxUSE_DATETIME
modif = true;
# endif // wxUSE_DATETIME
if (modif)
{
- wxLogTrace(_T("xrc"),
- _T("opening file '%s'"), i->File.c_str());
+ wxLogTrace(_T("xrc"), _T("opening file '%s'"), rec->File);
wxInputStream *stream = NULL;
# if wxUSE_FILESYSTEM
- file = fsys.OpenFile(i->File);
+ file = fsys.OpenFile(rec->File);
if (file)
stream = file->GetStream();
# else
- stream = new wxFileInputStream(i->File);
+ stream = new wxFileInputStream(rec->File);
# endif
if (stream)
{
- delete i->Doc;
- i->Doc = new wxXmlDocument;
+ delete rec->Doc;
+ rec->Doc = new wxXmlDocument;
}
- if (!stream || !i->Doc->Load(*stream, encoding))
+ if (!stream || !stream->IsOk() || !rec->Doc->Load(*stream, encoding))
{
wxLogError(_("Cannot load resources from file '%s'."),
- i->File.c_str());
- wxDELETE(i->Doc);
+ rec->File);
+ wxDELETE(rec->Doc);
rt = false;
}
- else if (i->Doc->GetRoot()->GetName() != wxT("resource"))
+ else if (rec->Doc->GetRoot()->GetName() != wxT("resource"))
{
- wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), i->File.c_str());
- wxDELETE(i->Doc);
+ wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), rec->File);
+ wxDELETE(rec->Doc);
rt = false;
}
else
{
long version;
int v1, v2, v3, v4;
- wxString verstr = i->Doc->GetRoot()->GetAttribute(
+ wxString verstr = rec->Doc->GetRoot()->GetAttribute(
wxT("version"), wxT("0.0.0.0"));
if (wxSscanf(verstr.c_str(), wxT("%i.%i.%i.%i"),
&v1, &v2, &v3, &v4) == 4)
rt = false;
}
- ProcessPlatformProperty(i->Doc->GetRoot());
+ ProcessPlatformProperty(rec->Doc->GetRoot());
#if wxUSE_DATETIME
#if wxUSE_FILESYSTEM
- i->Time = file->GetModificationTime();
+ rec->Time = file->GetModificationTime();
#else // wxUSE_FILESYSTEM
- i->Time = wxDateTime(wxFileModificationTime(i->File));
+ rec->Time = wxDateTime(wxFileModificationTime(rec->File));
#endif // wxUSE_FILESYSTEM
#endif // wxUSE_DATETIME
}
for ( wxXmlResourceDataRecords::const_iterator f = Data().begin();
f != Data().end(); ++f )
{
- if ( f->Doc == NULL || f->Doc->GetRoot() == NULL )
+ wxXmlResourceDataRecord* const rec = *f;
+ if ( rec->Doc == NULL || rec->Doc->GetRoot() == NULL )
continue;
- wxXmlNode* found = DoFindResource(f->Doc->GetRoot(),
+ wxXmlNode* found = DoFindResource(rec->Doc->GetRoot(),
name, classname, recursive);
if ( found )
{
#if wxUSE_FILESYSTEM
- m_curFileSystem.ChangePathTo(f->File);
+ m_curFileSystem.ChangePathTo(rec->File);
#endif
return found;
}
wxXmlNode *parNode = GetParamNode(param);
wxString str1(GetNodeContent(parNode));
wxString str2;
- const wxChar *dt;
- wxChar amp_char;
+
+ // "\\" wasn't translated to "\" prior to 2.5.3.0:
+ const bool escapeBackslash = (m_resource->CompareVersion(2,5,3,0) >= 0);
// VS: First version of XRC resources used $ instead of & (which is
// illegal in XML), but later I realized that '_' fits this purpose
// much better (because &File means "File with F underlined").
- if (m_resource->CompareVersion(2,3,0,1) < 0)
- amp_char = wxT('$');
- else
- amp_char = wxT('_');
+ const wxChar amp_char = (m_resource->CompareVersion(2,3,0,1) < 0)
+ ? '$' : '_';
- for (dt = str1.c_str(); *dt; dt++)
+ for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
{
// Remap amp_char to &, map double amp_char to amp_char (for things
// like "&File..." -- this is illegal in XML, so we use "_File..."):
- if (*dt == amp_char)
+ if ( *dt == amp_char )
{
if ( *(++dt) == amp_char )
str2 << amp_char;
str2 << wxT('&') << *dt;
}
// Remap \n to CR, \r to LF, \t to TAB, \\ to \:
- else if (*dt == wxT('\\'))
- switch (*(++dt))
+ else if ( *dt == wxT('\\') )
+ {
+ switch ( (*(++dt)).GetValue() )
{
case wxT('n'):
str2 << wxT('\n');
case wxT('\\') :
// "\\" wasn't translated to "\" prior to 2.5.3.0:
- if (m_resource->CompareVersion(2,5,3,0) >= 0)
+ if ( escapeBackslash )
{
str2 << wxT('\\');
break;
str2 << wxT('\\') << *dt;
break;
}
- else str2 << *dt;
+ }
+ else
+ {
+ str2 << *dt;
+ }
}
if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
#else
// The string is internally stored as UTF-8, we have to convert
// it into system's default encoding so that it can be displayed:
- return wxString(str2.mb_str(wxConvUTF8), wxConvLocal);
+ return wxString(str2.wc_str(wxConvUTF8), wxConvLocal);
#endif
}
}
{
wxString str = GetParamValue(param);
+#if wxUSE_INTL
// strings in XRC always use C locale but wxString::ToDouble() uses the
// current one, so transform the string to it supposing that the only
// difference between them is the decimal separator
// TODO: use wxString::ToCDouble() when we have it
str.Replace(wxT("."), wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
wxLOCALE_CAT_NUMBER));
+#endif // wxUSE_INTL
double value;
if (!str.ToDouble(&value))
+bool wxXmlResourceHandler::GetBoolAttr(const wxString& attr, bool defaultv)
+{
+ wxString v;
+ return m_node->GetAttribute(attr, &v) ? v == '1' : defaultv;
+}
+
bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
{
- wxString v = GetParamValue(param);
- v.MakeLower();
- if (!v) return defaultv;
+ const wxString v = GetParamValue(param);
- return (v == wxT("1"));
+ return v.empty() ? defaultv : (v == '1');
}
return wxBitmap(img);
}
-#if wxUSE_ANIMATIONCTRL
-wxAnimation wxXmlResourceHandler::GetAnimation(const wxString& param)
-{
- wxAnimation ani;
-
- /* load the animation from file: */
- wxString name = GetParamValue(param);
- if (name.empty()) return wxNullAnimation;
-#if wxUSE_FILESYSTEM
- wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
- if (fsfile == NULL)
- {
- wxLogError(_("XRC resource: Cannot create animation from '%s'."),
- name.c_str());
- return wxNullAnimation;
- }
- ani.Load(*(fsfile->GetStream()));
- delete fsfile;
-#else
- ani.LoadFile(name);
-#endif
-
- if (!ani.IsOk())
- {
- wxLogError(_("XRC resource: Cannot create animation from '%s'."),
- name.c_str());
- return wxNullAnimation;
- }
-
- return ani;
-}
-#endif // wxUSE_ANIMATIONCTRL
-
-
wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
const wxArtClient& defaultArtClient,
while (n)
{
if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
+ {
+ // TODO: check that there are no other properties/parameters with
+ // the same name and log an error if there are (can't do this
+ // right now as I'm not sure if it's not going to break code
+ // using this function in unintentional way (i.e. for
+ // accessing other things than properties), for example
+ // wxBitmapComboBoxXmlHandler almost surely does
return n;
+ }
n = n->GetNext();
}
return NULL;
}
-
-
bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname)
{
return node->GetAttribute(wxT("class"), wxEmptyString) == classname;
if (hasFacename)
{
wxString faces = GetParamValue(wxT("face"));
- wxArrayString facenames(wxFontEnumerator::GetFacenames());
wxStringTokenizer tk(faces, wxT(","));
+#if wxUSE_FONTENUM
+ wxArrayString facenames(wxFontEnumerator::GetFacenames());
while (tk.HasMoreTokens())
{
int index = facenames.Index(tk.GetNextToken(), false);
break;
}
}
+#else // !wxUSE_FONTENUM
+ // just use the first face name if we can't check its availability:
+ if (tk.HasMoreTokens())
+ facename = tk.GetNextToken();
+#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
}
// encoding
struct XRCID_record
{
- int id;
+ /* Hold the id so that once an id is allocated for a name, it
+ does not get created again by NewControlId at least
+ until we are done with it */
+ wxWindowIDRef id;
char *key;
XRCID_record *next;
};
}
else
{
- (*rec_var)->id = wxNewId();
+ (*rec_var)->id = wxWindowBase::NewControlId();
}
}
return XRCID_Lookup(str_id, value_if_not_found);
}
+/* static */
+wxString wxXmlResource::FindXRCIDById(int numId)
+{
+ for ( int i = 0; i < XRCID_TABLE_SIZE; i++ )
+ {
+ for ( XRCID_record *rec = XRCID_Records[i]; rec; rec = rec->next )
+ {
+ if ( rec->id == numId )
+ return wxString(rec->key);
+ }
+ }
+
+ return wxString();
+}
static void CleanXRCID_Record(XRCID_record *rec)
{
if (rec)
{
CleanXRCID_Record(rec->next);
+
free(rec->key);
delete rec;
}
stdID(wxID_HELP_CONTEXT);
stdID(wxID_CLOSE_ALL);
stdID(wxID_PREFERENCES);
+ stdID(wxID_EDIT);
stdID(wxID_CUT);
stdID(wxID_COPY);
stdID(wxID_PASTE);
stdID(wxID_MAXIMIZE_FRAME);
stdID(wxID_ICONIZE_FRAME);
stdID(wxID_RESTORE_FRAME);
+ stdID(wxID_CDROM);
+ stdID(wxID_CONVERT);
+ stdID(wxID_EXECUTE);
+ stdID(wxID_FLOPPY);
+ stdID(wxID_HARDDISK);
+ stdID(wxID_BOTTOM);
+ stdID(wxID_FIRST);
+ stdID(wxID_LAST);
+ stdID(wxID_TOP);
+ stdID(wxID_INFO);
+ stdID(wxID_JUMP_TO);
+ stdID(wxID_NETWORK);
+ stdID(wxID_SELECT_COLOR);
+ stdID(wxID_SELECT_FONT);
+ stdID(wxID_SORT_ASCENDING);
+ stdID(wxID_SORT_DESCENDING);
+ stdID(wxID_SPELL_CHECK);
+ stdID(wxID_STRIKETHROUGH);
#undef stdID
}
// --------------- module and globals -----------------------------
+// normally we would do the cleanup from wxXmlResourceModule::OnExit() but it
+// can happen that some XRC records have been created because of the use of
+// XRCID() in event tables, which happens during static objects initialization,
+// but then the application initialization failed and so the wx modules were
+// neither initialized nor cleaned up -- this static object does the cleanup in
+// this case
+static struct wxXRCStaticCleanup
+{
+ ~wxXRCStaticCleanup() { CleanXRCID_Records(); }
+} s_staticCleanup;
+
class wxXmlResourceModule: public wxModule
{
DECLARE_DYNAMIC_CLASS(wxXmlResourceModule)