more eol-style
[xonotic/netradiant.git] / radiant / eclass_def.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "cmdlib.h"
23
24 #include "synapse.h"
25 #define USE_QERTABLE_DEFINE
26 #include "qerplugin.h"
27 #define USE_ECLASSMANAGER_DEFINE
28 #include "ieclass.h"
29 #define USE_SCRIPLIBTABLE_DEFINE
30 #include "iscriplib.h"
31
32 #define __VFSTABLENAME g_FileSystemTable_def
33 #define USE_VFSTABLE_DEFINE
34 #include "ifilesystem.h"
35
36
37 #include "eclass_def.h"
38
39 /*! \file eclass_def.cpp
40     \brief .def entity description format
41     implements parsing for .def entity format
42     this is statically linked into the radiant core as we always need it, but really considered
43     as an idependant module by the rest of the core. "ECLASS_MAJOR" "def"
44 */
45
46 _QERScripLibTable g_ScripLibTable;
47 _EClassManagerTable g_EClassManagerTable;
48 _QERFuncTable_1 g_FuncTable;
49 _QERFileSystemTable g_FileSystemTable_def;
50
51 CSynapseBuiltinClientDef eclass_def;
52
53 // forward declare, I'm cheap
54 void Eclass_ScanFile (char *filename);
55
56 const char* EClass_GetExtension()
57 {
58   return "def";
59 }
60
61 void CSynapseBuiltinClientDef::EnumerateInterfaces(CSynapseServer *server)
62 {
63   AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(g_ScripLibTable), SYN_REQUIRE, &g_ScripLibTable);
64   AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
65   AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(g_EClassManagerTable), SYN_REQUIRE, &g_EClassManagerTable);
66   // hardcode the minor for now, we can still add it to the synapse.config at some point
67   AddAPI(VFS_MAJOR, "pk3", sizeof(g_FileSystemTable_def), SYN_REQUIRE, &g_FileSystemTable_def);
68   
69   AddAPI(ECLASS_MAJOR, "def", sizeof(_EClassTable));
70 }
71
72 bool CSynapseBuiltinClientDef::RequestAPI(APIDescriptor_t *pAPI)
73 {
74   if (!strcmp(pAPI->major_name, ECLASS_MAJOR))
75   {
76     _EClassTable* pTable= static_cast<_EClassTable*>(pAPI->mpTable);
77     pTable->m_pfnScanFile = &Eclass_ScanFile;
78     pTable->m_pfnGetExtension = &EClass_GetExtension;
79     
80     return true;    
81   }
82   
83   Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
84   return false;
85 }
86
87 #include "version.h"
88
89 const char* CSynapseBuiltinClientDef::GetInfo()
90 {
91   return "Builtin .def module built " __DATE__ " " RADIANT_VERSION;
92 }
93
94 // ------------------------------------------------------------------------------------------------
95
96 qboolean eclass_found;
97 char *debugname;
98
99 void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p)
100 {
101   // Hydra: removed some amazingly bad cstring usage, whoever wrote that
102   // needs to be taken out and shot.
103
104   char *pText = NULL;
105   char *where = NULL;
106
107   p = NULL; // incase we don't find what we're looking for.
108   where = strstr(e->comments,pWhat);
109   if (!where)
110     return;
111
112   pText = where + strlen(pWhat);
113   if (*pText == '\"')
114     pText++;
115
116   where = strchr(pText,'\"');
117   if (where)
118   {
119     int len = (where-pText);
120     p = new char[len + 1];
121     strncpy(p,pText,len);
122     p[len]=0; // just to make sure, as most implementations of strncpy don't null terminate
123   }
124   else
125     p = strdup(pText);
126 }
127
128 eclass_t *Eclass_InitFromText (char *text)
129 {
130         char    *t;
131         int             len;
132         int             r, i;
133         char    parms[256], *p;
134         eclass_t        *e;
135         char    color[128];
136
137         e = (eclass_t*)malloc(sizeof(*e));
138         memset (e, 0, sizeof(*e));
139         
140         text += strlen("/*QUAKED ");
141
142   // grab the name
143         text = COM_Parse (text);
144         e->name = (char*)malloc (strlen(Get_COM_Token())+1);
145         strcpy (e->name, Get_COM_Token());
146         debugname = e->name;
147
148   // grab the color, reformat as texture name
149   r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
150   if (r != 3) {
151                 return e;
152   }
153         sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
154         //strcpy (e->texdef.name, color);
155         e->texdef.SetName(color);
156
157         while (*text != ')')
158   {
159     if (!*text) {
160                         return e;
161     }
162                 text++;
163         }
164         text++;
165         
166   // get the size       
167         text = COM_Parse (text);
168         if (Get_COM_Token()[0] == '(')
169         {       // parse the size as two vectors
170                 e->fixedsize = true;
171                 r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
172                         &e->maxs[0], &e->maxs[1], &e->maxs[2]);
173     if (r != 6) {
174                         return e;
175     }
176
177                 for (i=0 ; i<2 ; i++)
178                 {
179                         while (*text != ')')
180                         {
181         if (!*text) {
182                                         return e;
183         }
184                                 text++;
185                         }
186                         text++;
187                 }
188         }
189         
190   // get the flags
191         
192   // copy to the first /n
193         p = parms;
194         while (*text && *text != '\n')
195                 *p++ = *text++;
196         *p = 0;
197         text++;
198         
199   // any remaining words are parm flags
200         p = parms;
201         for (i=0 ; i<MAX_FLAGS ; i++)
202         {
203                 p = COM_Parse (p);
204                 if (!p)
205                         break;
206                 strcpy (e->flagnames[i], Get_COM_Token());
207         } 
208
209   // find the length until close comment
210         for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
211         ;
212         
213   // copy the comment block out
214         len = t-text;
215         e->comments = (char*)malloc (len+1);
216         memcpy (e->comments, text, len);
217 #ifdef _WIN32
218   // the win32 Gtk widgets are expecting text stuff to be in unix format (that is CR only instead of DOS's CR/LF)
219   // we convert on the fly by replacing the LF with a ' ' (yeah I'm cheap)
220         for (i=0 ; i<len ; i++)
221                 if (text[i] == '\r')
222                         e->comments[i] = ' ';
223                 else
224                         e->comments[i] = text[i];
225 #endif
226   e->comments[len] = 0;
227         
228   setSpecialLoad(e, "model=", e->modelpath);
229   setSpecialLoad(e, "skin=", e->skinpath);
230   char *pFrame = NULL;
231   setSpecialLoad(e, "frame=", pFrame);
232   if (pFrame != NULL)
233   {
234     e->nFrame = atoi(pFrame);
235     delete pFrame; //Hydra - Fixed memory leak!
236   }
237
238   if(!e->skinpath)
239           setSpecialLoad(e, "texture=", e->skinpath);
240
241   // setup show flags
242   e->nShowFlags = 0;
243   if (strcmpi(e->name, "light") == 0 || strcmpi(e->name, "dlight") == 0 || strcmpi(e->name, "lightjunior") == 0)
244   {
245     e->nShowFlags |= ECLASS_LIGHT;
246   }
247
248   if (  (strnicmp(e->name, "info_player", strlen("info_player")) == 0)
249       ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0) 
250       ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) 
251       ||(strnicmp(e->name, "misc_teleporter_dest", strlen("misc_teleporter_dest")) == 0) 
252           )
253   {
254     e->nShowFlags |= ECLASS_ANGLE;
255   }
256   if (strcmpi(e->name, "path") == 0)
257   {
258     e->nShowFlags |= ECLASS_PATH;
259   }
260   if (strcmpi(e->name, "misc_model") == 0)
261   {
262     e->nShowFlags |= ECLASS_MISCMODEL;
263   }
264
265
266   return e;
267 }
268
269 void Eclass_ScanFile (char *filename)
270 {
271         int             size;
272         char    *data;
273         eclass_t        *e;
274         int             i;
275         char    temp[1024];
276         
277         QE_ConvertDOSToUnixName( temp, filename );
278         
279         size = vfsLoadFullPathFile(filename, (void**)&data);
280   if (size <= 0)
281   {
282     Sys_FPrintf (SYS_ERR, "Eclass_ScanFile: %s not found\n", filename);
283     return;
284   }
285   Sys_Printf ("ScanFile: %s\n", temp);  
286   eclass_found = false;
287   for (i=0 ; i<size ; i++)
288   {
289     if (!strncmp(data+i, "/*QUAKED",8))
290     {
291       e = Eclass_InitFromText (data+i);
292       if (e)
293         Eclass_InsertAlphabetized (e);
294       else
295         Sys_FPrintf (SYS_ERR, "Error parsing: %s in %s\n",debugname, filename);
296       
297       // single ?
298       *Get_Eclass_E() = e;
299       Set_Eclass_Found(true);
300       if ( Get_Parsing_Single() )
301         break;
302     }
303   }
304     
305   g_free (data);                
306 }