1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdgeorges.h"
22 #include "nel/misc/i_xml.h"
23 #include "nel/misc/o_xml.h"
24 #include "nel/misc/common.h"
25 #include "nel/misc/path.h"
27 #include "nel/georges/form.h"
28 #include "nel/georges/form_loader.h"
34 using namespace NLMISC
;
39 // ***************************************************************************
41 // ***************************************************************************
43 void warning (bool exception
, const char *format
, ... )
45 // Make a buffer string
47 va_start( args
, format
);
49 vsnprintf( buffer
, 1024, format
, args
);
55 // Make an error message
57 smprintf (tmp
, 1024, "NeL::Georges %s", buffer
);
58 throw EXmlParsingError (tmp
);
62 nlwarning ("NeL::Georges %s", buffer
);
66 // ***************************************************************************
68 // ***************************************************************************
74 // ***************************************************************************
76 UFormElm
& CForm::getRootNode ()
81 // ***************************************************************************
83 const UFormElm
& CForm::getRootNode () const
88 // ***************************************************************************
90 // ***************************************************************************
92 CForm::CForm () : Elements (this, NULL
, NULL
, 0xffffffff)
95 for (i
=0; i
<HeldElementCount
; i
++)
97 HeldElements
[i
] = new CFormElmStruct (this, NULL
, NULL
, 0xffffffff);
101 // ***************************************************************************
106 for (i
=0; i
<HeldElementCount
; i
++)
108 delete HeldElements
[i
];
112 // ***************************************************************************
114 void CForm::write (xmlDocPtr doc
, const std::string
&filename
)
117 if (!filename
.empty())
118 _Filename
= CFile::getFilename (filename
);
120 // Create the first node
121 xmlNodePtr node
= xmlNewDocNode (doc
, NULL
, (const xmlChar
*)"FORM", NULL
);
122 xmlDocSetRootElement (doc
, node
);
125 for (uint parent
=0; parent
<ParentList
.size (); parent
++)
127 // Parent name not empty ?
128 if (!(ParentList
[parent
].ParentFilename
.empty()))
131 xmlNodePtr parentNode
= xmlNewChild ( node
, NULL
, (const xmlChar
*)"PARENT", NULL
);
132 xmlSetProp (parentNode
, (const xmlChar
*)"Filename", (const xmlChar
*)ParentList
[parent
].ParentFilename
.c_str());
137 Elements
.write (node
, this, std::string(), true);
139 // Write held elements
141 for (i
=0; i
<HeldElementCount
; i
++)
143 HeldElements
[i
]->write (node
, this, std::string(), true);
150 // ***************************************************************************
152 void CForm::readParent (const char *parent
, CFormLoader
&loader
)
155 CForm
*theParent
= (CForm
*)loader
.loadForm (parent
);
156 if (theParent
!= NULL
)
159 if (!insertParent (getParentCount (), parent
, theParent
))
161 // Make an error message
162 std::string parentName
= parent
;
165 xmlFree ((void*)parent
);
168 warning (true, "readParent", "Can't set the parent FORM named (%s). Check if it is the same form or if it use a differnt formDfn.", parentName
.c_str ());
173 // Make an error message
174 std::string parentName
= parent
;
177 xmlFree ((void*)parent
);
180 warning (true, "readParent", "Can't load the parent FORM named (%s).", parentName
.c_str ());
184 // ***************************************************************************
186 void CForm::read (xmlNodePtr node
, CFormLoader
&loader
, CFormDfn
*dfn
, const std::string
&filename
)
189 _Filename
= CFile::getFilename (filename
);
198 if ( ((const char*)node
->name
== NULL
) || (strcmp ((const char*)node
->name
, "FORM") != 0) )
200 // Make an error message
201 warning (true, "read", "XML Syntax error in block line %d, node (%s) should be FORM.",
202 (sint
)node
->line
, node
->name
);
205 // Get first struct node
206 xmlNodePtr child
= CIXml::getFirstChildNode (node
, "STRUCT");
210 warning (true, "read", "Syntax error in block line %d, node (%s) should have a STRUCT child node.",
211 (sint
)node
->line
, node
->name
);
215 Elements
.read (child
, loader
, dfn
, this);
217 // Get next struct node
218 child
= CIXml::getNextChildNode (node
, "STRUCT");
220 while ( (child
!= NULL
) && (index
< HeldElementCount
))
222 HeldElements
[index
]->read (child
, loader
, dfn
, this);
225 while (index
< HeldElementCount
)
228 HeldElements
[index
]->build (dfn
);
232 // Get the old parent parameter
233 const char *parent
= (const char*)xmlGetProp (node
, (xmlChar
*)"Parent");
236 // Add a parent, xmlFree is done by readParent
237 readParent (parent
, loader
);
240 // Read the new parent nodes
241 uint parentCount
= CIXml::countChildren (node
, "PARENT");
243 // Reserve some parents
244 ParentList
.reserve (ParentList
.size () + parentCount
);
246 // Enum children node
247 child
= CIXml::getFirstChildNode (node
, "PARENT");
250 parent
= (const char*)xmlGetProp (child
, (xmlChar
*)"Filename");
252 // Add a parent, xmlFree is done by readParent
253 readParent (parent
, loader
);
255 // Next node <PARENT>
256 child
= CIXml::getNextChildNode (child
, "PARENT");
263 // ***************************************************************************
265 const std::string
&CForm::getComment () const
267 return Header
.Comments
;
270 // ***************************************************************************
272 void CForm::write (NLMISC::IStream
&stream
)
276 xmlStream
.init (&stream
);
279 write (xmlStream
.getDocument (), std::string());
282 // ***************************************************************************
284 bool CForm::insertParent (uint before
, const std::string
&filename
, CForm
*parent
)
289 // Must have the same DFN
290 if (parent
->Elements
.FormDfn
== Elements
.FormDfn
)
293 std::vector
<CParent
>::iterator ite
= ParentList
.insert (ParentList
.begin() + before
, CParent());
294 ite
->Parent
= parent
;
295 ite
->ParentFilename
= filename
;
302 warning (false, "insertParent", "Can't insert parent form (%s) that has not the same DFN.", filename
.c_str());
308 // ***************************************************************************
310 void CForm::removeParent (uint parent
)
312 ParentList
.erase (ParentList
.begin() + parent
);
315 // ***************************************************************************
317 CForm
*CForm::getParent (uint parent
) const
319 return ParentList
[parent
].Parent
;
322 // ***************************************************************************
324 const std::string
&CForm::getParentFilename (uint parent
) const
326 return ParentList
[parent
].ParentFilename
;
329 // ***************************************************************************
331 uint
CForm::getParentCount () const
333 return (uint
)ParentList
.size ();
336 // ***************************************************************************
343 // ***************************************************************************
345 void CForm::clearParents ()
350 // ***************************************************************************
352 const std::string
&CForm::getFilename () const
357 // ***************************************************************************
359 void CForm::warning (bool exception
, const std::string
&function
, const char *format
, ... ) const
361 // Make a buffer string
363 va_start( args
, format
);
365 vsnprintf( buffer
, 1024, format
, args
);
369 NLGEORGES::warning (exception
, "(CForm::%s) in form (%s) : %s", function
.c_str(), _Filename
.c_str (), buffer
);
372 // ***************************************************************************
374 void CForm::getDependencies (std::set
<std::string
> &dependencies
) const
377 if (dependencies
.insert (toLowerAscii(CFile::getFilename (_Filename
))).second
)
381 for (i
=0; i
<ParentList
.size (); i
++)
383 if (ParentList
[i
].Parent
)
385 ParentList
[i
].Parent
->getDependencies (dependencies
);
390 Elements
.getDependencies (dependencies
);
394 // ***************************************************************************
396 uint
CForm::getNumParent () const
398 return getParentCount();
401 // ***************************************************************************
403 UForm
*CForm::getParentForm (uint parent
) const
405 CForm
*form
= getParent (parent
);
409 // ***************************************************************************