]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/xml/xmlres.cpp
Added alpha blending in prep for FreeType text to canvas.
[wxWidgets.git] / contrib / src / xml / xmlres.cpp
CommitLineData
56d2f750
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: xmlres.cpp
3// Purpose: XML resources
4// Author: Vaclav Slavik
5// Created: 2000/03/05
6// RCS-ID: $Id$
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/wfstream.h"
25#include "wx/filesys.h"
26#include "wx/log.h"
27#include "wx/intl.h"
28#include "wx/tokenzr.h"
29#include "wx/module.h"
792064e9
VS
30#include "wx/bitmap.h"
31#include "wx/image.h"
56d2f750
VS
32
33#include "wx/xml/xml.h"
34#include "wx/xml/xmlres.h"
35
36#include "wx/arrimpl.cpp"
37WX_DEFINE_OBJARRAY(wxXmlResourceDataRecords);
38
39
40wxXmlResource::wxXmlResource()
41{
42 m_Handlers.DeleteContents(TRUE);
43}
44
0ceae932 45wxXmlResource::wxXmlResource(const wxString& filemask)
56d2f750
VS
46{
47 m_Handlers.DeleteContents(TRUE);
0ceae932 48 Load(filemask);
56d2f750
VS
49}
50
51wxXmlResource::~wxXmlResource()
52{
53 ClearHandlers();
54}
55
56
0ceae932 57bool wxXmlResource::Load(const wxString& filemask)
56d2f750
VS
58{
59 wxString fnd;
60 wxXmlResourceDataRecord *drec;
0ceae932 61 bool iswild = wxIsWild(filemask);
56d2f750
VS
62
63#if wxUSE_FILESYSTEM
64 wxFileSystem fsys;
65# define wxXmlFindFirst fsys.FindFirst(filemask, wxFILE)
66# define wxXmlFindNext fsys.FindNext()
67#else
68# define wxXmlFindFirst wxFindFirstFile(filemask, wxFILE)
69# define wxXmlFindNext wxFindNextFile()
56d2f750 70#endif
0ceae932
VS
71 if (iswild)
72 fnd = wxXmlFindFirst;
73 else
74 fnd = filemask;
56d2f750
VS
75 while (!!fnd)
76 {
77#if wxUSE_FILESYSTEM
0ceae932
VS
78 if (filemask.Lower().Matches("*.zip") ||
79 filemask.Lower().Matches("*.rsc"))
56d2f750
VS
80 {
81 wxFileSystem fs2;
82 wxString fnd2;
83
84 fnd2 = fs2.FindFirst(fnd + wxT("#zip:*.xmb"), wxFILE);
85 while (!!fnd2)
86 {
87 drec = new wxXmlResourceDataRecord;
88 drec->File = fnd2;
89 m_Data.Add(drec);
90 fnd2 = fs2.FindNext();
91 }
92 }
93 else
94#endif
95 {
96 drec = new wxXmlResourceDataRecord;
97 drec->File = fnd;
98 m_Data.Add(drec);
99 }
0ceae932
VS
100
101 if (iswild)
102 fnd = wxXmlFindNext;
103 else
104 fnd = wxEmptyString;
56d2f750
VS
105 }
106# undef wxXmlFindFirst
107# undef wxXmlFindNext
108 return TRUE;
109}
110
111
112
113void wxXmlResource::AddHandler(wxXmlResourceHandler *handler)
114{
115 m_Handlers.Append(handler);
116 handler->SetParentResource(this);
117}
118
119
120
121void wxXmlResource::ClearHandlers()
122{
123 m_Handlers.Clear();
124}
125
126
127
128wxMenu *wxXmlResource::LoadMenu(const wxString& name)
129{
130 return (wxMenu*)CreateResFromNode(FindResource(name, wxT("menu")), NULL, NULL);
131}
132
133
134
135wxMenuBar *wxXmlResource::LoadMenuBar(const wxString& name)
136{
137 return (wxMenuBar*)CreateResFromNode(FindResource(name, wxT("menubar")), NULL, NULL);
138}
139
140
141
792064e9
VS
142wxToolBar *wxXmlResource::LoadToolBar(wxWindow *parent, const wxString& name)
143{
144 return (wxToolBar*)CreateResFromNode(FindResource(name, wxT("toolbar")), parent, NULL);
145}
146
147
148
56d2f750
VS
149wxDialog *wxXmlResource::LoadDialog(wxWindow *parent, const wxString& name)
150{
151 wxDialog *dialog = new wxDialog;
152 if (!LoadDialog(dialog, parent, name))
153 { delete dialog; return NULL; }
154 else return dialog;
155}
156
157bool wxXmlResource::LoadDialog(wxDialog *dlg, wxWindow *parent, const wxString& name)
158{
159 return CreateResFromNode(FindResource(name, wxT("dialog")), parent, dlg) != NULL;
160}
161
162
163
164wxPanel *wxXmlResource::LoadPanel(wxWindow *parent, const wxString& name)
165{
166 wxPanel *panel = new wxPanel;
167 if (!LoadPanel(panel, parent, name))
168 { delete panel; return NULL; }
169 else return panel;
170}
171
172bool wxXmlResource::LoadPanel(wxPanel *panel, wxWindow *parent, const wxString& name)
173{
174 return CreateResFromNode(FindResource(name, wxT("panel")), parent, panel) != NULL;
175}
176
177
178
29b5f2cc
VS
179void wxXmlResource::ProcessPlatformProperty(wxXmlNode *node)
180{
181 wxString s;
182 bool isok;
183
184 wxXmlNode *c = node->GetChildren();
185 while (c)
186 {
187 isok = FALSE;
188 if (!c->GetPropVal(_T("platform"), &s))
189 isok = TRUE;
190 else
191 {
192 wxStringTokenizer tkn(s, " |");
193
194 while (tkn.HasMoreTokens())
195 {
196 s = tkn.GetNextToken();
197 if (
198#ifdef __WXMSW__
199 s == wxString(_T("win"))
200#elif defined(__UNIX__)
201 s == wxString(_T("unix"))
202#elif defined(__MAC__)
203 s == wxString(_T("mac"))
204#elif defined(__OS2__)
205 s == wxString(_T("os2"))
206#else
207 FALSE
208#endif
209 ) isok = TRUE;
210 }
211 }
212
213 if (isok)
214 ProcessPlatformProperty(c);
215 else
216 {
217 node->RemoveChild(c);
218 delete c;
219 }
220
221 c = c->GetNext();
222 }
223}
224
225
226
56d2f750
VS
227void wxXmlResource::UpdateResources()
228{
229 bool modif;
230# if wxUSE_FILESYSTEM
231 wxFSFile *file;
232 wxFileSystem fsys;
233# endif
234
235 for (size_t i = 0; i < m_Data.GetCount(); i++)
236 {
237 modif = (m_Data[i].Doc == NULL);
238
239 if (!modif)
240 {
241# if wxUSE_FILESYSTEM
242 file = fsys.OpenFile(m_Data[i].File);
243 modif = file && file->GetModificationTime() > m_Data[i].Time;
244 if (!file)
245 wxLogError(_("Cannot open file '%s'."), m_Data[i].File.c_str());
246 delete file;
247# else
248 modif = wxDateTime(wxFileModificationTime(m_Data[i].File)) > m_Data[i].Time;
249# endif
250 }
251
252 if (modif)
253 {
254 wxInputStream *stream;
255
256# if wxUSE_FILESYSTEM
257 file = fsys.OpenFile(m_Data[i].File);
258 stream = file->GetStream();
259# else
260 stream = new wxFileInputStream(m_Data[i].File);
261# endif
262
263 if (stream)
264 {
265 delete m_Data[i].Doc;
266 m_Data[i].Doc = new wxXmlDocument;
267 }
268 if (!stream || !m_Data[i].Doc->Load(*stream))
0ceae932 269 {
56d2f750 270 wxLogError(_("Cannot load resources from file '%s'."), m_Data[i].File.c_str());
0ceae932
VS
271 delete m_Data[i].Doc;
272 m_Data[i].Doc = NULL;
273 }
274 else if (m_Data[i].Doc->GetRoot()->GetName() != _T("resource"))
275 {
56d2f750 276 wxLogError(_("Invalid XML resource '%s': doesn't have root node 'resource'."), m_Data[i].File.c_str());
0ceae932
VS
277 delete m_Data[i].Doc;
278 m_Data[i].Doc = NULL;
279 }
280 else
281 ProcessPlatformProperty(m_Data[i].Doc->GetRoot());
29b5f2cc 282
56d2f750
VS
283# if wxUSE_FILESYSTEM
284 delete file;
285# else
286 delete stream;
287# endif
288 }
289 }
290}
291
292
293
294wxXmlNode *wxXmlResource::FindResource(const wxString& name, const wxString& type)
295{
296 UpdateResources(); //ensure everything is up-to-date
297
298 wxString dummy;
299 for (size_t f = 0; f < m_Data.GetCount(); f++)
300 {
0ceae932 301 if (m_Data[f].Doc == NULL || m_Data[f].Doc->GetRoot() == NULL) continue;
56d2f750
VS
302 for (wxXmlNode *node = m_Data[f].Doc->GetRoot()->GetChildren();
303 node; node = node->GetNext())
304 if ( node->GetType() == wxXML_ELEMENT_NODE &&
305 (!type || node->GetName() == type) &&
306 node->GetPropVal(wxT("name"), &dummy) &&
29b5f2cc 307 dummy == name)
792064e9
VS
308 {
309#if wxUSE_FILESYSTEM
310 m_CurFileSystem.ChangePathTo(m_Data[f].File);
311#endif
56d2f750 312 return node;
792064e9 313 }
56d2f750
VS
314 }
315
316 wxLogError(_("XML resource '%s' (type '%s') not found!"),
317 name.c_str(), type.c_str());
318 return NULL;
319}
320
321
322
323wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, wxObject *instance)
324{
325 if (node == NULL) return NULL;
326
327 wxXmlResourceHandler *handler;
328 wxObject *ret;
329 wxNode * ND = m_Handlers.GetFirst();
330 while (ND)
331 {
332 handler = (wxXmlResourceHandler*)ND->GetData();
333 if (handler->CanHandle(node))
334 {
335 ret = handler->CreateResource(node, parent, instance);
336 if (ret) return ret;
337 }
338 ND = ND->GetNext();
339 }
340
341 wxLogError(_("No handler found for XML node '%s'!"), node->GetName().c_str());
342 return NULL;
343}
344
345
346
347
348
349
350
351
352
353wxXmlResourceHandler::wxXmlResourceHandler()
354 : m_Node(NULL), m_Parent(NULL), m_Instance(NULL),
355 m_ParentAsWindow(NULL), m_InstanceAsWindow(NULL)
356{}
357
358
359
360wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent, wxObject *instance)
361{
56d2f750
VS
362 wxXmlNode *myNode = m_Node;
363 wxObject *myParent = m_Parent, *myInstance = m_Instance;
364 wxWindow *myParentAW = m_ParentAsWindow, *myInstanceAW = m_InstanceAsWindow;
365
366 m_Node = node;
367 m_Parent = parent;
368 m_Instance = instance;
369 m_ParentAsWindow = wxDynamicCast(m_Parent, wxWindow);
370 m_InstanceAsWindow = wxDynamicCast(m_Instance, wxWindow);
371
372 wxObject *returned = DoCreateResource();
373
374 m_Node = myNode;
375 m_Parent = myParent; m_ParentAsWindow = myParentAW;
376 m_Instance = myInstance; m_InstanceAsWindow = myInstanceAW;
377
378 return returned;
379}
380
381
56d2f750
VS
382void wxXmlResourceHandler::AddStyle(const wxString& name, int value)
383{
384 m_StyleNames.Add(name);
385 m_StyleValues.Add(value);
386}
387
388
09dc1241
VS
389
390void wxXmlResourceHandler::AddWindowStyles()
391{
392 ADD_STYLE(wxSIMPLE_BORDER);
393 ADD_STYLE(wxSUNKEN_BORDER);
394 ADD_STYLE(wxDOUBLE_BORDER);
395 ADD_STYLE(wxRAISED_BORDER);
396 ADD_STYLE(wxSTATIC_BORDER);
397 ADD_STYLE(wxTRANSPARENT_WINDOW);
398 ADD_STYLE(wxWANTS_CHARS);
399 ADD_STYLE(wxNO_FULL_REPAINT_ON_RESIZE);
400}
401
402
403
56d2f750
VS
404bool wxXmlResourceHandler::HasParam(const wxString& param)
405{
406 return (GetParamNode(param) != NULL);
407}
408
409
410int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults)
411{
412 wxString s = GetParamValue(param);
413
414 if (!s) return defaults;
415
416 wxStringTokenizer tkn(s, _T("| "), wxTOKEN_STRTOK);
417 int style = 0;
418 int index;
419 wxString fl;
420 while (tkn.HasMoreTokens())
421 {
422 fl = tkn.GetNextToken();
423 index = m_StyleNames.Index(fl);
424 if (index != wxNOT_FOUND)
425 style |= m_StyleValues[index];
426 else
427 wxLogError(_("Unknown style flag ") + fl);
428 }
429 return style;
430}
431
432
433
434wxString wxXmlResourceHandler::GetText(const wxString& param)
435{
436 wxString str1 = GetParamValue(param);
437 wxString str2;
438 const wxChar *dt;
439
440 for (dt = str1.c_str(); *dt; dt++)
441 {
442 // Remap $ to &, map $$ to $ (for things like "&File..." --
443 // this is illegal in XML, so we use "$File..."):
444 if (*dt == '$')
445 switch (*(++dt))
446 {
447 case '$' : str2 << '$'; break;
448 default : str2 << '&' << *dt; break;
449 }
450 // Remap \n to CR, \r LF, \t to TAB:
451 else if (*dt == '\\')
452 switch (*(++dt))
453 {
454 case 'n' : str2 << '\n'; break;
455 case 't' : str2 << '\t'; break;
456 case 'r' : str2 << '\r'; break;
457 default : str2 << '\\' << *dt; break;
458 }
459 else str2 << *dt;
460 }
461 return str2;
462}
463
464
465
466long wxXmlResourceHandler::GetLong(const wxString& param, long defaultv)
467{
468 long value;
469 wxString str1 = GetParamValue(param);
470
471 if (!str1.ToLong(&value))
472 value = defaultv;
473
474 return value;
475}
476
477
478int wxXmlResourceHandler::GetID()
479{
480 wxString sid = GetName();
481 long num;
482
483 if (sid == _T("-1")) return -1;
484 else if (sid.IsNumber() && sid.ToLong(&num)) return num;
485#define stdID(id) else if (sid == _T(#id)) return id
486 stdID(wxID_OPEN); stdID(wxID_CLOSE); stdID(wxID_NEW);
487 stdID(wxID_SAVE); stdID(wxID_SAVEAS); stdID(wxID_REVERT);
488 stdID(wxID_EXIT); stdID(wxID_UNDO); stdID(wxID_REDO);
489 stdID(wxID_HELP); stdID(wxID_PRINT); stdID(wxID_PRINT_SETUP);
490 stdID(wxID_PREVIEW); stdID(wxID_ABOUT); stdID(wxID_HELP_CONTENTS);
491 stdID(wxID_HELP_COMMANDS); stdID(wxID_HELP_PROCEDURES);
492 stdID(wxID_CUT); stdID(wxID_COPY); stdID(wxID_PASTE);
493 stdID(wxID_CLEAR); stdID(wxID_FIND); stdID(wxID_DUPLICATE);
494 stdID(wxID_SELECTALL); stdID(wxID_OK); stdID(wxID_CANCEL);
495 stdID(wxID_APPLY); stdID(wxID_YES); stdID(wxID_NO);
496 stdID(wxID_STATIC); stdID(wxID_FORWARD); stdID(wxID_BACKWARD);
497 stdID(wxID_DEFAULT); stdID(wxID_MORE); stdID(wxID_SETUP);
498 stdID(wxID_RESET); stdID(wxID_HELP_CONTEXT);
499#undef stdID
500 else return XMLID(sid.c_str());
501}
502
503
504wxString wxXmlResourceHandler::GetName()
505{
506 return m_Node->GetPropVal(_T("name"), _T("-1"));
507}
508
509
510
511bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
512{
513 wxString v = GetParamValue(param);
514 v.MakeLower();
515 if (!v) return defaultv;
10461e19 516 else return (v == _T("1"));
56d2f750
VS
517}
518
519
520
521wxColour wxXmlResourceHandler::GetColour(const wxString& param)
522{
523 wxString v = GetParamValue(param);
524 unsigned long tmp = 0;
525
526 if (v.Length() != 7 || v[0] != _T('#') ||
527 wxSscanf(v.c_str(), _T("#%lX"), &tmp) != 1)
528 {
529 wxLogError(_("XML resource: Incorrect colour specification '%s' for property '%s'."),
530 v.c_str(), param.c_str());
531 return wxNullColour;
532 }
533
534 return wxColour((tmp & 0xFF0000) >> 16 ,
535 (tmp & 0x00FF00) >> 8,
536 (tmp & 0x0000FF));
537}
538
539
792064e9
VS
540
541wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param, wxSize size)
542{
543 wxString name = GetParamValue(param);
544 if (name.IsEmpty()) return wxNullBitmap;
545#if wxUSE_FILESYSTEM
546 wxFSFile *fsfile = GetCurFileSystem().OpenFile(name);
547 if (fsfile == NULL)
548 {
549 wxLogError(_("XML resource: Cannot create bitmap from '%s'."), param.mb_str());
550 return wxNullBitmap;
551 }
552 wxImage img(*(fsfile->GetStream()));
553 delete fsfile;
554#else
555 wxImage img(GetParamValue(_T("bitmap")));
556#endif
557 if (!img.Ok())
558 {
559 wxLogError(_("XML resource: Cannot create bitmap from '%s'."), param.mb_str());
560 return wxNullBitmap;
561 }
562 if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y);
563 return img.ConvertToBitmap();
564}
565
566
567
568wxIcon wxXmlResourceHandler::GetIcon(const wxString& param, wxSize size)
569{
bebb14d5 570#if wxCHECK_VERSION(2,3,0) || defined(__WXMSW__)
792064e9
VS
571 wxIcon icon;
572 icon.CopyFromBitmap(GetBitmap(param, size));
573#else
574 wxIcon *iconpt;
575 wxBitmap bmppt = GetBitmap(param, size);
576 iconpt = (wxIcon*)(&bmppt);
577 wxIcon icon(*iconpt);
578#endif
579 return icon;
580}
581
582
583
56d2f750
VS
584wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
585{
586 wxXmlNode *n = m_Node->GetChildren();
587
588 while (n)
589 {
590 if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
591 return n;
592 n = n->GetNext();
593 }
594 return NULL;
595}
596
597
598wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node)
599{
600 wxXmlNode *n = node;
601 if (n == NULL) return wxEmptyString;
602 n = n->GetChildren();
603
604 while (n)
605 {
606 if (n->GetType() == wxXML_TEXT_NODE ||
607 n->GetType() == wxXML_CDATA_SECTION_NODE)
608 return n->GetContent();
609 n = n->GetNext();
610 }
611 return wxEmptyString;
612}
613
614
615
616wxString wxXmlResourceHandler::GetParamValue(const wxString& param)
617{
618 return GetNodeContent(GetParamNode(param));
619}
620
621
622
623wxSize wxXmlResourceHandler::GetSize(const wxString& param)
624{
625 wxString s = GetParamValue(param);
29b5f2cc 626 if (s.IsEmpty()) s = _T("-1,-1");
56d2f750
VS
627 bool is_dlg;
628 long sx, sy;
629
630 is_dlg = s[s.Length()-1] == _T('d');
631 if (is_dlg) s.RemoveLast();
632
633 if (!s.BeforeFirst(_T(',')).ToLong(&sx) ||
634 !s.AfterLast(_T(',')).ToLong(&sy))
635 {
636 wxLogError(_("Cannot parse coordinates from '%s'."), s.mb_str());
637 return wxDefaultSize;
638 }
639
640 if (is_dlg)
641 {
642 if (m_InstanceAsWindow)
643 return wxDLG_UNIT(m_InstanceAsWindow, wxSize(sx, sy));
644 else if (m_ParentAsWindow)
645 return wxDLG_UNIT(m_ParentAsWindow, wxSize(sx, sy));
646 else
647 {
648 wxLogError(_("Cannot convert dialog units: dialog unknown."));
649 return wxDefaultSize;
650 }
651 }
652 else return wxSize(sx, sy);
653}
654
655
656
657wxPoint wxXmlResourceHandler::GetPosition(const wxString& param)
658{
659 wxSize sz = GetSize(param);
660 return wxPoint(sz.x, sz.y);
661}
662
663
664
bebb14d5
VS
665wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, wxCoord defaultv)
666{
667 wxString s = GetParamValue(param);
668 if (s.IsEmpty()) return defaultv;
669 bool is_dlg;
670 long sx;
671
672 is_dlg = s[s.Length()-1] == _T('d');
673 if (is_dlg) s.RemoveLast();
674
675 if (!s.ToLong(&sx))
676 {
677 wxLogError(_("Cannot parse dimension from '%s'."), s.mb_str());
678 return defaultv;
679 }
680
681 if (is_dlg)
682 {
683 if (m_InstanceAsWindow)
684 return wxDLG_UNIT(m_InstanceAsWindow, wxSize(sx, 0)).x;
685 else if (m_ParentAsWindow)
686 return wxDLG_UNIT(m_ParentAsWindow, wxSize(sx, 0)).x;
687 else
688 {
689 wxLogError(_("Cannot convert dialog units: dialog unknown."));
690 return defaultv;
691 }
692 }
693 else return sx;
694}
695
696
697
56d2f750
VS
698void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
699{
700 //FIXME : add font, cursor
701
702 if (HasParam(_T("exstyle")))
703 wnd->SetExtraStyle(GetStyle(_T("exstyle")));
704 if (HasParam(_T("bg")))
705 wnd->SetBackgroundColour(GetColour(_T("bg")));
706 if (HasParam(_T("fg")))
707 wnd->SetForegroundColour(GetColour(_T("fg")));
708 if (GetBool(_T("enabled"), 1) == 0)
709 wnd->Enable(FALSE);
710 if (GetBool(_T("focused"), 0) == 1)
711 wnd->SetFocus();
712 if (GetBool(_T("hidden"), 0) == 1)
713 wnd->Show(FALSE);
714#if wxUSE_TOOLTIPS
715 if (HasParam(_T("tooltip")))
716 wnd->SetToolTip(GetText(_T("tooltip")));
717#endif
718}
719
720
721void wxXmlResourceHandler::CreateChildren(wxObject *parent,
722 bool only_this_handler, wxXmlNode *children_node)
723{
724 if (children_node == NULL) children_node = GetParamNode(_T("children"));
725 if (children_node == NULL) return;
792064e9 726
56d2f750 727 wxXmlNode *n = children_node->GetChildren();
792064e9 728
56d2f750
VS
729 while (n)
730 {
731 if (n->GetType() == wxXML_ELEMENT_NODE)
732 {
733 if (only_this_handler)
734 {
735 if (CanHandle(n))
736 CreateResource(n, parent, NULL);
737 }
738 else
739 m_Resource->CreateResFromNode(n, parent, NULL);
740 }
741 n = n->GetNext();
742 }
743}
744
745
746
747
748
749
750
751
752
753// --------------- XMLID implementation -----------------------------
754
56d2f750
VS
755#define XMLID_TABLE_SIZE 1024
756
29b5f2cc 757
56d2f750
VS
758struct XMLID_record
759{
760 int id;
29b5f2cc 761 char *key;
56d2f750
VS
762 XMLID_record *next;
763};
764
765static XMLID_record *XMLID_Records[XMLID_TABLE_SIZE] = {NULL};
766static int XMLID_LastID = wxID_HIGHEST;
767
768/*static*/ int wxXmlResource::GetXMLID(const char *str_id)
769{
770 int index = 0;
771
772 for (const char *c = str_id; *c != '\0'; c++) index += (int)*c;
773 index %= XMLID_TABLE_SIZE;
774
775 XMLID_record *oldrec = NULL;
29b5f2cc 776 int matchcnt = 0;
56d2f750
VS
777 for (XMLID_record *rec = XMLID_Records[index]; rec; rec = rec->next)
778 {
29b5f2cc
VS
779 if (strcmp(rec->key, str_id) == 0)
780 {
29b5f2cc
VS
781 return rec->id;
782 }
783 matchcnt++;
56d2f750
VS
784 oldrec = rec;
785 }
786
787 XMLID_record **rec_var = (oldrec == NULL) ?
788 &XMLID_Records[index] : &oldrec->next;
789 *rec_var = new XMLID_record;
790 (*rec_var)->id = ++XMLID_LastID;
29b5f2cc 791 (*rec_var)->key = strdup(str_id);
56d2f750
VS
792 (*rec_var)->next = NULL;
793
794 return (*rec_var)->id;
795}
796
797
798static void CleanXMLID_Record(XMLID_record *rec)
799{
800 if (rec)
801 {
802 CleanXMLID_Record(rec->next);
29b5f2cc 803 free (rec->key);
56d2f750
VS
804 delete rec;
805 }
806}
807
808static void CleanXMLID_Records()
809{
810 for (int i = 0; i < XMLID_TABLE_SIZE; i++)
811 CleanXMLID_Record(XMLID_Records[i]);
812}
813
814
815
816
817
818
819
820
821// --------------- module and globals -----------------------------
822
823
824static wxXmlResource gs_XmlResource;
825
826wxXmlResource *wxTheXmlResource = &gs_XmlResource;
827
828
829class wxXmlResourceModule: public wxModule
830{
831DECLARE_DYNAMIC_CLASS(wxXmlResourceModule)
832public:
833 wxXmlResourceModule() {}
834 bool OnInit() {return TRUE;}
835 void OnExit()
836 {
837 wxTheXmlResource->ClearHandlers();
838 CleanXMLID_Records();
839 }
840};
841
842IMPLEMENT_DYNAMIC_CLASS(wxXmlResourceModule, wxModule)