]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/mapxml/xmlparse.cpp
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / mapxml / xmlparse.cpp
1 //
2 // parses xml tree format into internal objects
3 //
4
5
6 #include "plugin.h"
7
8 void Patch_XMLParse( patchMesh_t *pPatch, xmlNodePtr surface ){
9         char *str, *content;
10         int i, j;
11
12         for ( xmlNodePtr current = surface->children; current != NULL; current = current->next )
13         {
14                 if ( current->type != XML_ELEMENT_NODE ) {
15                         continue;
16                 }
17                 if ( !strcmp( (char *)current->name, "matrix" ) ) {
18                         str = (char *)xmlGetProp( current, (xmlChar *)"width" );
19                         pPatch->width = atoi( str );
20                         xmlFree( str );
21                         str = (char *)xmlGetProp( current, (xmlChar *)"height" );
22                         pPatch->height = atoi( str );
23                         xmlFree( str );
24
25                         content = Q_StrDup( (char *)current->children->content );
26
27                         str = strtok( content, " \n\r\t\v\0" );
28                         for ( i = 0; i < pPatch->width; i++ )
29                         {
30                                 for ( j = 0; j < pPatch->height; j++ )
31                                 {
32                                         pPatch->ctrl[i][j].xyz[0] = atof( str );
33                                         str = strtok( NULL, " \n\r\t\v\0" );
34                                         pPatch->ctrl[i][j].xyz[1] = atof( str );
35                                         str = strtok( NULL, " \n\r\t\v\0" );
36                                         pPatch->ctrl[i][j].xyz[2] = atof( str );
37                                         str = strtok( NULL, " \n\r\t\v\0" );
38                                         pPatch->ctrl[i][j].st[0] = atof( str );
39                                         str = strtok( NULL, " \n\r\t\v\0" );
40                                         pPatch->ctrl[i][j].st[1] = atof( str );
41                                         str = strtok( NULL, " \n\r\t\v\0" );
42                                 }
43                         }
44
45                         delete [] content;
46                 }
47                 else if ( !strcmp( (char *)current->name, "shader" ) ) {
48                         pPatch->pShader = QERApp_Shader_ForName( (char*)current->children->content );
49                         pPatch->d_texture = pPatch->pShader->getTexture();
50                 }
51         }
52 }
53
54 void Face_XMLParse( face_t *face, xmlNodePtr surface ){
55         char *str, *content;
56         int i, j;
57
58         for ( xmlNodePtr current = surface->children; current != NULL; current = current->next )
59         {
60                 if ( current->type != XML_ELEMENT_NODE ) {
61                         continue;
62                 }
63                 if ( !strcmp( (char *)current->name, "planepts" ) ) {
64                         content = Q_StrDup( (char *)current->children->content );
65
66                         str = strtok( content, " \n\r\t\v\0" );
67                         for ( i = 0 ; i < 3 ; i++ )
68                         {
69                                 for ( j = 0 ; j < 3 ; j++ )
70                                 {
71                                         face->planepts[i][j] = atof( str );
72                                         str = strtok( NULL, " \n\r\t\v\0" );
73                                 }
74                         }
75
76                         delete [] content;
77                 }
78                 else if ( !strcmp( (char *)current->name, "texdef" ) ) {
79                         content = Q_StrDup( (char *)current->children->content );
80
81                         str = strtok( content, " \n\r\t\v\0" );
82                         face->texdef.shift[0] = atof( str );
83                         str = strtok( NULL, " \n\r\t\v\0" );
84                         face->texdef.shift[1] = atof( str );
85                         str = strtok( NULL, " \n\r\t\v\0" );
86                         face->texdef.rotate = atof( str );
87                         str = strtok( NULL, " \n\r\t\v\0" );
88                         face->texdef.scale[0] = atof( str );
89                         str = strtok( NULL, " \n\r\t\v\0" );
90                         face->texdef.scale[1] = atof( str );
91
92                         delete [] content;
93                 }
94                 else if ( !strcmp( (char *)current->name, "bpmatrix" ) ) {
95                         content = Q_StrDup( (char *)current->children->content );
96
97                         str = strtok( content, " \n\r\t\v\0" );
98                         face->brushprimit_texdef.coords[0][0] = atof( str );
99                         str = strtok( NULL, " \n\r\t\v\0" );
100                         face->brushprimit_texdef.coords[0][1] = atof( str );
101                         str = strtok( NULL, " \n\r\t\v\0" );
102                         face->brushprimit_texdef.coords[0][2] = atof( str );
103                         str = strtok( NULL, " \n\r\t\v\0" );
104                         face->brushprimit_texdef.coords[1][0] = atof( str );
105                         str = strtok( NULL, " \n\r\t\v\0" );
106                         face->brushprimit_texdef.coords[1][1] = atof( str );
107                         str = strtok( NULL, " \n\r\t\v\0" );
108                         face->brushprimit_texdef.coords[1][2] = atof( str );
109
110                         delete [] content;
111                 }
112                 else if ( !strcmp( (char *)current->name, "flags" ) ) {
113                         content = Q_StrDup( (char *)current->children->content );
114
115                         str = strtok( content, " \n\r\t\v\0" );
116                         face->texdef.contents = atoi( str );
117                         str = strtok( NULL, " \n\r\t\v\0" );
118                         face->texdef.flags = atoi( str );
119                         str = strtok( NULL, " \n\r\t\v\0" );
120                         face->texdef.value = atoi( str );
121
122                         delete [] content;
123                 }
124                 else if ( !strcmp( (char *)current->name, "shader" ) ) {
125                         face->texdef.SetName( (char *)current->children->content );
126                 }
127         }
128 }
129
130 void Brush_XMLParse( brush_t *pBrush, xmlNodePtr primitive ){
131         face_t    *f;
132
133         for ( xmlNodePtr current = primitive->children; current != NULL; current = current->next )
134         {
135                 if ( current->type != XML_ELEMENT_NODE ) {
136                         continue;
137                 }
138                 f = pBrush->brush_faces;
139                 pBrush->brush_faces = Face_Alloc();
140                 Face_XMLParse( pBrush->brush_faces, current );
141                 pBrush->brush_faces->next = f;
142         }
143 }
144
145 void Entity_XMLParse( entity_t *pEntity, xmlNodePtr entity ){
146         brush_t *pBrush;
147
148         for ( xmlNodePtr current = entity->children; current != NULL; current = current->next )
149         {
150                 if ( current->type != XML_ELEMENT_NODE ) {
151                         continue;
152                 }
153                 if ( !strcmp( (char *)current->name, "epair" ) ) {
154                         char *key = (char *)xmlGetProp( current, (xmlChar *)"key" );
155                         char *value = (char *)xmlGetProp( current, (xmlChar *)"value" );
156                         SetKeyValue( pEntity, key, value );
157                         xmlFree( key );
158                         xmlFree( value );
159                 }
160                 else if ( strcmp( (char *)current->name, "brush" ) == 0 ) {
161                         pBrush = Brush_Alloc();
162                         Brush_XMLParse( pBrush, current );
163                         ( (CPtrArray*)pEntity->pData )->Add( pBrush );
164                 }
165                 else if ( strcmp( (char *)current->name, "patch" ) == 0 ) {
166                         pBrush = Brush_Alloc();
167                         pBrush->patchBrush = true;
168                         pBrush->pPatch = Patch_Alloc();
169                         pBrush->pPatch->pSymbiot = pBrush;
170                         Patch_XMLParse( pBrush->pPatch, current );
171                         ( (CPtrArray*)pEntity->pData )->Add( pBrush );
172                 }
173         }
174 }
175
176 void Map_XMLRead( CPtrArray *map, xmlNodePtr map_node ){
177         entity_t *pEntity;
178         xmlNodePtr current;
179
180         for ( current = map_node->children; current != NULL; current = current->next )
181         {
182                 if ( current->type != XML_ELEMENT_NODE ) {
183                         continue;
184                 }
185                 pEntity = Entity_Alloc();
186                 pEntity->pData = new CPtrArray;
187                 Entity_XMLParse( pEntity, current );
188                 map->Add( pEntity );
189         }
190 }
191
192 // SPoG
193 // temporarily copied from qe3.cpp
194 // duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())
195
196 void HandleXMLError( void* ctxt, const char* text, ... ){
197         va_list argptr;
198         static char buf[32768];
199
200         va_start( argptr,text );
201         vsprintf( buf, text, argptr );
202         Sys_FPrintf( SYS_ERR, "XML %s\n", buf );
203         va_end( argptr );
204 }
205
206 #define DTD_BUFFER_LENGTH 1024
207 xmlDocPtr ParseXMLStream( IDataStream *stream, bool validate = false ){
208         xmlDocPtr doc = NULL;
209         bool wellFormed = false, valid = false;
210         int res, size = 1024;
211         char chars[1024];
212         xmlParserCtxtPtr ctxt;
213
214         // SPoG
215         // HACK: use AppPath to resolve DTD location
216         // do a buffer-safe string copy and concatenate
217         int i;
218         char* w;
219         const char* r;
220         char buf[DTD_BUFFER_LENGTH];
221
222         w = buf;
223         i = 0;
224         // copy
225         //assert(g_FuncTable.m_pfnGetQERPath() != NULL);
226         for ( r = g_FuncTable.m_pfnGetQERPath(); i < DTD_BUFFER_LENGTH && *r != '\0'; i++, r++ ) w[i] = *r;
227         // concatenate
228         for ( r = "dtds/"; i < DTD_BUFFER_LENGTH && *r != '\0'; i++, r++ ) w[i] = *r;
229         // terminate
230         w[i] = '\0';
231
232         if ( i == DTD_BUFFER_LENGTH ) {
233                 HandleXMLError( NULL, "ERROR: buffer overflow: DTD path length too large\n" );
234                 return NULL;
235         }
236
237         //if(validate)
238         //  xmlDoValidityCheckingDefaultValue = 1;
239         //else
240         xmlDoValidityCheckingDefaultValue = 0;
241
242         xmlSetGenericErrorFunc( NULL, HandleXMLError );
243
244         res = stream->Read( chars, 4 );
245         if ( res > 0 ) {
246                 ctxt = xmlCreatePushParserCtxt( NULL, NULL, chars, res, buf );
247
248                 while ( ( res = stream->Read( chars, size ) ) > 0 )
249                 {
250                         xmlParseChunk( ctxt, chars, res, 0 );
251                 }
252                 xmlParseChunk( ctxt, chars, 0, 1 );
253                 doc = ctxt->myDoc;
254
255                 wellFormed = ( ctxt->wellFormed == 1 );
256                 valid = ( ctxt->valid == 1 );
257
258                 xmlFreeParserCtxt( ctxt );
259         }
260
261         if ( wellFormed && ( !validate || ( validate && valid ) ) ) {
262                 return doc;
263         }
264
265         if ( doc != NULL ) {
266                 xmlFreeDoc( doc );
267         }
268
269         return NULL;
270 }
271
272 // duplicate code ends here
273
274 void Map_Read( IDataStream *in, CPtrArray *map ){
275         xmlDocPtr doc;
276
277         doc = ParseXMLStream( in, false ); // quick hack while dtd validation is broken
278
279         if ( doc != NULL ) {
280                 xmlNodePtr node = doc->children;
281                 while ( node != NULL && node->type != XML_ELEMENT_NODE ) node = node->next;
282                 if ( node != NULL ) {
283                         Map_XMLRead( map, node );
284                 }
285         }
286
287         xmlFreeDoc( doc );
288 }