-//\r
-// parses xml tree format into internal objects\r
-//\r
-\r
-\r
-#include "plugin.h"\r
-\r
-void Patch_XMLParse(patchMesh_t *pPatch, xmlNodePtr surface)\r
-{\r
- char *str, *content;\r
- int i, j;\r
-\r
- for(xmlNodePtr current = surface->children; current != NULL; current = current->next)\r
- {\r
- if(current->type != XML_ELEMENT_NODE) continue;\r
- if(!strcmp((char *)current->name, "matrix"))\r
- {\r
- str = (char *)xmlGetProp(current, (xmlChar *)"width");\r
- pPatch->width = atoi(str);\r
- xmlFree(str);\r
- str = (char *)xmlGetProp(current, (xmlChar *)"height");\r
- pPatch->height = atoi(str);\r
- xmlFree(str);\r
-\r
- content = Q_StrDup((char *)current->children->content);\r
-\r
- str = strtok(content, " \n\r\t\v\0");\r
- for(i=0; i<pPatch->width; i++)\r
- {\r
- for(j=0; j<pPatch->height; j++)\r
- {\r
- pPatch->ctrl[i][j].xyz[0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- pPatch->ctrl[i][j].xyz[1] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- pPatch->ctrl[i][j].xyz[2] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- pPatch->ctrl[i][j].st[0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- pPatch->ctrl[i][j].st[1] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- }\r
- }\r
-\r
- delete [] content;\r
- }\r
- else if(!strcmp((char *)current->name, "shader")) {\r
- pPatch->pShader = QERApp_Shader_ForName((char*)current->children->content);\r
- pPatch->d_texture = pPatch->pShader->getTexture();\r
- }\r
- }\r
-}\r
-\r
-void Face_XMLParse (face_t *face, xmlNodePtr surface)\r
-{\r
- char *str, *content;\r
- int i, j;\r
-\r
- for(xmlNodePtr current = surface->children; current != NULL; current = current->next)\r
- {\r
- if(current->type != XML_ELEMENT_NODE) continue;\r
- if(!strcmp((char *)current->name, "planepts"))\r
- {\r
- content = Q_StrDup((char *)current->children->content);\r
-\r
- str = strtok(content, " \n\r\t\v\0");\r
- for (i=0 ; i<3 ; i++)\r
- {\r
- for (j=0 ; j<3 ; j++)\r
- {\r
- face->planepts[i][j] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- }\r
- }\r
-\r
- delete [] content;\r
- }\r
- else if(!strcmp((char *)current->name, "texdef"))\r
- {\r
- content = Q_StrDup((char *)current->children->content);\r
- \r
- str = strtok(content, " \n\r\t\v\0");\r
- face->texdef.shift[0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.shift[1] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.rotate = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.scale[0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.scale[1] = atof(str);\r
-\r
- delete [] content;\r
- }\r
- else if(!strcmp((char *)current->name, "bpmatrix"))\r
- {\r
- content = Q_StrDup((char *)current->children->content);\r
- \r
- str = strtok(content, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[0][0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[0][1] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[0][2] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[1][0] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[1][1] = atof(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->brushprimit_texdef.coords[1][2] = atof(str);\r
-\r
- delete [] content;\r
- }\r
- else if(!strcmp((char *)current->name, "flags"))\r
- {\r
- content = Q_StrDup((char *)current->children->content);\r
-\r
- str = strtok(content, " \n\r\t\v\0");\r
- face->texdef.contents = atoi(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.flags = atoi(str);\r
- str = strtok(NULL, " \n\r\t\v\0");\r
- face->texdef.value = atoi(str);\r
-\r
- delete [] content;\r
- }\r
- else if(!strcmp((char *)current->name, "shader"))\r
- {\r
- face->texdef.SetName((char *)current->children->content);\r
- }\r
- }\r
-}\r
-\r
-void Brush_XMLParse (brush_t *pBrush, xmlNodePtr primitive)\r
-{\r
- face_t *f;\r
-\r
- for(xmlNodePtr current = primitive->children; current != NULL; current = current->next)\r
- {\r
- if(current->type != XML_ELEMENT_NODE) continue;\r
- f = pBrush->brush_faces;\r
- pBrush->brush_faces = Face_Alloc();\r
- Face_XMLParse(pBrush->brush_faces, current);\r
- pBrush->brush_faces->next = f;\r
- }\r
-}\r
-\r
-void Entity_XMLParse(entity_t *pEntity, xmlNodePtr entity)\r
-{\r
- brush_t *pBrush;\r
-\r
- for(xmlNodePtr current = entity->children; current != NULL; current = current->next)\r
- {\r
- if(current->type != XML_ELEMENT_NODE) continue;\r
- if(!strcmp((char *)current->name, "epair"))\r
- {\r
- char *key = (char *)xmlGetProp(current, (xmlChar *)"key");\r
- char *value = (char *)xmlGetProp(current, (xmlChar *)"value");\r
- SetKeyValue(pEntity, key, value);\r
- xmlFree(key);\r
- xmlFree(value);\r
- }\r
- else if(strcmp((char *)current->name, "brush") == 0)\r
- {\r
- pBrush = Brush_Alloc();\r
- Brush_XMLParse(pBrush, current);\r
- ((CPtrArray*)pEntity->pData)->Add(pBrush);\r
- }\r
- else if(strcmp((char *)current->name, "patch") == 0)\r
- {\r
- pBrush = Brush_Alloc();\r
- pBrush->patchBrush = true;\r
- pBrush->pPatch = Patch_Alloc();\r
- pBrush->pPatch->pSymbiot = pBrush;\r
- Patch_XMLParse(pBrush->pPatch, current);\r
- ((CPtrArray*)pEntity->pData)->Add(pBrush);\r
- }\r
- }\r
-}\r
-\r
-void Map_XMLRead(CPtrArray *map, xmlNodePtr map_node)\r
-{\r
- entity_t *pEntity;\r
- xmlNodePtr current;\r
-\r
- for(current = map_node->children; current != NULL; current = current->next)\r
- {\r
- if(current->type != XML_ELEMENT_NODE) continue;\r
- pEntity = Entity_Alloc();\r
- pEntity->pData = new CPtrArray;\r
- Entity_XMLParse(pEntity, current);\r
- map->Add(pEntity);\r
- }\r
-}\r
-\r
-// SPoG\r
-// temporarily copied from qe3.cpp\r
-// duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())\r
-\r
-void HandleXMLError( void* ctxt, const char* text, ... )\r
-{\r
- va_list argptr;\r
- static char buf[32768];\r
-\r
- va_start (argptr,text);\r
- vsprintf (buf, text, argptr);\r
- Sys_FPrintf (SYS_ERR, "XML %s\n", buf);\r
- va_end (argptr);\r
-}\r
-\r
-#define DTD_BUFFER_LENGTH 1024\r
-xmlDocPtr ParseXMLStream(IDataStream *stream, bool validate = false)\r
-{\r
- xmlDocPtr doc = NULL;\r
- bool wellFormed = false, valid = false;\r
- int res, size = 1024;\r
- char chars[1024];\r
- xmlParserCtxtPtr ctxt;\r
-\r
- // SPoG\r
- // HACK: use AppPath to resolve DTD location\r
- // do a buffer-safe string copy and concatenate\r
- int i;\r
- char* w;\r
- const char* r;\r
- char buf[DTD_BUFFER_LENGTH];\r
-\r
- w = buf;\r
- i = 0;\r
- // copy\r
- //assert(g_FuncTable.m_pfnGetQERPath() != NULL);\r
- for(r = g_FuncTable.m_pfnGetQERPath(); i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;\r
- // concatenate\r
- for(r = "dtds/"; i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;\r
- // terminate\r
- w[i] = '\0';\r
-\r
- if(i == DTD_BUFFER_LENGTH)\r
- {\r
- HandleXMLError(NULL, "ERROR: buffer overflow: DTD path length too large\n");\r
- return NULL;\r
- }\r
-\r
- //if(validate)\r
- // xmlDoValidityCheckingDefaultValue = 1;\r
- //else\r
- xmlDoValidityCheckingDefaultValue = 0;\r
-\r
- xmlSetGenericErrorFunc(NULL, HandleXMLError);\r
-\r
- res = stream->Read(chars, 4);\r
- if (res > 0)\r
- {\r
- ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, buf);\r
-\r
- while ((res = stream->Read(chars, size)) > 0)\r
- {\r
- xmlParseChunk(ctxt, chars, res, 0);\r
- }\r
- xmlParseChunk(ctxt, chars, 0, 1);\r
- doc = ctxt->myDoc;\r
-\r
- wellFormed = (ctxt->wellFormed == 1);\r
- valid = (ctxt->valid == 1);\r
-\r
- xmlFreeParserCtxt(ctxt);\r
- }\r
-\r
- if(wellFormed && (!validate || (validate && valid)))\r
- return doc;\r
-\r
- if(doc != NULL)\r
- xmlFreeDoc(doc);\r
-\r
- return NULL;\r
-}\r
-\r
-// duplicate code ends here\r
-\r
-void Map_Read (IDataStream *in, CPtrArray *map)\r
-{\r
- xmlDocPtr doc;\r
-\r
- doc = ParseXMLStream(in, false ); // quick hack while dtd validation is broken\r
-\r
- if(doc != NULL)\r
- {\r
- xmlNodePtr node=doc->children;\r
- while(node != NULL && node->type != XML_ELEMENT_NODE) node=node->next;\r
- if(node != NULL)\r
- Map_XMLRead(map, node);\r
- }\r
- \r
- xmlFreeDoc(doc);\r
-}\r
+//
+// parses xml tree format into internal objects
+//
+
+
+#include "plugin.h"
+
+void Patch_XMLParse(patchMesh_t *pPatch, xmlNodePtr surface)
+{
+ char *str, *content;
+ int i, j;
+
+ for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
+ {
+ if(current->type != XML_ELEMENT_NODE) continue;
+ if(!strcmp((char *)current->name, "matrix"))
+ {
+ str = (char *)xmlGetProp(current, (xmlChar *)"width");
+ pPatch->width = atoi(str);
+ xmlFree(str);
+ str = (char *)xmlGetProp(current, (xmlChar *)"height");
+ pPatch->height = atoi(str);
+ xmlFree(str);
+
+ content = Q_StrDup((char *)current->children->content);
+
+ str = strtok(content, " \n\r\t\v\0");
+ for(i=0; i<pPatch->width; i++)
+ {
+ for(j=0; j<pPatch->height; j++)
+ {
+ pPatch->ctrl[i][j].xyz[0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ pPatch->ctrl[i][j].xyz[1] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ pPatch->ctrl[i][j].xyz[2] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ pPatch->ctrl[i][j].st[0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ pPatch->ctrl[i][j].st[1] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ }
+ }
+
+ delete [] content;
+ }
+ else if(!strcmp((char *)current->name, "shader")) {
+ pPatch->pShader = QERApp_Shader_ForName((char*)current->children->content);
+ pPatch->d_texture = pPatch->pShader->getTexture();
+ }
+ }
+}
+
+void Face_XMLParse (face_t *face, xmlNodePtr surface)
+{
+ char *str, *content;
+ int i, j;
+
+ for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
+ {
+ if(current->type != XML_ELEMENT_NODE) continue;
+ if(!strcmp((char *)current->name, "planepts"))
+ {
+ content = Q_StrDup((char *)current->children->content);
+
+ str = strtok(content, " \n\r\t\v\0");
+ for (i=0 ; i<3 ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ face->planepts[i][j] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ }
+ }
+
+ delete [] content;
+ }
+ else if(!strcmp((char *)current->name, "texdef"))
+ {
+ content = Q_StrDup((char *)current->children->content);
+
+ str = strtok(content, " \n\r\t\v\0");
+ face->texdef.shift[0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.shift[1] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.rotate = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.scale[0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.scale[1] = atof(str);
+
+ delete [] content;
+ }
+ else if(!strcmp((char *)current->name, "bpmatrix"))
+ {
+ content = Q_StrDup((char *)current->children->content);
+
+ str = strtok(content, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[0][0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[0][1] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[0][2] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[1][0] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[1][1] = atof(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->brushprimit_texdef.coords[1][2] = atof(str);
+
+ delete [] content;
+ }
+ else if(!strcmp((char *)current->name, "flags"))
+ {
+ content = Q_StrDup((char *)current->children->content);
+
+ str = strtok(content, " \n\r\t\v\0");
+ face->texdef.contents = atoi(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.flags = atoi(str);
+ str = strtok(NULL, " \n\r\t\v\0");
+ face->texdef.value = atoi(str);
+
+ delete [] content;
+ }
+ else if(!strcmp((char *)current->name, "shader"))
+ {
+ face->texdef.SetName((char *)current->children->content);
+ }
+ }
+}
+
+void Brush_XMLParse (brush_t *pBrush, xmlNodePtr primitive)
+{
+ face_t *f;
+
+ for(xmlNodePtr current = primitive->children; current != NULL; current = current->next)
+ {
+ if(current->type != XML_ELEMENT_NODE) continue;
+ f = pBrush->brush_faces;
+ pBrush->brush_faces = Face_Alloc();
+ Face_XMLParse(pBrush->brush_faces, current);
+ pBrush->brush_faces->next = f;
+ }
+}
+
+void Entity_XMLParse(entity_t *pEntity, xmlNodePtr entity)
+{
+ brush_t *pBrush;
+
+ for(xmlNodePtr current = entity->children; current != NULL; current = current->next)
+ {
+ if(current->type != XML_ELEMENT_NODE) continue;
+ if(!strcmp((char *)current->name, "epair"))
+ {
+ char *key = (char *)xmlGetProp(current, (xmlChar *)"key");
+ char *value = (char *)xmlGetProp(current, (xmlChar *)"value");
+ SetKeyValue(pEntity, key, value);
+ xmlFree(key);
+ xmlFree(value);
+ }
+ else if(strcmp((char *)current->name, "brush") == 0)
+ {
+ pBrush = Brush_Alloc();
+ Brush_XMLParse(pBrush, current);
+ ((CPtrArray*)pEntity->pData)->Add(pBrush);
+ }
+ else if(strcmp((char *)current->name, "patch") == 0)
+ {
+ pBrush = Brush_Alloc();
+ pBrush->patchBrush = true;
+ pBrush->pPatch = Patch_Alloc();
+ pBrush->pPatch->pSymbiot = pBrush;
+ Patch_XMLParse(pBrush->pPatch, current);
+ ((CPtrArray*)pEntity->pData)->Add(pBrush);
+ }
+ }
+}
+
+void Map_XMLRead(CPtrArray *map, xmlNodePtr map_node)
+{
+ entity_t *pEntity;
+ xmlNodePtr current;
+
+ for(current = map_node->children; current != NULL; current = current->next)
+ {
+ if(current->type != XML_ELEMENT_NODE) continue;
+ pEntity = Entity_Alloc();
+ pEntity->pData = new CPtrArray;
+ Entity_XMLParse(pEntity, current);
+ map->Add(pEntity);
+ }
+}
+
+// SPoG
+// temporarily copied from qe3.cpp
+// duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())
+
+void HandleXMLError( void* ctxt, const char* text, ... )
+{
+ va_list argptr;
+ static char buf[32768];
+
+ va_start (argptr,text);
+ vsprintf (buf, text, argptr);
+ Sys_FPrintf (SYS_ERR, "XML %s\n", buf);
+ va_end (argptr);
+}
+
+#define DTD_BUFFER_LENGTH 1024
+xmlDocPtr ParseXMLStream(IDataStream *stream, bool validate = false)
+{
+ xmlDocPtr doc = NULL;
+ bool wellFormed = false, valid = false;
+ int res, size = 1024;
+ char chars[1024];
+ xmlParserCtxtPtr ctxt;
+
+ // SPoG
+ // HACK: use AppPath to resolve DTD location
+ // do a buffer-safe string copy and concatenate
+ int i;
+ char* w;
+ const char* r;
+ char buf[DTD_BUFFER_LENGTH];
+
+ w = buf;
+ i = 0;
+ // copy
+ //assert(g_FuncTable.m_pfnGetQERPath() != NULL);
+ for(r = g_FuncTable.m_pfnGetQERPath(); i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
+ // concatenate
+ for(r = "dtds/"; i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
+ // terminate
+ w[i] = '\0';
+
+ if(i == DTD_BUFFER_LENGTH)
+ {
+ HandleXMLError(NULL, "ERROR: buffer overflow: DTD path length too large\n");
+ return NULL;
+ }
+
+ //if(validate)
+ // xmlDoValidityCheckingDefaultValue = 1;
+ //else
+ xmlDoValidityCheckingDefaultValue = 0;
+
+ xmlSetGenericErrorFunc(NULL, HandleXMLError);
+
+ res = stream->Read(chars, 4);
+ if (res > 0)
+ {
+ ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, buf);
+
+ while ((res = stream->Read(chars, size)) > 0)
+ {
+ xmlParseChunk(ctxt, chars, res, 0);
+ }
+ xmlParseChunk(ctxt, chars, 0, 1);
+ doc = ctxt->myDoc;
+
+ wellFormed = (ctxt->wellFormed == 1);
+ valid = (ctxt->valid == 1);
+
+ xmlFreeParserCtxt(ctxt);
+ }
+
+ if(wellFormed && (!validate || (validate && valid)))
+ return doc;
+
+ if(doc != NULL)
+ xmlFreeDoc(doc);
+
+ return NULL;
+}
+
+// duplicate code ends here
+
+void Map_Read (IDataStream *in, CPtrArray *map)
+{
+ xmlDocPtr doc;
+
+ doc = ParseXMLStream(in, false ); // quick hack while dtd validation is broken
+
+ if(doc != NULL)
+ {
+ xmlNodePtr node=doc->children;
+ while(node != NULL && node->type != XML_ELEMENT_NODE) node=node->next;
+ if(node != NULL)
+ Map_XMLRead(map, node);
+ }
+
+ xmlFreeDoc(doc);
+}