2 // parses xml tree format into internal objects
8 void Patch_XMLParse(patchMesh_t *pPatch, xmlNodePtr surface)
13 for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
15 if(current->type != XML_ELEMENT_NODE) continue;
16 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)
59 for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
61 if(current->type != XML_ELEMENT_NODE) continue;
62 if(!strcmp((char *)current->name, "planepts"))
64 content = Q_StrDup((char *)current->children->content);
66 str = strtok(content, " \n\r\t\v\0");
71 face->planepts[i][j] = atof(str);
72 str = strtok(NULL, " \n\r\t\v\0");
78 else if(!strcmp((char *)current->name, "texdef"))
80 content = Q_StrDup((char *)current->children->content);
82 str = strtok(content, " \n\r\t\v\0");
83 face->texdef.shift[0] = atof(str);
84 str = strtok(NULL, " \n\r\t\v\0");
85 face->texdef.shift[1] = atof(str);
86 str = strtok(NULL, " \n\r\t\v\0");
87 face->texdef.rotate = atof(str);
88 str = strtok(NULL, " \n\r\t\v\0");
89 face->texdef.scale[0] = atof(str);
90 str = strtok(NULL, " \n\r\t\v\0");
91 face->texdef.scale[1] = atof(str);
95 else if(!strcmp((char *)current->name, "bpmatrix"))
97 content = Q_StrDup((char *)current->children->content);
99 str = strtok(content, " \n\r\t\v\0");
100 face->brushprimit_texdef.coords[0][0] = atof(str);
101 str = strtok(NULL, " \n\r\t\v\0");
102 face->brushprimit_texdef.coords[0][1] = atof(str);
103 str = strtok(NULL, " \n\r\t\v\0");
104 face->brushprimit_texdef.coords[0][2] = atof(str);
105 str = strtok(NULL, " \n\r\t\v\0");
106 face->brushprimit_texdef.coords[1][0] = atof(str);
107 str = strtok(NULL, " \n\r\t\v\0");
108 face->brushprimit_texdef.coords[1][1] = atof(str);
109 str = strtok(NULL, " \n\r\t\v\0");
110 face->brushprimit_texdef.coords[1][2] = atof(str);
114 else if(!strcmp((char *)current->name, "flags"))
116 content = Q_StrDup((char *)current->children->content);
118 str = strtok(content, " \n\r\t\v\0");
119 face->texdef.contents = atoi(str);
120 str = strtok(NULL, " \n\r\t\v\0");
121 face->texdef.flags = atoi(str);
122 str = strtok(NULL, " \n\r\t\v\0");
123 face->texdef.value = atoi(str);
127 else if(!strcmp((char *)current->name, "shader"))
129 face->texdef.SetName((char *)current->children->content);
134 void Brush_XMLParse (brush_t *pBrush, xmlNodePtr primitive)
138 for(xmlNodePtr current = primitive->children; current != NULL; current = current->next)
140 if(current->type != XML_ELEMENT_NODE) continue;
141 f = pBrush->brush_faces;
142 pBrush->brush_faces = Face_Alloc();
143 Face_XMLParse(pBrush->brush_faces, current);
144 pBrush->brush_faces->next = f;
148 void Entity_XMLParse(entity_t *pEntity, xmlNodePtr entity)
152 for(xmlNodePtr current = entity->children; current != NULL; current = current->next)
154 if(current->type != XML_ELEMENT_NODE) continue;
155 if(!strcmp((char *)current->name, "epair"))
157 char *key = (char *)xmlGetProp(current, (xmlChar *)"key");
158 char *value = (char *)xmlGetProp(current, (xmlChar *)"value");
159 SetKeyValue(pEntity, key, value);
163 else if(strcmp((char *)current->name, "brush") == 0)
165 pBrush = Brush_Alloc();
166 Brush_XMLParse(pBrush, current);
167 ((CPtrArray*)pEntity->pData)->Add(pBrush);
169 else if(strcmp((char *)current->name, "patch") == 0)
171 pBrush = Brush_Alloc();
172 pBrush->patchBrush = true;
173 pBrush->pPatch = Patch_Alloc();
174 pBrush->pPatch->pSymbiot = pBrush;
175 Patch_XMLParse(pBrush->pPatch, current);
176 ((CPtrArray*)pEntity->pData)->Add(pBrush);
181 void Map_XMLRead(CPtrArray *map, xmlNodePtr map_node)
186 for(current = map_node->children; current != NULL; current = current->next)
188 if(current->type != XML_ELEMENT_NODE) continue;
189 pEntity = Entity_Alloc();
190 pEntity->pData = new CPtrArray;
191 Entity_XMLParse(pEntity, current);
197 // temporarily copied from qe3.cpp
198 // duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())
200 void HandleXMLError( void* ctxt, const char* text, ... )
203 static char buf[32768];
205 va_start (argptr,text);
206 vsprintf (buf, text, argptr);
207 Sys_FPrintf (SYS_ERR, "XML %s\n", buf);
211 #define DTD_BUFFER_LENGTH 1024
212 xmlDocPtr ParseXMLStream(IDataStream *stream, bool validate = false)
214 xmlDocPtr doc = NULL;
215 bool wellFormed = false, valid = false;
216 int res, size = 1024;
218 xmlParserCtxtPtr ctxt;
221 // HACK: use AppPath to resolve DTD location
222 // do a buffer-safe string copy and concatenate
226 char buf[DTD_BUFFER_LENGTH];
231 //assert(g_FuncTable.m_pfnGetQERPath() != NULL);
232 for(r = g_FuncTable.m_pfnGetQERPath(); i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
234 for(r = "dtds/"; i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
238 if(i == DTD_BUFFER_LENGTH)
240 HandleXMLError(NULL, "ERROR: buffer overflow: DTD path length too large\n");
245 // xmlDoValidityCheckingDefaultValue = 1;
247 xmlDoValidityCheckingDefaultValue = 0;
249 xmlSetGenericErrorFunc(NULL, HandleXMLError);
251 res = stream->Read(chars, 4);
254 ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, buf);
256 while ((res = stream->Read(chars, size)) > 0)
258 xmlParseChunk(ctxt, chars, res, 0);
260 xmlParseChunk(ctxt, chars, 0, 1);
263 wellFormed = (ctxt->wellFormed == 1);
264 valid = (ctxt->valid == 1);
266 xmlFreeParserCtxt(ctxt);
269 if(wellFormed && (!validate || (validate && valid)))
278 // duplicate code ends here
280 void Map_Read (IDataStream *in, CPtrArray *map)
284 doc = ParseXMLStream(in, false ); // quick hack while dtd validation is broken
288 xmlNodePtr node=doc->children;
289 while(node != NULL && node->type != XML_ELEMENT_NODE) node=node->next;
291 Map_XMLRead(map, node);