2 // parses xml tree format into internal objects
8 void Patch_XMLParse( patchMesh_t *pPatch, xmlNodePtr surface ){
12 for ( xmlNodePtr current = surface->children; current != NULL; current = current->next )
14 if ( current->type != XML_ELEMENT_NODE ) {
17 if ( !strcmp( (char *)current->name, "matrix" ) ) {
18 str = (char *)xmlGetProp( current, (xmlChar *)"width" );
19 pPatch->width = atoi( str );
21 str = (char *)xmlGetProp( current, (xmlChar *)"height" );
22 pPatch->height = atoi( str );
25 content = Q_StrDup( (char *)current->children->content );
27 str = strtok( content, " \n\r\t\v\0" );
28 for ( i = 0; i < pPatch->width; i++ )
30 for ( j = 0; j < pPatch->height; j++ )
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" );
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();
54 void Face_XMLParse( face_t *face, xmlNodePtr surface ){
58 for ( xmlNodePtr current = surface->children; current != NULL; current = current->next )
60 if ( current->type != XML_ELEMENT_NODE ) {
63 if ( !strcmp( (char *)current->name, "planepts" ) ) {
64 content = Q_StrDup( (char *)current->children->content );
66 str = strtok( content, " \n\r\t\v\0" );
67 for ( i = 0 ; i < 3 ; i++ )
69 for ( j = 0 ; j < 3 ; j++ )
71 face->planepts[i][j] = atof( str );
72 str = strtok( NULL, " \n\r\t\v\0" );
78 else if ( !strcmp( (char *)current->name, "texdef" ) ) {
79 content = Q_StrDup( (char *)current->children->content );
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 );
94 else if ( !strcmp( (char *)current->name, "bpmatrix" ) ) {
95 content = Q_StrDup( (char *)current->children->content );
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 );
112 else if ( !strcmp( (char *)current->name, "flags" ) ) {
113 content = Q_StrDup( (char *)current->children->content );
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 );
124 else if ( !strcmp( (char *)current->name, "shader" ) ) {
125 face->texdef.SetName( (char *)current->children->content );
130 void Brush_XMLParse( brush_t *pBrush, xmlNodePtr primitive ){
133 for ( xmlNodePtr current = primitive->children; current != NULL; current = current->next )
135 if ( current->type != XML_ELEMENT_NODE ) {
138 f = pBrush->brush_faces;
139 pBrush->brush_faces = Face_Alloc();
140 Face_XMLParse( pBrush->brush_faces, current );
141 pBrush->brush_faces->next = f;
145 void Entity_XMLParse( entity_t *pEntity, xmlNodePtr entity ){
148 for ( xmlNodePtr current = entity->children; current != NULL; current = current->next )
150 if ( current->type != XML_ELEMENT_NODE ) {
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 );
160 else if ( strcmp( (char *)current->name, "brush" ) == 0 ) {
161 pBrush = Brush_Alloc();
162 Brush_XMLParse( pBrush, current );
163 ( (CPtrArray*)pEntity->pData )->Add( pBrush );
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 );
176 void Map_XMLRead( CPtrArray *map, xmlNodePtr map_node ){
180 for ( current = map_node->children; current != NULL; current = current->next )
182 if ( current->type != XML_ELEMENT_NODE ) {
185 pEntity = Entity_Alloc();
186 pEntity->pData = new CPtrArray;
187 Entity_XMLParse( pEntity, current );
193 // temporarily copied from qe3.cpp
194 // duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())
196 void HandleXMLError( void* ctxt, const char* text, ... ){
198 static char buf[32768];
200 va_start( argptr,text );
201 vsprintf( buf, text, argptr );
202 Sys_FPrintf( SYS_ERR, "XML %s\n", buf );
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;
212 xmlParserCtxtPtr ctxt;
215 // HACK: use AppPath to resolve DTD location
216 // do a buffer-safe string copy and concatenate
220 char buf[DTD_BUFFER_LENGTH];
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;
228 for ( r = "dtds/"; i < DTD_BUFFER_LENGTH && *r != '\0'; i++, r++ ) w[i] = *r;
232 if ( i == DTD_BUFFER_LENGTH ) {
233 HandleXMLError( NULL, "ERROR: buffer overflow: DTD path length too large\n" );
238 // xmlDoValidityCheckingDefaultValue = 1;
240 xmlDoValidityCheckingDefaultValue = 0;
242 xmlSetGenericErrorFunc( NULL, HandleXMLError );
244 res = stream->Read( chars, 4 );
246 ctxt = xmlCreatePushParserCtxt( NULL, NULL, chars, res, buf );
248 while ( ( res = stream->Read( chars, size ) ) > 0 )
250 xmlParseChunk( ctxt, chars, res, 0 );
252 xmlParseChunk( ctxt, chars, 0, 1 );
255 wellFormed = ( ctxt->wellFormed == 1 );
256 valid = ( ctxt->valid == 1 );
258 xmlFreeParserCtxt( ctxt );
261 if ( wellFormed && ( !validate || ( validate && valid ) ) ) {
272 // duplicate code ends here
274 void Map_Read( IDataStream *in, CPtrArray *map ){
277 doc = ParseXMLStream( in, false ); // quick hack while dtd validation is broken
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 );