home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / src / xrc / xmlres.cpp < prev    next >
C/C++ Source or Header  |  2002-08-27  |  33KB  |  1,191 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        xmlres.cpp
  3. // Purpose:     XRC resources
  4. // Author:      Vaclav Slavik
  5. // Created:     2000/03/05
  6. // RCS-ID:      $Id: xmlres.cpp,v 1.22 2002/08/25 12:14:37 VS Exp $
  7. // Copyright:   (c) 2000 Vaclav Slavik
  8. // Licence:     wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #ifdef __GNUG__
  12. #pragma implementation "xmlres.h"
  13. #endif
  14.  
  15. // For compilers that support precompilation, includes "wx.h".
  16. #include "wx/wxprec.h"
  17.  
  18. #ifdef __BORLANDC__
  19.     #pragma hdrstop
  20. #endif
  21.  
  22. #include "wx/dialog.h"
  23. #include "wx/panel.h"
  24. #include "wx/frame.h"
  25. #include "wx/wfstream.h"
  26. #include "wx/filesys.h"
  27. #include "wx/log.h"
  28. #include "wx/intl.h"
  29. #include "wx/tokenzr.h"
  30. #include "wx/fontenum.h"
  31. #include "wx/module.h"
  32. #include "wx/bitmap.h"
  33. #include "wx/image.h"
  34. #include "wx/fontmap.h"
  35. #include "wx/artprov.h"
  36.  
  37. #include "wx/xrc/xml.h"
  38. #include "wx/xrc/xmlres.h"
  39.  
  40. #include "wx/arrimpl.cpp"
  41. WX_DEFINE_OBJARRAY(wxXmlResourceDataRecords);
  42.  
  43.  
  44. wxXmlResource *wxXmlResource::ms_instance = NULL;
  45.  
  46. /*static*/ wxXmlResource *wxXmlResource::Get()
  47. {
  48.     if ( !ms_instance )
  49.         ms_instance = new wxXmlResource;
  50.     return ms_instance;
  51. }
  52.  
  53. /*static*/ wxXmlResource *wxXmlResource::Set(wxXmlResource *res)
  54. {
  55.     wxXmlResource *old = ms_instance;
  56.     ms_instance = res;
  57.     return old;
  58. }
  59.  
  60. wxXmlResource::wxXmlResource(int flags)
  61. {
  62.     m_handlers.DeleteContents(TRUE);
  63.     m_flags = flags;
  64.     m_version = -1;
  65. }
  66.  
  67. wxXmlResource::wxXmlResource(const wxString& filemask, int flags)
  68. {
  69.     m_flags = flags;
  70.     m_version = -1;
  71.     m_handlers.DeleteContents(TRUE);
  72.     Load(filemask);
  73. }
  74.  
  75. wxXmlResource::~wxXmlResource()
  76. {
  77.     ClearHandlers();
  78. }
  79.  
  80.  
  81. bool wxXmlResource::Load(const wxString& filemask)
  82. {
  83.     wxString fnd;
  84.     wxXmlResourceDataRecord *drec;
  85.     bool iswild = wxIsWild(filemask);
  86.     bool rt = TRUE;
  87.  
  88. #if wxUSE_FILESYSTEM
  89.     wxFileSystem fsys;
  90. #   define wxXmlFindFirst  fsys.FindFirst(filemask, wxFILE)
  91. #   define wxXmlFindNext   fsys.FindNext()
  92. #else
  93. #   define wxXmlFindFirst  wxFindFirstFile(filemask, wxFILE)
  94. #   define wxXmlFindNext   wxFindNextFile()
  95. #endif
  96.     if (iswild)
  97.         fnd = wxXmlFindFirst;
  98.     else
  99.         fnd = filemask;
  100.     while (!!fnd)
  101.     {
  102. #if wxUSE_FILESYSTEM
  103.         if (filemask.Lower().Matches(wxT("*.zip")) ||
  104.             filemask.Lower().Matches(wxT("*.xrs")))
  105.         {
  106.             rt = rt && Load(fnd + wxT("#zip:*.xmlbin"));
  107.             rt = rt && Load(fnd + wxT("#zip:*.xrc"));
  108.         }
  109.         else
  110. #endif
  111.         {
  112.             drec = new wxXmlResourceDataRecord;
  113.             drec->File = fnd;
  114.             m_data.Add(drec);
  115.         }
  116.  
  117.         if (iswild)
  118.             fnd = wxXmlFindNext;
  119.         else
  120.             fnd = wxEmptyString;
  121.     }
  122. #   undef wxXmlFindFirst
  123. #   undef wxXmlFindNext
  124.     return rt;
  125. }
  126.  
  127.  
  128.  
  129. void wxXmlResource::AddHandler(wxXmlResourceHandler *handler)
  130. {
  131.     m_handlers.Append(handler);
  132.     handler->SetParentResource(this);
  133. }
  134.  
  135. void wxXmlResource::InsertHandler(wxXmlResourceHandler *handler)
  136. {
  137.     m_handlers.Insert(handler);
  138.     handler->SetParentResource(this);
  139. }
  140.  
  141.  
  142.  
  143. void wxXmlResource::ClearHandlers()
  144. {
  145.     m_handlers.Clear();
  146. }
  147.  
  148.  
  149.  
  150. wxMenu *wxXmlResource::LoadMenu(const wxString& name)
  151. {
  152.     return (wxMenu*)CreateResFromNode(FindResource(name, wxT("wxMenu")), NULL, NULL);
  153. }
  154.  
  155.  
  156.  
  157. wxMenuBar *wxXmlResource::LoadMenuBar(wxWindow *parent, const wxString& name)
  158. {
  159.     return (wxMenuBar*)CreateResFromNode(FindResource(name, wxT("wxMenuBar")), parent, NULL);
  160. }
  161.  
  162.  
  163.  
  164. #if wxUSE_TOOLBAR
  165. wxToolBar *wxXmlResource::LoadToolBar(wxWindow *parent, const wxString& name)
  166. {
  167.     return (wxToolBar*)CreateResFromNode(FindResource(name, wxT("wxToolBar")), parent, NULL);
  168. }
  169. #endif
  170.  
  171.  
  172. wxDialog *wxXmlResource::LoadDialog(wxWindow *parent, const wxString& name)
  173. {
  174.     return (wxDialog*)CreateResFromNode(FindResource(name, wxT("wxDialog")), parent, NULL);
  175. }
  176.  
  177. bool wxXmlResource::LoadDialog(wxDialog *dlg, wxWindow *parent, const wxString& name)
  178. {
  179.     return CreateResFromNode(FindResource(name, wxT("wxDialog")), parent, dlg) != NULL;
  180. }
  181.  
  182.  
  183.  
  184. wxPanel *wxXmlResource::LoadPanel(wxWindow *parent, const wxString& name)
  185. {
  186.     return (wxPanel*)CreateResFromNode(FindResource(name, wxT("wxPanel")), parent, NULL);
  187. }
  188.  
  189. bool wxXmlResource::LoadPanel(wxPanel *panel, wxWindow *parent, const wxString& name)
  190. {
  191.     return CreateResFromNode(FindResource(name, wxT("wxPanel")), parent, panel) != NULL;
  192. }
  193.  
  194. wxFrame *wxXmlResource::LoadFrame(wxWindow* parent, const wxString& name)
  195. {
  196.     return (wxFrame*)CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, NULL);
  197. }
  198.  
  199. bool wxXmlResource::LoadFrame(wxFrame* frame, wxWindow *parent, const wxString& name)
  200. {
  201.     return CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, frame) != NULL;
  202. }
  203.  
  204. wxBitmap wxXmlResource::LoadBitmap(const wxString& name)
  205. {
  206.     wxBitmap *bmp = (wxBitmap*)CreateResFromNode(
  207.                                FindResource(name, wxT("wxBitmap")), NULL, NULL);
  208.     wxBitmap rt;
  209.  
  210.     if (bmp) { rt = *bmp; delete bmp; }
  211.     return rt;
  212. }
  213.  
  214. wxIcon wxXmlResource::LoadIcon(const wxString& name)
  215. {
  216.     wxIcon *icon = (wxIcon*)CreateResFromNode(
  217.                             FindResource(name, wxT("wxIcon")), NULL, NULL);
  218.     wxIcon rt;
  219.  
  220.     if (icon) { rt = *icon; delete icon; }
  221.     return rt;
  222. }
  223.  
  224.  
  225. wxObject *wxXmlResource::LoadObject(wxWindow *parent, const wxString& name, const wxString& classname)
  226. {
  227.     return CreateResFromNode(FindResource(name, classname), parent, NULL);
  228. }
  229.  
  230. bool wxXmlResource::LoadObject(wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname)
  231. {
  232.     return CreateResFromNode(FindResource(name, classname), parent, instance) != NULL;
  233. }
  234.  
  235.  
  236. bool wxXmlResource::AttachUnknownControl(const wxString& name,
  237.                                          wxWindow *control, wxWindow *parent)
  238. {
  239.     if (parent == NULL)
  240.         parent = control->GetParent();
  241.     wxWindow *container = parent->FindWindow(name + wxT("_container"));
  242.     if (!container)
  243.     {
  244.         wxLogError(_("Cannot find container for unknown control '%s'."), name.c_str());
  245.         return FALSE;
  246.     }
  247.     return control->Reparent(container);
  248. }
  249.  
  250.  
  251. static void ProcessPlatformProperty(wxXmlNode *node)
  252. {
  253.     wxString s;
  254.     bool isok;
  255.  
  256.     wxXmlNode *c = node->GetChildren();
  257.     while (c)
  258.     {
  259.         isok = FALSE;
  260.         if (!c->GetPropVal(wxT("platform"), &s))
  261.             isok = TRUE;
  262.         else
  263.         {
  264.             wxStringTokenizer tkn(s, " |");
  265.  
  266.             while (tkn.HasMoreTokens())
  267.             {
  268.                 s = tkn.GetNextToken();
  269.                 if (
  270. #ifdef __WXMSW__
  271.                     s == wxString(wxT("win"))
  272. #elif defined(__UNIX__)
  273.                     s == wxString(wxT("unix"))
  274. #elif defined(__MAC__)
  275.                     s == wxString(wxT("mac"))
  276. #elif defined(__OS2__)
  277.                     s == wxString(wxT("os2"))
  278. #else
  279.                     FALSE
  280. #endif
  281.               ) isok = TRUE;
  282.             }
  283.         }
  284.  
  285.         if (isok)
  286.         {
  287.             ProcessPlatformProperty(c);
  288.             c = c->GetNext();
  289.         }
  290.         else
  291.         {
  292.             wxXmlNode *c2 = c->GetNext();
  293.             node->RemoveChild(c);
  294.             delete c;
  295.             c = c2;
  296.         }
  297.     }
  298. }
  299.  
  300.  
  301.  
  302. void wxXmlResource::UpdateResources()
  303. {
  304.     bool modif;
  305. #   if wxUSE_FILESYSTEM
  306.     wxFSFile *file = NULL;
  307.     wxFileSystem fsys;
  308. #   endif
  309.  
  310.     wxString encoding(wxT("UTF-8"));
  311. #if !wxUSE_UNICODE && wxUSE_INTL
  312.     if ( (GetFlags() & wxXRC_USE_LOCALE) == 0 )
  313.     {
  314.         // In case we are not using wxLocale to translate strings, convert the strings
  315.         // GUI's charset. This must not be done when wxXRC_USE_LOCALE is on, because
  316.         // it could break wxGetTranslation lookup.
  317.         encoding = wxLocale::GetSystemEncodingName();
  318.     }
  319. #endif
  320.  
  321.     for (size_t i = 0; i < m_data.GetCount(); i++)
  322.     {
  323.         modif = (m_data[i].Doc == NULL);
  324.  
  325.         if (!modif)
  326.         {
  327. #           if wxUSE_FILESYSTEM
  328.             file = fsys.OpenFile(m_data[i].File);
  329.             modif = file && file->GetModificationTime() > m_data[i].Time;
  330.             if (!file)
  331.                 wxLogError(_("Cannot open file '%s'."), m_data[i].File.c_str());
  332.             wxDELETE(file);
  333. #           else
  334.             modif = wxDateTime(wxFileModificationTime(m_data[i].File)) > m_data[i].Time;
  335. #           endif
  336.         }
  337.  
  338.         if (modif)
  339.         {
  340.             wxInputStream *stream = NULL;
  341.  
  342. #           if wxUSE_FILESYSTEM
  343.             file = fsys.OpenFile(m_data[i].File);
  344.             if (file)
  345.                 stream = file->GetStream();
  346. #           else
  347.             stream = new wxFileInputStream(m_data[i].File);
  348. #           endif
  349.  
  350.             if (stream)
  351.             {
  352.                 delete m_data[i].Doc;
  353.                 m_data[i].Doc = new wxXmlDocument;
  354.             }
  355.             if (!stream || !m_data[i].Doc->Load(*stream, encoding))
  356.             {
  357.                 wxLogError(_("Cannot load resources from file '%s'."),
  358.                            m_data[i].File.c_str());
  359.                 wxDELETE(m_data[i].Doc);
  360.             }
  361.             else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource"))
  362.             {
  363.                 wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), m_data[i].File.c_str());
  364.                 wxDELETE(m_data[i].Doc);
  365.             }
  366.             else
  367.             {
  368.                 long version;
  369.                 int v1, v2, v3, v4;
  370.                 wxString verstr = m_data[i].Doc->GetRoot()->GetPropVal(
  371.                                       wxT("version"), wxT("0.0.0.0"));
  372.                 if (wxSscanf(verstr.c_str(), wxT("%i.%i.%i.%i"),
  373.                     &v1, &v2, &v3, &v4) == 4)
  374.                     version = v1*256*256*256+v2*256*256+v3*256+v4;
  375.                 else
  376.                     version = 0;
  377.                 if (m_version == -1)
  378.                     m_version = version;
  379.                 if (m_version != version)
  380.                     wxLogError(_("Resource files must have same version number!"));
  381.  
  382.                 ProcessPlatformProperty(m_data[i].Doc->GetRoot());
  383.                 m_data[i].Time = file->GetModificationTime();
  384.             }
  385.  
  386. #           if wxUSE_FILESYSTEM
  387.                 wxDELETE(file);
  388. #           else
  389.                 wxDELETE(stream);
  390. #           endif
  391.         }
  392.     }
  393. }
  394.  
  395.  
  396. wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent,
  397.                                          const wxString& name,
  398.                                          const wxString& classname,
  399.                                          bool recursive)
  400. {
  401.     wxString dummy;
  402.     wxXmlNode *node;
  403.  
  404.     // first search for match at the top-level nodes (as this is
  405.     // where the resource is most commonly looked for):
  406.     for (node = parent->GetChildren(); node; node = node->GetNext())
  407.     {
  408.         if ( node->GetType() == wxXML_ELEMENT_NODE &&
  409.                  (node->GetName() == wxT("object") ||
  410.                   node->GetName() == wxT("object_ref")) &&
  411.                 (!classname ||
  412.                  node->GetPropVal(wxT("class"), wxEmptyString) == classname) &&
  413.                 node->GetPropVal(wxT("name"), &dummy) && dummy == name )
  414.             return node;
  415.     }
  416.  
  417.     if ( recursive )
  418.         for (node = parent->GetChildren(); node; node = node->GetNext())
  419.         {
  420.             if ( node->GetType() == wxXML_ELEMENT_NODE &&
  421.                  (node->GetName() == wxT("object") ||
  422.                   node->GetName() == wxT("object_ref")) )
  423.             {
  424.                 wxXmlNode* found = DoFindResource(node, name, classname, TRUE);
  425.                 if ( found )
  426.                     return found;
  427.             }
  428.         }
  429.  
  430.    return NULL;
  431. }
  432.  
  433. wxXmlNode *wxXmlResource::FindResource(const wxString& name,
  434.                                        const wxString& classname,
  435.                                        bool recursive)
  436. {
  437.     UpdateResources(); //ensure everything is up-to-date
  438.  
  439.     wxString dummy;
  440.     for (size_t f = 0; f < m_data.GetCount(); f++)
  441.     {
  442.         if ( m_data[f].Doc == NULL || m_data[f].Doc->GetRoot() == NULL )
  443.             continue;
  444.  
  445.         wxXmlNode* found = DoFindResource(m_data[f].Doc->GetRoot(),
  446.                                           name, classname, recursive);
  447.         if ( found )
  448.         {
  449. #if wxUSE_FILESYSTEM
  450.             m_curFileSystem.ChangePathTo(m_data[f].File);
  451. #endif
  452.             return found;
  453.         }
  454.     }
  455.  
  456.     wxLogError(_("XRC resource '%s' (class '%s') not found!"),
  457.                name.c_str(), classname.c_str());
  458.     return NULL;
  459. }
  460.  
  461. static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
  462. {
  463.     // Merge properties:
  464.     for (wxXmlProperty *prop = with.GetProperties(); prop; prop = prop->GetNext())
  465.     {
  466.         wxXmlProperty *dprop;
  467.         for (dprop = dest.GetProperties(); dprop; dprop = dprop->GetNext())
  468.         {
  469.  
  470.             if ( dprop->GetName() == prop->GetName() )
  471.             {
  472.                 dprop->SetValue(prop->GetValue());
  473.                 break;
  474.             }
  475.         }
  476.  
  477.         if ( !dprop )
  478.             dest.AddProperty(prop->GetName(), prop->GetValue());
  479.    }
  480.  
  481.     // Merge child nodes:
  482.     for (wxXmlNode* node = with.GetChildren(); node; node = node->GetNext())
  483.     {
  484.         wxString name = node->GetPropVal(wxT("name"), wxEmptyString);
  485.         wxXmlNode *dnode;
  486.  
  487.         for (dnode = dest.GetChildren(); dnode; dnode = dnode->GetNext() )
  488.         {
  489.             if ( dnode->GetName() == node->GetName() &&
  490.                  dnode->GetPropVal("name", wxEmptyString) == name &&
  491.                  dnode->GetType() == node->GetType() )
  492.             {
  493.                 MergeNodes(*dnode, *node);
  494.                 break;
  495.             }
  496.         }
  497.  
  498.         if ( !dnode )
  499.             dest.AddChild(new wxXmlNode(*node));
  500.     }
  501.  
  502.     if ( dest.GetType() == wxXML_TEXT_NODE && with.GetContent().Length() )
  503.          dest.SetContent(with.GetContent());
  504. }
  505.  
  506. wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, wxObject *instance)
  507. {
  508.     if (node == NULL) return NULL;
  509.  
  510.     // handling of referenced resource
  511.     if ( node->GetName() == wxT("object_ref") )
  512.     {
  513.         wxString refName = node->GetPropVal(wxT("ref"), wxEmptyString);
  514.         wxXmlNode* refNode = FindResource(refName, wxEmptyString, TRUE);
  515.  
  516.         if ( !refNode )
  517.         {
  518.             wxLogError(_("Referenced object node with ref=\"%s\" not found!"),
  519.                        refName.c_str());
  520.             return NULL;
  521.         }
  522.  
  523.         wxXmlNode copy(*refNode);
  524.         MergeNodes(copy, *node);
  525.  
  526.         return CreateResFromNode(©, parent, instance);
  527.     }
  528.  
  529.     wxXmlResourceHandler *handler;
  530.     wxObject *ret;
  531.     wxNode * ND = m_handlers.GetFirst();
  532.     while (ND)
  533.     {
  534.         handler = (wxXmlResourceHandler*)ND->GetData();
  535.         if (node->GetName() == wxT("object") && handler->CanHandle(node))
  536.         {
  537.             ret = handler->CreateResource(node, parent, instance);
  538.             if (ret) return ret;
  539.         }
  540.         ND = ND->GetNext();
  541.     }
  542.  
  543.     wxLogError(_("No handler found for XML node '%s', class '%s'!"),
  544.                node->GetName().c_str(),
  545.                node->GetPropVal(wxT("class"), wxEmptyString).c_str());
  546.     return NULL;
  547. }
  548.  
  549.  
  550.  
  551.  
  552. wxXmlResourceHandler::wxXmlResourceHandler()
  553.         : m_node(NULL), m_parent(NULL), m_instance(NULL),
  554.           m_parentAsWindow(NULL), m_instanceAsWindow(NULL)
  555. {}
  556.  
  557.  
  558.  
  559. wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent, wxObject *instance)
  560. {
  561.     wxXmlNode *myNode = m_node;
  562.     wxString myClass = m_class;
  563.     wxObject *myParent = m_parent, *myInstance = m_instance;
  564.     wxWindow *myParentAW = m_parentAsWindow, *myInstanceAW = m_instanceAsWindow;
  565.  
  566.     m_instance = instance;
  567.     if (!m_instance && node->HasProp(wxT("subclass")) &&
  568.         !(m_resource->GetFlags() & wxXRC_NO_SUBCLASSING))
  569.     {
  570.         wxString subclass = node->GetPropVal(wxT("subclass"), wxEmptyString);
  571.         wxClassInfo* classInfo = wxClassInfo::FindClass(subclass);
  572.  
  573.         if (classInfo)
  574.             m_instance = classInfo->CreateObject();
  575.  
  576.         if (!m_instance)
  577.         {
  578.             wxLogError(_("Subclass '%s' not found for resource '%s', not subclassing!"),
  579.                        subclass.c_str(), node->GetPropVal(wxT("name"), wxEmptyString).c_str());
  580.         }
  581.  
  582.         m_instance = classInfo->CreateObject();
  583.     }
  584.  
  585.     m_node = node;
  586.     m_class = node->GetPropVal(wxT("class"), wxEmptyString);
  587.     m_parent = parent;
  588.     m_parentAsWindow = wxDynamicCast(m_parent, wxWindow);
  589.     m_instanceAsWindow = wxDynamicCast(m_instance, wxWindow);
  590.  
  591.     wxObject *returned = DoCreateResource();
  592.  
  593.     m_node = myNode;
  594.     m_class = myClass;
  595.     m_parent = myParent; m_parentAsWindow = myParentAW;
  596.     m_instance = myInstance; m_instanceAsWindow = myInstanceAW;
  597.  
  598.     return returned;
  599. }
  600.  
  601.  
  602. void wxXmlResourceHandler::AddStyle(const wxString& name, int value)
  603. {
  604.     m_styleNames.Add(name);
  605.     m_styleValues.Add(value);
  606. }
  607.  
  608.  
  609.  
  610. void wxXmlResourceHandler::AddWindowStyles()
  611. {
  612.     XRC_ADD_STYLE(wxSIMPLE_BORDER);
  613.     XRC_ADD_STYLE(wxSUNKEN_BORDER);
  614.     XRC_ADD_STYLE(wxDOUBLE_BORDER);
  615.     XRC_ADD_STYLE(wxRAISED_BORDER);
  616.     XRC_ADD_STYLE(wxSTATIC_BORDER);
  617.     XRC_ADD_STYLE(wxNO_BORDER);
  618.     XRC_ADD_STYLE(wxTRANSPARENT_WINDOW);
  619.     XRC_ADD_STYLE(wxWANTS_CHARS);
  620.     XRC_ADD_STYLE(wxNO_FULL_REPAINT_ON_RESIZE);
  621. }
  622.  
  623.  
  624.  
  625. bool wxXmlResourceHandler::HasParam(const wxString& param)
  626. {
  627.     return (GetParamNode(param) != NULL);
  628. }
  629.  
  630.  
  631. int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults)
  632. {
  633.     wxString s = GetParamValue(param);
  634.  
  635.     if (!s) return defaults;
  636.  
  637.     wxStringTokenizer tkn(s, wxT("| "), wxTOKEN_STRTOK);
  638.     int style = 0;
  639.     int index;
  640.     wxString fl;
  641.     while (tkn.HasMoreTokens())
  642.     {
  643.         fl = tkn.GetNextToken();
  644.         index = m_styleNames.Index(fl);
  645.         if (index != wxNOT_FOUND)
  646.             style |= m_styleValues[index];
  647.         else
  648.             wxLogError(_("Unknown style flag ") + fl);
  649.     }
  650.     return style;
  651. }
  652.  
  653.  
  654.  
  655. wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
  656. {
  657.     wxString str1(GetParamValue(param));
  658.     wxString str2;
  659.     const wxChar *dt;
  660.     wxChar amp_char;
  661.  
  662.     // VS: First version of XRC resources used $ instead of & (which is
  663.     //     illegal in XML), but later I realized that '_' fits this purpose
  664.     //     much better (because &File means "File with F underlined").
  665.     if (m_resource->CompareVersion(2,3,0,1) < 0)
  666.         amp_char = wxT('$');
  667.     else
  668.         amp_char = wxT('_');
  669.  
  670.     for (dt = str1.c_str(); *dt; dt++)
  671.     {
  672.         // Remap amp_char to &, map double amp_char to amp_char (for things
  673.         // like "&File..." -- this is illegal in XML, so we use "_File..."):
  674.         if (*dt == amp_char)
  675.         {
  676.             if ( *(++dt) == amp_char )
  677.                 str2 << amp_char;
  678.             else
  679.                 str2 << wxT('&') << *dt;
  680.         }
  681.         // Remap \n to CR, \r to LF, \t to TAB:
  682.         else if (*dt == wxT('\\'))
  683.             switch (*(++dt))
  684.             {
  685.                 case wxT('n') : str2 << wxT('\n'); break;
  686.                 case wxT('t') : str2 << wxT('\t'); break;
  687.                 case wxT('r') : str2 << wxT('\r'); break;
  688.                 default       : str2 << wxT('\\') << *dt; break;
  689.             }
  690.         else str2 << *dt;
  691.     }
  692.  
  693.     if (translate && m_resource->GetFlags() & wxXRC_USE_LOCALE)
  694.         return wxGetTranslation(str2);
  695.     else
  696.         return str2;
  697.  
  698. }
  699.  
  700.  
  701.  
  702. long wxXmlResourceHandler::GetLong(const wxString& param, long defaultv)
  703. {
  704.     long value;
  705.     wxString str1 = GetParamValue(param);
  706.  
  707.     if (!str1.ToLong(&value))
  708.         value = defaultv;
  709.  
  710.     return value;
  711. }
  712.  
  713.  
  714.  
  715. int wxXmlResourceHandler::GetID()
  716. {
  717.     wxString sid = GetName();
  718.     long num;
  719.  
  720.     if (sid == wxT("-1")) return -1;
  721.     else if (sid.IsNumber() && sid.ToLong(&num)) return num;
  722. #define stdID(id) else if (sid == wxT(#id)) return id
  723.     stdID(wxID_OPEN); stdID(wxID_CLOSE); stdID(wxID_NEW);
  724.     stdID(wxID_SAVE); stdID(wxID_SAVEAS); stdID(wxID_REVERT);
  725.     stdID(wxID_EXIT); stdID(wxID_UNDO); stdID(wxID_REDO);
  726.     stdID(wxID_HELP); stdID(wxID_PRINT); stdID(wxID_PRINT_SETUP);
  727.     stdID(wxID_PREVIEW); stdID(wxID_ABOUT); stdID(wxID_HELP_CONTENTS);
  728.     stdID(wxID_HELP_COMMANDS); stdID(wxID_HELP_PROCEDURES);
  729.     stdID(wxID_CUT); stdID(wxID_COPY); stdID(wxID_PASTE);
  730.     stdID(wxID_CLEAR); stdID(wxID_FIND); stdID(wxID_DUPLICATE);
  731.     stdID(wxID_SELECTALL); stdID(wxID_OK); stdID(wxID_CANCEL);
  732.     stdID(wxID_APPLY); stdID(wxID_YES); stdID(wxID_NO);
  733.     stdID(wxID_STATIC); stdID(wxID_FORWARD); stdID(wxID_BACKWARD);
  734.     stdID(wxID_DEFAULT); stdID(wxID_MORE); stdID(wxID_SETUP);
  735.     stdID(wxID_RESET); stdID(wxID_HELP_CONTEXT);
  736. #undef stdID
  737.     else return wxXmlResource::GetXRCID(sid);
  738. }
  739.  
  740.  
  741.  
  742. wxString wxXmlResourceHandler::GetName()
  743. {
  744.     return m_node->GetPropVal(wxT("name"), wxT("-1"));
  745. }
  746.  
  747.  
  748.  
  749. bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
  750. {
  751.     wxString v = GetParamValue(param);
  752.     v.MakeLower();
  753.     if (!v) return defaultv;
  754.     else return (v == wxT("1"));
  755. }
  756.  
  757.  
  758.  
  759. wxColour wxXmlResourceHandler::GetColour(const wxString& param)
  760. {
  761.     wxString v = GetParamValue(param);
  762.     unsigned long tmp = 0;
  763.  
  764.     if (v.Length() != 7 || v[0u] != wxT('#') ||
  765.         wxSscanf(v.c_str(), wxT("#%lX"), &tmp) != 1)
  766.     {
  767.         wxLogError(_("XRC resource: Incorrect colour specification '%s' for property '%s'."),
  768.                    v.c_str(), param.c_str());
  769.         return wxNullColour;
  770.     }
  771.  
  772.     return wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) ,
  773.                     (unsigned char) ((tmp & 0x00FF00) >> 8),
  774.                     (unsigned char) ((tmp & 0x0000FF)));
  775. }
  776.  
  777.  
  778.  
  779. wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
  780.                                          const wxArtClient& defaultArtClient,
  781.                                          wxSize size)
  782. {
  783.     /* If the bitmap is specified as stock item, query wxArtProvider for it: */
  784.     wxXmlNode *bmpNode = GetParamNode(param);
  785.     if ( bmpNode )
  786.     {
  787.         wxString sid = bmpNode->GetPropVal(wxT("stock_id"), wxEmptyString);
  788.         if ( !sid.empty() )
  789.         {
  790.             wxString scl = bmpNode->GetPropVal(wxT("stock_client"), defaultArtClient);
  791.             wxBitmap stockArt =
  792.                 wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(sid),
  793.                                          wxART_MAKE_CLIENT_ID_FROM_STR(scl),
  794.                                          size);
  795.             if ( stockArt.Ok() )
  796.                 return stockArt;
  797.         }
  798.     }
  799.  
  800.     /* ...or load the bitmap from file: */
  801.     wxString name = GetParamValue(param);
  802.     if (name.IsEmpty()) return wxNullBitmap;
  803. #if wxUSE_FILESYSTEM
  804.     wxFSFile *fsfile = GetCurFileSystem().OpenFile(name);
  805.     if (fsfile == NULL)
  806.     {
  807.         wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), param.c_str());
  808.         return wxNullBitmap;
  809.     }
  810.     wxImage img(*(fsfile->GetStream()));
  811.     delete fsfile;
  812. #else
  813.     wxImage img(GetParamValue(wxT("bitmap")));
  814. #endif
  815.  
  816.     if (!img.Ok())
  817.     {
  818.         wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), param.c_str());
  819.         return wxNullBitmap;
  820.     }
  821.     if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y);
  822.     return wxBitmap(img);
  823.  
  824. }
  825.  
  826.  
  827.  
  828. wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
  829.                                      const wxArtClient& defaultArtClient,
  830.                                      wxSize size)
  831. {
  832. #if wxCHECK_VERSION(2,3,0) || defined(__WXMSW__)
  833.     wxIcon icon;
  834.     icon.CopyFromBitmap(GetBitmap(param, defaultArtClient, size));
  835. #else
  836.     wxIcon *iconpt;
  837.     wxBitmap bmppt = GetBitmap(param, size);
  838.     iconpt = (wxIcon*)(&bmppt);
  839.     wxIcon icon(*iconpt);
  840. #endif
  841.     return icon;
  842. }
  843.  
  844.  
  845.  
  846. wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
  847. {
  848.     wxXmlNode *n = m_node->GetChildren();
  849.  
  850.     while (n)
  851.     {
  852.         if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
  853.             return n;
  854.         n = n->GetNext();
  855.     }
  856.     return NULL;
  857. }
  858.  
  859.  
  860. wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node)
  861. {
  862.     wxXmlNode *n = node;
  863.     if (n == NULL) return wxEmptyString;
  864.     n = n->GetChildren();
  865.  
  866.     while (n)
  867.     {
  868.         if (n->GetType() == wxXML_TEXT_NODE ||
  869.             n->GetType() == wxXML_CDATA_SECTION_NODE)
  870.             return n->GetContent();
  871.         n = n->GetNext();
  872.     }
  873.     return wxEmptyString;
  874. }
  875.  
  876.  
  877.  
  878. wxString wxXmlResourceHandler::GetParamValue(const wxString& param)
  879. {
  880.     if (param.IsEmpty())
  881.         return GetNodeContent(m_node);
  882.     else
  883.         return GetNodeContent(GetParamNode(param));
  884. }
  885.  
  886.  
  887.  
  888. wxSize wxXmlResourceHandler::GetSize(const wxString& param)
  889. {
  890.     wxString s = GetParamValue(param);
  891.     if (s.IsEmpty()) s = wxT("-1,-1");
  892.     bool is_dlg;
  893.     long sx, sy;
  894.  
  895.     is_dlg = s[s.Length()-1] == wxT('d');
  896.     if (is_dlg) s.RemoveLast();
  897.  
  898.     if (!s.BeforeFirst(wxT(',')).ToLong(&sx) ||
  899.         !s.AfterLast(wxT(',')).ToLong(&sy))
  900.     {
  901.         wxLogError(_("Cannot parse coordinates from '%s'."), s.c_str());
  902.         return wxDefaultSize;
  903.     }
  904.  
  905.     if (is_dlg)
  906.     {
  907.         if (m_instanceAsWindow)
  908.             return wxDLG_UNIT(m_instanceAsWindow, wxSize(sx, sy));
  909.         else if (m_parentAsWindow)
  910.             return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, sy));
  911.         else
  912.         {
  913.             wxLogError(_("Cannot convert dialog units: dialog unknown."));
  914.             return wxDefaultSize;
  915.         }
  916.     }
  917.     else return wxSize(sx, sy);
  918. }
  919.  
  920.  
  921.  
  922. wxPoint wxXmlResourceHandler::GetPosition(const wxString& param)
  923. {
  924.     wxSize sz = GetSize(param);
  925.     return wxPoint(sz.x, sz.y);
  926. }
  927.  
  928.  
  929.  
  930. wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, wxCoord defaultv)
  931. {
  932.     wxString s = GetParamValue(param);
  933.     if (s.IsEmpty()) return defaultv;
  934.     bool is_dlg;
  935.     long sx;
  936.  
  937.     is_dlg = s[s.Length()-1] == wxT('d');
  938.     if (is_dlg) s.RemoveLast();
  939.  
  940.     if (!s.ToLong(&sx))
  941.     {
  942.         wxLogError(_("Cannot parse dimension from '%s'."), s.c_str());
  943.         return defaultv;
  944.     }
  945.  
  946.     if (is_dlg)
  947.     {
  948.         if (m_instanceAsWindow)
  949.             return wxDLG_UNIT(m_instanceAsWindow, wxSize(sx, 0)).x;
  950.         else if (m_parentAsWindow)
  951.             return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, 0)).x;
  952.         else
  953.         {
  954.             wxLogError(_("Cannot convert dialog units: dialog unknown."));
  955.             return defaultv;
  956.         }
  957.     }
  958.     else return sx;
  959. }
  960.  
  961.  
  962.  
  963. wxFont wxXmlResourceHandler::GetFont(const wxString& param)
  964. {
  965.     wxXmlNode *font_node = GetParamNode(param);
  966.     if (font_node == NULL)
  967.     {
  968.         wxLogError(_("Cannot find font node '%s'."), param.c_str());
  969.         return wxNullFont;
  970.     }
  971.  
  972.     wxXmlNode *oldnode = m_node;
  973.     m_node = font_node;
  974.  
  975.     long size = GetLong(wxT("size"), 12);
  976.  
  977.     wxString style = GetParamValue(wxT("style"));
  978.     wxString weight = GetParamValue(wxT("weight"));
  979.     int istyle = wxNORMAL, iweight = wxNORMAL;
  980.     if (style == wxT("italic")) istyle = wxITALIC;
  981.     else if (style == wxT("slant")) istyle = wxSLANT;
  982.     if (weight == wxT("bold")) iweight = wxBOLD;
  983.     else if (weight == wxT("light")) iweight = wxLIGHT;
  984.  
  985.     wxString family = GetParamValue(wxT("family"));
  986.     int ifamily = wxDEFAULT;
  987.          if (family == wxT("decorative")) ifamily = wxDECORATIVE;
  988.     else if (family == wxT("roman")) ifamily = wxROMAN;
  989.     else if (family == wxT("script")) ifamily = wxSCRIPT;
  990.     else if (family == wxT("swiss")) ifamily = wxSWISS;
  991.     else if (family == wxT("modern")) ifamily = wxMODERN;
  992.  
  993.     bool underlined = GetBool(wxT("underlined"), FALSE);
  994.  
  995.     wxString encoding = GetParamValue(wxT("encoding"));
  996.     wxFontMapper mapper;
  997.     wxFontEncoding enc = wxFONTENCODING_DEFAULT;
  998.     if (!encoding.IsEmpty())
  999.         enc = mapper.CharsetToEncoding(encoding);
  1000.     if (enc == wxFONTENCODING_SYSTEM)
  1001.         enc = wxFONTENCODING_DEFAULT;
  1002.  
  1003.     wxString faces = GetParamValue(wxT("face"));
  1004.     wxString facename = wxEmptyString;
  1005.     wxFontEnumerator enu;
  1006.     enu.EnumerateFacenames();
  1007.     wxStringTokenizer tk(faces, wxT(","));
  1008.     while (tk.HasMoreTokens())
  1009.     {
  1010.         int index = enu.GetFacenames()->Index(tk.GetNextToken(), FALSE);
  1011.         if (index != wxNOT_FOUND)
  1012.         {
  1013.             facename = (*enu.GetFacenames())[index];
  1014.             break;
  1015.         }
  1016.     }
  1017.  
  1018.     m_node = oldnode;
  1019.  
  1020.     wxFont font(size, ifamily, istyle, iweight, underlined, facename, enc);
  1021.     return font;
  1022. }
  1023.  
  1024.  
  1025. void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
  1026. {
  1027.     //FIXME : add cursor
  1028.  
  1029.     if (HasParam(wxT("exstyle")))
  1030.         wnd->SetExtraStyle(GetStyle(wxT("exstyle")));
  1031.     if (HasParam(wxT("bg")))
  1032.         wnd->SetBackgroundColour(GetColour(wxT("bg")));
  1033.     if (HasParam(wxT("fg")))
  1034.         wnd->SetForegroundColour(GetColour(wxT("fg")));
  1035.     if (GetBool(wxT("enabled"), 1) == 0)
  1036.         wnd->Enable(FALSE);
  1037.     if (GetBool(wxT("focused"), 0) == 1)
  1038.         wnd->SetFocus();
  1039.     if (GetBool(wxT("hidden"), 0) == 1)
  1040.         wnd->Show(FALSE);
  1041. #if wxUSE_TOOLTIPS
  1042.     if (HasParam(wxT("tooltip")))
  1043.         wnd->SetToolTip(GetText(wxT("tooltip")));
  1044. #endif
  1045.     if (HasParam(wxT("font")))
  1046.         wnd->SetFont(GetFont());
  1047. }
  1048.  
  1049.  
  1050. void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
  1051. {
  1052.     wxXmlNode *n = m_node->GetChildren();
  1053.  
  1054.     while (n)
  1055.     {
  1056.         if (n->GetType() == wxXML_ELEMENT_NODE &&
  1057.             n->GetName() == wxT("object"))
  1058.         {
  1059.             if (this_hnd_only && CanHandle(n))
  1060.                 CreateResource(n, parent, NULL);
  1061.             else
  1062.                 m_resource->CreateResFromNode(n, parent, NULL);
  1063.         }
  1064.         n = n->GetNext();
  1065.     }
  1066. }
  1067.  
  1068.  
  1069. void wxXmlResourceHandler::CreateChildrenPrivately(wxObject *parent, wxXmlNode *rootnode)
  1070. {
  1071.     wxXmlNode *root;
  1072.     if (rootnode == NULL) root = m_node; else root = rootnode;
  1073.     wxXmlNode *n = root->GetChildren();
  1074.  
  1075.     while (n)
  1076.     {
  1077.         if (n->GetType() == wxXML_ELEMENT_NODE && CanHandle(n))
  1078.         {
  1079.             CreateResource(n, parent, NULL);
  1080.         }
  1081.         n = n->GetNext();
  1082.     }
  1083. }
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091. // --------------- XRCID implementation -----------------------------
  1092.  
  1093. #define XRCID_TABLE_SIZE     1024
  1094.  
  1095.  
  1096. struct XRCID_record
  1097. {
  1098.     int id;
  1099.     wxChar *key;
  1100.     XRCID_record *next;
  1101. };
  1102.  
  1103. static XRCID_record *XRCID_Records[XRCID_TABLE_SIZE] = {NULL};
  1104.  
  1105. /*static*/ int wxXmlResource::GetXRCID(const wxChar *str_id)
  1106. {
  1107.     static int XRCID_LastID = wxID_HIGHEST;
  1108.  
  1109.     int index = 0;
  1110.  
  1111.     for (const wxChar *c = str_id; *c != wxT('\0'); c++) index += (int)*c;
  1112.     index %= XRCID_TABLE_SIZE;
  1113.  
  1114.     XRCID_record *oldrec = NULL;
  1115.     int matchcnt = 0;
  1116.     for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next)
  1117.     {
  1118.         if (wxStrcmp(rec->key, str_id) == 0)
  1119.         {
  1120.             return rec->id;
  1121.         }
  1122.         matchcnt++;
  1123.         oldrec = rec;
  1124.     }
  1125.  
  1126.     XRCID_record **rec_var = (oldrec == NULL) ?
  1127.                               &XRCID_Records[index] : &oldrec->next;
  1128.     *rec_var = new XRCID_record;
  1129.     (*rec_var)->id = ++XRCID_LastID;
  1130.     (*rec_var)->key = wxStrdup(str_id);
  1131.     (*rec_var)->next = NULL;
  1132.  
  1133.     return (*rec_var)->id;
  1134. }
  1135.  
  1136.  
  1137. static void CleanXRCID_Record(XRCID_record *rec)
  1138. {
  1139.     if (rec)
  1140.     {
  1141.         CleanXRCID_Record(rec->next);
  1142.         free(rec->key);
  1143.         delete rec;
  1144.     }
  1145. }
  1146.  
  1147. static void CleanXRCID_Records()
  1148. {
  1149.     for (int i = 0; i < XRCID_TABLE_SIZE; i++)
  1150.         CleanXRCID_Record(XRCID_Records[i]);
  1151. }
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160. // --------------- module and globals -----------------------------
  1161.  
  1162. class wxXmlResourceModule: public wxModule
  1163. {
  1164. DECLARE_DYNAMIC_CLASS(wxXmlResourceModule)
  1165. public:
  1166.     wxXmlResourceModule() {}
  1167.     bool OnInit()
  1168.     {
  1169.         return TRUE;
  1170.     }
  1171.     void OnExit()
  1172.     {
  1173.         delete wxXmlResource::Set(NULL);
  1174.         CleanXRCID_Records();
  1175.     }
  1176. };
  1177.  
  1178. IMPLEMENT_DYNAMIC_CLASS(wxXmlResourceModule, wxModule)
  1179.  
  1180.  
  1181. // When wxXml is loaded dynamically after the application is already running
  1182. // then the built-in module system won't pick this one up.  Add it manually.
  1183. void wxXmlInitResourceModule()
  1184. {
  1185.     wxModule* module = new wxXmlResourceModule;
  1186.     module->Init();
  1187.     wxModule::RegisterModule(module);
  1188. }
  1189.  
  1190.  
  1191.