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