* applied patch by StefanV (from mailinglist) that fixes an error in config.py (broke...
[xonotic/netradiant.git] / radiant / pluginmanager.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 // PlugInManager.cpp: implementation of the CPlugInManager class.
23 //
24 //////////////////////////////////////////////////////////////////////
25
26 #include "stdafx.h"
27 #if defined (__linux__) || defined (__APPLE__)
28   #include <dirent.h>
29   #include <sys/time.h>
30 #endif
31 #ifdef __APPLE__
32   #ifdef __cplusplus
33     extern "C" {
34     #endif
35     #include <dlfcn.h>
36     #ifdef __cplusplus
37     }
38   #endif
39 #endif
40 #ifdef _WIN32
41   #include "objbase.h"
42 #endif
43 #include "pluginmanager.h"
44 #include "plugin.h"
45 #include "missing.h"
46 #include "filters.h"
47
48 #include "version.h"
49
50 CRadiantImageManager g_ImageManager;
51 CRadiantPluginManager g_PluginsManager;
52
53 _QERPlugSurfaceTable g_SurfaceTable;
54 _QERFileSystemTable g_FileSystemTable;
55 _QERShadersTable g_ShadersTable;
56 _QERPlugMapTable g_MapTable;
57 _QERPlugMapTable g_MapTable2;
58 _QEREntityTable g_EntityTable;
59 _EClassTable g_EClassDefTable;
60
61 /*!
62   extending entity class formats
63   this approach only allows a single additional format, but it is enough for now
64 */
65 bool g_bHaveEClassExt = false;
66 _EClassTable g_EClassExtTable;
67
68
69 filetype_t g_pattern_all("all files", "*.*");
70 filetype_t g_pattern_projqe4v2("qe4 v2 project files", "*.qe4");
71 filetype_t g_pattern_projxml("xml project files", "*.proj");
72 filetype_t g_pattern_mapq3("quake3 maps", "*.map");
73 filetype_t g_pattern_mapxml("xml quake3 maps", "*.xmap");
74 filetype_t g_pattern_modelmd3("md3 models", "*.md3");
75 filetype_t g_pattern_modelmdc("mdc models", "*.mdc");
76 filetype_t g_pattern_modelmd2("md2 models", "*.md2");
77 filetype_t g_pattern_modelmdl("mdl models", "*.mdl");
78 //filetype_t g_pattern_modelea3("EA3 models", "*.ea3");
79 filetype_t g_pattern_soundwav("PCM sound files", "*.wav");
80 filetype_t g_pattern_regq3("quake3 region", "*.reg");
81
82 #include <map>
83
84 class RadiantFileTypeRegistry : public IFileTypeRegistry
85 {
86 public:
87   virtual ~RadiantFileTypeRegistry() {}
88   virtual void addType(const char* key, filetype_t type)
89   {
90     m_typelists[key].push_back(type);
91   }
92   virtual void getTypeList(const char* key, IFileTypeList* typelist)
93   {
94     filetype_list_t& list_ref = m_typelists[key];
95     for(unsigned int i=0; i<list_ref.size(); ++i)
96       typelist->addType(list_ref[i].getType());
97   }
98 private:
99   struct filetype_copy_t
100   {
101     inline filetype_copy_t(const filetype_t other)
102       : m_name(other.name), m_pattern(other.pattern)
103     {}
104     inline filetype_t getType() const
105     {
106       return filetype_t(m_name.c_str(), m_pattern.c_str());
107     }
108   private:
109     string_t m_name;
110     string_t m_pattern;
111   };
112   typedef vector<filetype_copy_t> filetype_list_t;
113   map<string_t, filetype_list_t> m_typelists;
114 };
115
116 static RadiantFileTypeRegistry g_patterns;
117
118 IFileTypeRegistry* GetFileTypeRegistry()
119 {
120   return &g_patterns;
121 }
122
123 void InitFileTypes()
124 {
125   //GetFileTypeRegistry()->addType("project", g_pattern_projqe4v2);
126   GetFileTypeRegistry()->addType("project", g_pattern_projxml);
127
128   GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapq3);
129   GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapxml);
130
131   GetFileTypeRegistry()->addType("region", g_pattern_regq3);
132 /*
133   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd3);
134   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd2);
135   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdl);
136   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdc);
137   //GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelea3);
138   */
139
140   GetFileTypeRegistry()->addType("sound", g_pattern_soundwav);
141 }
142
143
144 class CRadiantModelModuleManager : public CSynapseAPIManager
145 {
146   typedef list<APIDescriptor_t*> APIDescriptorList;
147
148   APIDescriptorList mAPIs;
149 public:
150   CRadiantModelModuleManager()
151   {
152     SetMatchAPI(MODEL_MAJOR, "*");
153   }
154   virtual ~CRadiantModelModuleManager()
155   {
156     APIDescriptorList::iterator i;
157     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
158     {
159       delete (_QERPlugModelTable*)(*i)->mpTable;
160       delete *i;
161       *i = NULL;
162     }
163     mAPIs.clear();
164   }
165
166   // CSynapseAPIManager interface -------------------
167   APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
168   {
169     APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
170     pRequireAPI->mpTable = new _QERPlugModelTable;
171     ((_QERPlugModelTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugModelTable);
172     pRequireAPI->mSize = sizeof(_QERPlugModelTable);
173     mAPIs.push_front(pRequireAPI);
174     return pRequireAPI;
175   }
176
177   // Model Manager specific
178   const _QERPlugModelTable* GetModelTable(const char* version)
179   {
180     APIDescriptorList::iterator i;
181     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
182       if(strcmp(version, (*i)->minor_name) == 0)
183         return ((_QERPlugModelTable*)(*i)->mpTable);
184     return NULL;
185   }
186 };
187
188 CRadiantModelModuleManager g_ModelManager;
189
190 /*! One of these exists for each unique model ID in use */
191 class CModelWrapper
192 {
193   friend class CModelManager;
194 public:
195   CModelWrapper (const char *id, const char* version) : refcount(1)
196   {
197     copy(id, version);
198     construct();
199   }
200   void Refresh()
201   {
202     destroy();
203     construct();
204   }
205   ~CModelWrapper ()
206   {
207     destroy();
208   }
209 private:
210   void copy(const char* id, const char* version)
211   {
212     m_id = id;
213     m_version = version;
214   }
215   void construct()
216   {
217     m_model.pRender = NULL;
218     m_model.pSelect = NULL;
219     m_model.pEdit = NULL;
220
221     const _QERPlugModelTable* pTable = g_ModelManager.GetModelTable(m_version.c_str());
222
223     if(pTable != NULL)
224       pTable->m_pfnLoadModel(&m_model, m_id.c_str());
225   }
226   void destroy()
227   {
228     if (m_model.pRender) m_model.pRender->DecRef();
229     if (m_model.pSelect) m_model.pSelect->DecRef();
230     if (m_model.pEdit) m_model.pEdit->DecRef();
231   }
232   string_t m_id;
233   string_t m_version;
234   entity_interfaces_t m_model;
235   int refcount;
236 };
237
238 /*! Creates and tracks CModelWrapper instances.
239 Creates a new instance for each unique ID requested, keeps count of the number of
240 times an ID is being referenced, and destroys any instance that is no longer in use */
241 class CModelManager : public IModelCache
242 {
243 public:
244   CModelManager()
245   {
246     m_ptrs = g_ptr_array_new ();
247   }
248   virtual ~CModelManager()
249   {
250     g_ptr_array_free(m_ptrs, FALSE);
251   }
252
253   virtual void DeleteByID(const char *id, const char* version)
254   {
255     unsigned int i;
256     CModelWrapper *elem;
257     for(i=0; i<m_ptrs->len; i++)
258     {
259       elem = (CModelWrapper*)m_ptrs->pdata[i];
260       if(strcmp(elem->m_version.c_str(), version) == 0
261         && strcmp(elem->m_id.c_str(), id) == 0
262         && --elem->refcount == 0)
263       {
264         g_ptr_array_remove_index_fast(m_ptrs, i);
265         delete elem;
266         return;
267       }
268     }
269   }
270
271   virtual entity_interfaces_t *GetByID(const char *id, const char* version)
272   {
273     unsigned int i;
274     CModelWrapper *elem;
275     for(i=0; i<m_ptrs->len; i++)
276     {
277       elem = (CModelWrapper*)m_ptrs->pdata[i];
278       if(strcmp(elem->m_version.c_str(), version) == 0
279         && strcmp(elem->m_id.c_str(), id) == 0)
280       {
281         elem->refcount++;
282         return &elem->m_model;
283       }
284     }
285
286     elem = new CModelWrapper(id, version);
287     g_ptr_array_add(m_ptrs, elem);
288
289     return &elem->m_model;
290   }
291
292   virtual void RefreshAll()
293   {
294     for(unsigned int i=0; i<m_ptrs->len; ++i)
295       ((CModelWrapper*)m_ptrs->pdata[i])->Refresh();
296   }
297 private:
298   GPtrArray *m_ptrs; // array of CModelWrapper*
299 };
300
301 CModelManager g_model_cache;
302
303 IModelCache* GetModelCache()
304 {
305   return &g_model_cache;
306 }
307
308 // toolbar manager
309 class CRadiantToolbarModuleManager : public CSynapseAPIManager
310 {
311   typedef list<APIDescriptor_t*> APIDescriptorList;
312
313   APIDescriptorList mAPIs;
314 public:
315   CRadiantToolbarModuleManager()
316   {
317     SetMatchAPI(TOOLBAR_MAJOR, "*");
318   }
319   virtual ~CRadiantToolbarModuleManager()
320   {
321     APIDescriptorList::iterator i;
322     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
323     {
324       delete (_QERPlugToolbarTable*)(*i)->mpTable;
325       delete *i;
326       *i = NULL;
327     }
328     mAPIs.clear();
329   }
330
331   // CSynapseAPIManager interface -------------------
332   APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
333   {
334     APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
335     pRequireAPI->mpTable = new _QERPlugToolbarTable;
336     ((_QERPlugToolbarTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugToolbarTable);
337     pRequireAPI->mSize = sizeof(_QERPlugToolbarTable);
338     mAPIs.push_front(pRequireAPI);
339     return pRequireAPI;
340   }
341
342   // Toolbar Manager specific
343   void ConstructToolbar()
344   {
345     APIDescriptorList::iterator i;
346     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
347       AddItem((_QERPlugToolbarTable*)(*i)->mpTable);
348   }
349
350 private:
351
352   void AddItem(_QERPlugToolbarTable* pTable)
353   {
354     const unsigned int count = pTable->m_pfnToolbarButtonCount();
355     for(unsigned int i=0; i<count; ++i)
356     {
357       const IToolbarButton* button = pTable->m_pfnGetToolbarButton(i);
358       g_pParentWnd->AddPlugInToolbarButton(button);
359     }
360   }
361 };
362
363 CRadiantToolbarModuleManager g_ToolbarModuleManager;
364
365
366 /* image manager ---------------------------------------- */
367
368 CRadiantImageManager::~CRadiantImageManager()
369 {
370   list<CImageTableSlot *>::iterator iSlot;
371   for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
372   {
373     delete *iSlot;
374     *iSlot = NULL;
375   }
376 }
377
378 void CImageTableSlot::InitForFillAPITable(APIDescriptor_t *pAPI)
379 {
380   mpAPI = pAPI;
381   mpTable = new _QERPlugImageTable;
382   mpTable->m_nSize = sizeof(_QERPlugImageTable);
383   mpAPI->mSize = sizeof(_QERPlugImageTable);
384   mpAPI->mpTable = mpTable;
385 }
386
387 void CRadiantImageManager::FillAPITable(APIDescriptor_t *pAPI)
388 {
389   CImageTableSlot *pSlot = new CImageTableSlot();
390   pSlot->InitForFillAPITable(pAPI);
391   mSlots.push_front(pSlot);
392 }
393
394 /*!
395   Loads an image by calling the module that handles the extension extracted from the filename
396   \param name The filename to load. If no extension is provided, we walk the list of supported extensions.
397   \param pic The returned image data
398   \param width The returned width of the image
399   \param height The returned height of the image
400 */
401 void CRadiantImageManager::LoadImage(const char *name, byte **pic, int *width, int *height)
402 {
403   const char *ext = NULL;
404   int len;
405
406   // extract extension
407   len = strlen (name);
408   if ((len > 5) && (name[len-4] == '.'))
409     ext = &name[len-3];
410
411   if (ext == NULL)
412   {
413     // if no extension is provided, start walking through the list
414     Str fullname;
415     list<CImageTableSlot *>::iterator iSlot;
416     for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
417     {
418       APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
419       fullname.Format("%s.%s", name, pAPI->minor_name);
420       (*iSlot)->GetTable()->m_pfnLoadImage(fullname.GetBuffer(), pic, width, height);
421       if (*pic)
422         return; // this was the right extension, we loaded
423     }
424     return;
425   }
426
427   // start walking the interfaces
428   list<CImageTableSlot *>::iterator iSlot;
429   for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
430   {
431     APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
432     if (!strcmp(pAPI->minor_name, ext))
433     {
434       (*iSlot)->GetTable()->m_pfnLoadImage(name, pic, width, height);
435       return;
436     }
437   }
438   Sys_FPrintf(SYS_WRN, "WARNING: no image table for extension '%s'\n", ext);
439 }
440
441 void CRadiantImageManager::BeginExtensionsScan()
442 {
443   mExtScanSlot = mSlots.begin();
444 }
445
446 const char* CRadiantImageManager::GetNextExtension()
447 {
448   if (mExtScanSlot != mSlots.end())
449   {
450     char *ext = (*mExtScanSlot)->GetDescriptor()->minor_name;
451     mExtScanSlot++;
452     return ext;
453   }
454   return NULL;
455 }
456
457 /* plugin manager --------------------------------------- */
458 APIDescriptor_t* CRadiantPluginManager::BuildRequireAPI(APIDescriptor_t *pAPI)
459 {
460   CPluginSlot *pSlot = new CPluginSlot(pAPI);
461   mSlots.push_front(pSlot);
462   return pSlot->GetDescriptor();
463 }
464
465 void CRadiantPluginManager::PopulateMenu()
466 {
467   list<CPluginSlot *>::iterator iPlug;
468   for(iPlug=mSlots.begin(); iPlug != mSlots.end(); iPlug++)
469   {
470     g_pParentWnd->AddPlugInMenuItem(*iPlug);
471   }
472 }
473
474 void CSynapseClientRadiant::ImportMap(IDataStream *in, CPtrArray *ents, const char *type)
475 {
476   if (strcmp(type,"map")==0)
477   {
478     g_MapTable.m_pfnMap_Read(in, ents);
479   }
480   else if (strcmp(type,"xmap")==0)
481   {
482     g_MapTable2.m_pfnMap_Read(in, ents);
483   }
484   else
485     Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
486 }
487
488 void CSynapseClientRadiant::ExportMap(CPtrArray *ents, IDataStream *out, const char *type)
489 {
490   if (strcmp(type,"map")==0)
491   {
492     g_MapTable.m_pfnMap_Write(ents, out);
493   }
494   else if (strcmp(type,"xmap")==0)
495   {
496     g_MapTable2.m_pfnMap_Write(ents, out);
497   }
498   else
499     Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
500 }
501
502 CPluginSlot::CPluginSlot(APIDescriptor_t *pAPI)
503 {
504   mpAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
505   mpTable = new _QERPluginTable;
506   mpTable->m_nSize = sizeof(_QERPluginTable);
507   mpAPI->mSize = sizeof(_QERPluginTable);
508   mpAPI->mpTable = mpTable;
509   m_CommandStrings = NULL;
510   m_CommandIDs = NULL;
511   m_bReady = false;
512 }
513
514 CPluginSlot::~CPluginSlot()
515 {
516   delete mpAPI;
517   delete mpTable;
518   while (m_CommandStrings)
519   {
520     ::free (m_CommandStrings->data);
521     m_CommandStrings = g_slist_remove (m_CommandStrings, m_CommandStrings->data);
522   }
523 }
524
525 void CPluginSlot::Init()
526 {
527   CString str =   mpTable->m_pfnQERPlug_GetCommandList();
528   char cTemp[1024];
529   strcpy(cTemp, str);
530   char* token = strtok(cTemp, ",;");
531   if (token && *token == ' ')
532   {
533     while (*token == ' ')
534     token++;
535   }
536   while (token != NULL)
537   {
538     m_CommandStrings = g_slist_append (m_CommandStrings, strdup (token));
539     token = strtok(NULL, ",;");
540   }
541   mpTable->m_pfnQERPlug_Init(NULL, (void*)g_pParentWnd->m_pWidget);
542   m_bReady = true;
543 }
544
545 const char* CPluginSlot::getMenuName()
546 {
547   return mpAPI->minor_name;
548 }
549
550 int CPluginSlot::getCommandCount()
551 {
552   if (!m_bReady)
553     Init();
554   return g_slist_length (m_CommandStrings);
555 }
556
557 const char* CPluginSlot::getCommand(int n)
558 {
559   if (!m_bReady)
560     Init();
561   return (char*)g_slist_nth_data (m_CommandStrings, n);
562 }
563
564 void CPluginSlot::addMenuID(int n)
565 {
566   m_CommandIDs = g_slist_append (m_CommandIDs, GINT_TO_POINTER (n));
567 }
568
569 bool CPluginSlot::ownsCommandID(int n)
570 {
571   GSList* lst;
572
573   for (lst = m_CommandIDs; lst != NULL; lst = g_slist_next (lst))
574   {
575     if (GPOINTER_TO_INT (lst->data) == n)
576       return true;
577   }
578   return false;
579 }
580
581 void CPluginSlot::Dispatch(const char *p)
582 {
583   vec3_t vMin, vMax;
584   if (selected_brushes.next == &selected_brushes)
585   {
586     vMin[0] = vMin[1] = vMin[2] = 0;
587     VectorCopy(vMin, vMax);
588   } else
589   {
590     Select_GetBounds (vMin, vMax);
591   }
592   mpTable->m_pfnQERPlug_Dispatch(p, vMin, vMax, QE_SingleBrush(true));
593 }
594
595 CRadiantPluginManager::~CRadiantPluginManager()
596 {
597   list<CPluginSlot *>::iterator iSlot;
598   for(iSlot=mSlots.begin(); iSlot!=mSlots.end(); iSlot++)
599   {
600     delete *iSlot;
601     *iSlot = NULL;
602   }
603 }
604
605 bool CRadiantPluginManager::Dispatch(int n, const char* p)
606 {
607   list<CPluginSlot *>::iterator iPlug;
608   for(iPlug=mSlots.begin(); iPlug!=mSlots.end(); iPlug++)
609   {
610     CPluginSlot *pPlug = *iPlug;
611     if (pPlug->ownsCommandID(n))
612     {
613       pPlug->Dispatch(p);
614       return true;
615     }
616   }
617   return false;
618 }
619
620 //////////////////////////////////////////////////////////////////////
621 // Construction/Destruction
622 //////////////////////////////////////////////////////////////////////
623
624 CPlugInManager::CPlugInManager()
625 {
626   PatchesMode = EActivePatches;
627   m_PlugIns = NULL;
628 }
629
630 CPlugInManager::~CPlugInManager()
631 {
632   Cleanup();
633 }
634
635 void CPlugInManager::InitForDir(const Str &dir)
636 {
637   Str path;
638
639   path = dir;
640   path += g_strPluginsDir;
641   // SYNAPSE
642   g_pParentWnd->GetSynapseServer().AddSearchPath(path);
643
644   if (strcmp(g_strPluginsDir.GetBuffer(), g_strModulesDir.GetBuffer()) != 0)
645   {
646     path = dir;
647     path += g_strModulesDir;
648     // SYNAPSE
649     g_pParentWnd->GetSynapseServer().AddSearchPath(path);
650   }
651 }
652
653 static const XMLConfigEntry_t manager_entries[] =
654   {
655     { VFS_MAJOR,            SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },
656     { SHADERS_MAJOR,        SYN_REQUIRE, sizeof(g_ShadersTable),    &g_ShadersTable },
657     { MAP_MAJOR,            SYN_REQUIRE, sizeof(g_MapTable),        &g_MapTable },
658     { ECLASS_MAJOR,         SYN_REQUIRE, sizeof(g_EClassDefTable),  &g_EClassDefTable },
659     { SURFACEDIALOG_MAJOR,  SYN_REQUIRE, sizeof(g_SurfaceTable),    &g_SurfaceTable },
660     { NULL, SYN_UNKNOWN, 0, NULL } };
661
662 void CPlugInManager::Init()
663 {
664   Str synapse_config;
665
666   Cleanup();
667
668   // set some globals
669   g_qeglobals.bBSPFrontendPlugin = false;
670
671   InitForDir(g_strGameToolsPath);
672   InitForDir(g_strAppPath);
673
674   synapse_config = g_strGameToolsPath;
675   synapse_config += "synapse.config";
676   if (!g_pParentWnd->GetSynapseServer().Initialize(synapse_config.GetBuffer(), &Sys_Printf_VA))
677     Error("Synpase server initialization failed (see console)\n");
678
679   // builtin modules
680   g_pParentWnd->GetSynapseServer().EnumerateBuiltinModule(&eclass_def);
681
682   // APIs we provide
683   g_pParentWnd->GetSynapseClient().AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1));
684   g_pParentWnd->GetSynapseClient().AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(_QERScripLibTable));
685   g_pParentWnd->GetSynapseClient().AddAPI(BRUSH_MAJOR, NULL, sizeof(_QERBrushTable));
686   g_pParentWnd->GetSynapseClient().AddAPI(APPSHADERS_MAJOR, NULL, sizeof(_QERAppShadersTable));
687   g_pParentWnd->GetSynapseClient().AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable));
688   g_pParentWnd->GetSynapseClient().AddAPI(DATA_MAJOR, NULL, sizeof(_QERAppDataTable));
689   g_pParentWnd->GetSynapseClient().AddAPI(PATCH_MAJOR, NULL, sizeof(_QERPatchTable));
690   g_pParentWnd->GetSynapseClient().AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(_EClassManagerTable));
691   g_pParentWnd->GetSynapseClient().AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(_QERSelectedFaceTable));
692   g_pParentWnd->GetSynapseClient().AddAPI(APPSURFACEDIALOG_MAJOR, NULL, sizeof(_QERAppSurfaceTable));
693   g_pParentWnd->GetSynapseClient().AddAPI(UNDO_MAJOR, NULL, sizeof(_QERUndoTable));
694   g_pParentWnd->GetSynapseClient().AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable));
695   g_pParentWnd->GetSynapseClient().AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable));
696   g_pParentWnd->GetSynapseClient().AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable));
697
698   // modules configured by XML
699   if ( !g_pParentWnd->GetSynapseClient().ConfigXML( &g_pParentWnd->GetSynapseServer(), "core", manager_entries ) ) {
700     Error("Synapse server initialization failed (see console)\n");
701   }
702
703   // adding a manager is a special case that ConfigXML doesn't take care of
704   g_pParentWnd->GetSynapseServer().SelectClientConfig( "core" );
705   char *minor;
706   if ( !g_pParentWnd->GetSynapseServer().GetConfigForAPI( IMAGE_MAJOR, &minor ) ) {
707     Syn_Printf( "GetConfigForAPI '%s' failed - invalid XML config file?\n", IMAGE_MAJOR );
708     Error("Synapse server initialization failed (see console)\n");
709   }
710   g_ImageManager.SetMatchAPI( IMAGE_MAJOR, minor );
711   g_pParentWnd->GetSynapseClient().AddManager( &g_ImageManager );
712
713   // SYN_REQUIRE entries which are still hardcoded
714   g_pParentWnd->GetSynapseClient().AddAPI(MAP_MAJOR, "mapxml", sizeof(g_MapTable2), SYN_REQUIRE, &g_MapTable2);
715   g_pParentWnd->GetSynapseClient().AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);
716
717   // plugins: load anything that claims to be a plugin
718   // minor becomes some kind of matching pattern
719   // g_PluginsManager is an API any class, it receives several function tables as needed
720   // you can't do a SYN_PROVIDE with that, has to be a SYN_REQUIRE ?
721   g_PluginsManager.SetMatchAPI(PLUGIN_MAJOR, "*");
722   g_pParentWnd->GetSynapseClient().AddManager(&g_PluginsManager);
723   g_pParentWnd->GetSynapseClient().AddManager(&g_ToolbarModuleManager);
724   g_pParentWnd->GetSynapseClient().AddManager(&g_ModelManager);
725   if (!g_pParentWnd->GetSynapseServer().Resolve(&g_pParentWnd->GetSynapseClient()))
726   {
727     Error("synapse initialization fail (see console)");
728   }
729   g_PluginsManager.PopulateMenu();
730   g_ToolbarModuleManager.ConstructToolbar();
731   InitFileTypes();
732 }
733
734 void CPlugInManager::Shutdown()
735 {
736   g_pParentWnd->GetSynapseServer().Shutdown();
737 }
738
739 void CPlugInManager::Cleanup()
740 {
741   int i;
742
743   for (i = 0; i < m_BrushHandles.GetSize(); i++)
744   {
745     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
746     Brush_Free(pb);
747   }
748   m_BrushHandles.RemoveAll();
749
750   for (i = 0; i < m_EntityHandles.GetSize(); i++)
751   {
752     entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
753     Entity_Free(pe);
754   }
755   m_EntityHandles.RemoveAll();
756
757   // patches
758   // these are linked into the map
759   m_PatchesHandles.RemoveAll();
760   // these patches were allocated by Radiant on plugin request
761   // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
762   // in which case we are supposed to delete them
763   // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
764   // erased and we are trying a second time, therefore crashing ..
765   //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
766 #ifdef _DEBUG
767   if (m_PluginPatches.GetSize() != 0)
768     Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
769 #endif
770
771 /*      for (i = 0; i < m_PluginPatches.GetSize(); i++)
772   {
773     patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
774     if (pMesh->pSymbiot)
775       delete pMesh;
776   }
777   m_PluginPatches.RemoveAll(); */
778 }
779
780 void CPlugInManager::Dispatch(int n, const char * p)
781 {
782   g_PluginsManager.Dispatch(n, p);
783 }
784
785 void WINAPI QERApp_GetDispatchParams(vec3_t vMin, vec3_t vMax, bool *bSingleBrush)
786 {
787   if (selected_brushes.next == &selected_brushes)
788   {
789     vMin[0] = vMin[1] = vMin[2] = 0;
790     VectorCopy(vMin, vMax);
791   } else
792   {
793     Select_GetBounds (vMin, vMax);
794   }
795
796   if( bSingleBrush )
797     *bSingleBrush = QE_SingleBrush(true);
798 }
799
800
801 // creates a dummy brush in the active brushes list
802 // FIXME : is this one really USED ?
803 void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
804 {
805
806   brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
807   Entity_LinkBrush (world_entity, pBrush);
808   Brush_Build(pBrush);
809   Brush_AddToList (pBrush, &active_brushes);
810   Select_Brush(pBrush);
811   Sys_UpdateWindows(W_ALL);
812 }
813
814 void* CPlugInManager::CreateBrushHandle()
815 {
816   brush_t *pb = Brush_Alloc();
817   pb->numberId = g_nBrushId++;
818   m_BrushHandles.Add(pb);
819   return(void*)pb;
820 }
821
822 void CPlugInManager::DeleteBrushHandle(void * vp)
823 {
824   CPtrArray* pHandles[3];
825   pHandles[0] = &m_SelectedBrushHandles;
826   pHandles[1] = &m_ActiveBrushHandles;
827   pHandles[2] = &m_BrushHandles;
828
829   for (int j = 0; j < 3; j++)
830   {
831     for (int i = 0; i < pHandles[j]->GetSize(); i++)
832     {
833       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
834       if (pb == reinterpret_cast<brush_t*>(vp))
835       {
836         if (j == 2)
837         {
838           // only remove it from the list if it is work area
839           // this allows the selected and active list indexes to remain constant
840           // throughout a session (i.e. between an allocate and release)
841           pHandles[j]->RemoveAt(i);
842         }
843         Brush_Free(pb);
844         Sys_MarkMapModified();    // PGM
845         return;
846       }
847     }
848   }
849 }
850
851 void CPlugInManager::CommitBrushHandleToMap(void * vp)
852 {
853   g_bScreenUpdates = false;
854   for (int i = 0; i < m_BrushHandles.GetSize(); i++)
855   {
856     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
857     if (pb == reinterpret_cast<brush_t*>(vp))
858     {
859       m_BrushHandles.RemoveAt(i);
860       Entity_LinkBrush (world_entity, pb);
861       Brush_Build(pb);
862       Brush_AddToList (pb, &active_brushes);
863       Select_Brush(pb);
864     }
865   }
866   g_bScreenUpdates = true;
867   Sys_UpdateWindows(W_ALL);
868 }
869
870 void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
871 {
872   brush_t *bp = FindBrushHandle(vp);
873   if (bp != NULL)
874   {
875     face_t *f = Face_Alloc();
876     f->texdef = g_qeglobals.d_texturewin.texdef;
877     f->texdef.flags &= ~SURF_KEEP;
878     f->texdef.contents &= ~CONTENTS_KEEP;
879     f->next = bp->brush_faces;
880     bp->brush_faces = f;
881     VectorCopy (v1, f->planepts[0]);
882     VectorCopy (v2, f->planepts[1]);
883     VectorCopy (v3, f->planepts[2]);
884   }
885 }
886
887 brush_t* CPlugInManager::FindBrushHandle(void * vp)
888 {
889   CPtrArray* pHandles[4];
890   pHandles[0] = &m_SelectedBrushHandles;
891   pHandles[1] = &m_ActiveBrushHandles;
892   pHandles[2] = &m_BrushHandles;
893   pHandles[3] = &m_EntityBrushHandles;
894
895   for (int j = 0; j < 4; j++)
896   {
897     for (int i = 0; i < pHandles[j]->GetSize(); i++)
898     {
899       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
900       if (pb == reinterpret_cast<brush_t*>(vp))
901       {
902         return pb;
903       }
904     }
905   }
906   return NULL;
907 }
908
909 patchMesh_t* CPlugInManager::FindPatchHandle(int index)
910 {
911   switch (PatchesMode)
912   {
913   case EActivePatches:
914   case ESelectedPatches:
915     if ( index < m_PatchesHandles.GetSize() )
916     {
917       brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
918       return pb->pPatch;
919     }
920 #ifdef _DEBUG
921     Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
922 #endif
923     break;
924   case EAllocatedPatches:
925     if ( index < m_PluginPatches.GetSize() )
926     {
927       patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
928       return pPatch;
929     }
930 #ifdef _DEBUG
931     Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
932 #endif
933     break;
934   }
935   return NULL;
936 }
937
938 void* WINAPI QERApp_CreateBrushHandle()
939 {
940   return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
941 }
942
943 void WINAPI QERApp_DeleteBrushHandle(void* vp)
944 {
945   g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
946 }
947
948 void WINAPI QERApp_CommitBrushHandleToMap(void* vp)
949 {
950   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
951 }
952
953 void WINAPI QERApp_AddFace(void* vp, vec3_t v1, vec3_t v2, vec3_t v3)
954 {
955   g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
956 }
957
958 void WINAPI QERApp_DeleteSelection()
959 {
960   Select_Delete();
961 }
962
963 void QERApp_GetCamera( vec3_t origin, vec3_t angles )
964 {
965   VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->origin, origin );
966   VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->angles, angles );
967 }
968
969 void QERApp_SetCamera( vec3_t origin, vec3_t angles )
970 {
971   VectorCopy( origin, g_pParentWnd->GetCamWnd()->Camera()->origin );
972   VectorCopy( angles, g_pParentWnd->GetCamWnd()->Camera()->angles );
973
974   Sys_UpdateWindows( W_ALL ); // specify
975   g_pParentWnd->OnTimer();
976 }
977
978 void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )
979 {
980   GtkWidget *widget;
981
982   if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
983     widget = g_pParentWnd->GetCamWnd()->m_pParent;
984   else
985     widget = g_pParentWnd->GetCamWnd()->GetWidget();
986
987   get_window_pos (widget, x, y);
988
989   *width = g_pParentWnd->GetCamWnd()->Camera()->width;
990   *height = g_pParentWnd->GetCamWnd()->Camera()->height;
991 }
992
993 //FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
994 bool g_bPlugWait = false;
995 bool g_bPlugOK = false;
996 int  g_nPlugCount = 0;
997
998 void _PlugDone(bool b, int n)
999 {
1000   g_bPlugWait = false;
1001   g_bPlugOK = b;
1002   g_nPlugCount = n;
1003 }
1004
1005 void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, char* pMsg)
1006 {
1007   ShowInfoDialog(pMsg);
1008   g_bPlugWait = true;
1009   g_bPlugOK = false;
1010   g_nPlugCount = 0;
1011 //  g_nPlugCount=nMax-1;
1012   AcquirePath(nMax, &_PlugDone);
1013
1014   while (g_bPlugWait)
1015     gtk_main_iteration ();
1016
1017   HideInfoDialog();
1018
1019   pData->m_nCount = 0;
1020   pData->m_pVectors = NULL;
1021
1022   if (g_bPlugOK && g_nPlugCount > 0)
1023   {
1024     pData->m_nCount = g_nPlugCount;
1025     pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
1026     vec3_t *pOut = pData->m_pVectors;
1027     for (int i = 0; i < g_nPlugCount; i++)
1028     {
1029       memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
1030       pOut++;
1031     }
1032   }
1033 }
1034
1035 //#define DBG_PAPI
1036
1037 void CheckTexture(face_t *f)
1038 {
1039   if (!f->d_texture)
1040   {
1041 #ifdef DBG_PAPI
1042     Sys_Printf("CheckTexture: requesting %s\n", f->texdef.name);
1043 #endif
1044     f->pShader = QERApp_Shader_ForName (f->texdef.GetName());
1045     f->pShader->IncRef();
1046     f->d_texture = f->pShader->getTexture();
1047   }
1048 }
1049
1050 // expects pData->m_TextureName to be relative to "textures/"
1051 void WINAPI QERApp_AddFaceData(void* pv, _QERFaceData *pData)
1052 {
1053 #ifdef DBG_PAPI
1054   Sys_Printf("FindBrushHandle...");
1055 #endif
1056   brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1057 #ifdef DBG_PAPI
1058   Sys_Printf("Done\n");
1059 #endif
1060   if (pBrush != NULL)
1061   {
1062     face_t *f = Face_Alloc();
1063     f->texdef = g_qeglobals.d_texturewin.texdef;
1064     f->texdef.flags = pData->m_nFlags;
1065     f->texdef.contents = pData->m_nContents;
1066     f->texdef.value = pData->m_nValue;
1067     f->texdef.SetName(pData->m_TextureName);
1068     f->next = pBrush->brush_faces;
1069     pBrush->brush_faces = f;
1070     VectorCopy (pData->m_v1, f->planepts[0]);
1071     VectorCopy (pData->m_v2, f->planepts[1]);
1072     VectorCopy (pData->m_v3, f->planepts[2]);
1073     // we might need to convert one way or the other if the input and the brush coordinates setting don't match
1074     if (pData->m_bBPrimit == true)
1075     {
1076       f->brushprimit_texdef = pData->brushprimit_texdef;
1077       if (!g_qeglobals.m_bBrushPrimitMode)
1078       {
1079         // before calling into the conversion, make sure we have a texture!
1080         CheckTexture (f);
1081 #ifdef DBG_PAPI
1082         Sys_Printf("BrushPrimitFaceToFace...");
1083 #endif
1084
1085         // convert BP to regular
1086         BrushPrimitFaceToFace (f);
1087 #ifdef DBG_PAPI
1088         Sys_Printf("Done\n");
1089 #endif
1090       }
1091     } else
1092     {
1093 #ifdef _DEBUG
1094       if (pData->m_bBPrimit != false)
1095         Sys_FPrintf (SYS_WRN, "non-initialized pData->m_bBPrimit in QERApp_AddFaceData\n");
1096 #endif
1097       f->texdef.rotate = pData->m_fRotate;
1098       f->texdef.shift[0] = pData->m_fShift[0];
1099       f->texdef.shift[1] = pData->m_fShift[1];
1100       f->texdef.scale[0] = pData->m_fScale[0];
1101       f->texdef.scale[1] = pData->m_fScale[1];
1102       if (g_qeglobals.m_bBrushPrimitMode)
1103       {
1104         CheckTexture (f);
1105 #ifdef DBG_PAPI
1106         Sys_Printf("FaceToBrushPrimitFace...");
1107 #endif
1108
1109         // convert regular to BP
1110         FaceToBrushPrimitFace (f);
1111 #ifdef DBG_PAPI
1112         Sys_Printf("Done\n");
1113 #endif
1114       }
1115     }
1116     Sys_MarkMapModified();    // PGM
1117   }
1118 }
1119
1120 int WINAPI QERApp_GetFaceCount(void* pv)
1121 {
1122   int n = 0;
1123   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1124   if (pBrush != NULL)
1125   {
1126     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
1127     {
1128       n++;
1129     }
1130   }
1131   return n;
1132 }
1133
1134 _QERFaceData* WINAPI QERApp_GetFaceData(void* pv, int nFaceIndex)
1135 {
1136   static _QERFaceData face;
1137   int n = 0;
1138   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1139
1140   if (pBrush != NULL)
1141   {
1142     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
1143     {
1144
1145 #ifdef _DEBUG
1146       if (!pBrush->brush_faces)
1147       {
1148         Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
1149         return NULL;
1150       }
1151 #endif
1152
1153       if (n == nFaceIndex)
1154       {
1155         face.m_nContents = f->texdef.contents;
1156         face.m_nFlags = f->texdef.flags;
1157         face.m_nValue = f->texdef.value;
1158         if (g_qeglobals.m_bBrushPrimitMode)
1159         {
1160           //++timo NOTE: we may want to convert back to old format for backward compatibility with some old plugins?
1161           face.m_bBPrimit = true;
1162           face.brushprimit_texdef = f->brushprimit_texdef;
1163         } else
1164         {
1165           face.m_fRotate = f->texdef.rotate;
1166           face.m_fScale[0] = f->texdef.scale[0];
1167           face.m_fScale[1] = f->texdef.scale[1];
1168           face.m_fShift[0] = f->texdef.shift[0];
1169           face.m_fShift[1] = f->texdef.shift[1];
1170         }
1171         strcpy(face.m_TextureName, f->texdef.GetName());
1172         VectorCopy(f->planepts[0], face.m_v1);
1173         VectorCopy(f->planepts[1], face.m_v2);
1174         VectorCopy(f->planepts[2], face.m_v3);
1175         return &face;
1176       }
1177       n++;
1178     }
1179   }
1180   return NULL;
1181 }
1182
1183 void WINAPI QERApp_SetFaceData(void* pv, int nFaceIndex, _QERFaceData *pData)
1184 {
1185   int n = 0;
1186   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1187
1188   if (pBrush != NULL)
1189   {
1190     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
1191     {
1192       if (n == nFaceIndex)
1193       {
1194         f->texdef.flags = pData->m_nFlags;
1195         f->texdef.contents = pData->m_nContents;
1196         f->texdef.value = pData->m_nValue;
1197         f->texdef.rotate = pData->m_fRotate;
1198         f->texdef.shift[0] = pData->m_fShift[0];
1199         f->texdef.shift[1] = pData->m_fShift[1];
1200         f->texdef.scale[0] = pData->m_fScale[0];
1201         f->texdef.scale[1] = pData->m_fScale[1];
1202         //strcpy(f->texdef.name, pData->m_TextureName);
1203         f->texdef.SetName(pData->m_TextureName);
1204         VectorCopy(pData->m_v1, f->planepts[0]);
1205         VectorCopy(pData->m_v2, f->planepts[1]);
1206         VectorCopy(pData->m_v3, f->planepts[2]);
1207         Sys_MarkMapModified();    // PGM
1208         return;           // PGM
1209       }
1210       n++;
1211     }
1212   }
1213 }
1214
1215 void WINAPI QERApp_DeleteFace(void* pv, int nFaceIndex)
1216 {
1217   int n = 0;
1218   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1219   if (pBrush != NULL)
1220   {
1221     face_t *pPrev = pBrush->brush_faces;
1222     for (face_t *f = pBrush->brush_faces; f; f = f->next)
1223     {
1224       if (n == nFaceIndex)
1225       {
1226         pPrev->next = f->next;
1227         Face_Free (f);
1228         Sys_MarkMapModified();    // PGM
1229         return;
1230       }
1231       n++;
1232       pPrev = f;
1233     }
1234   }
1235 }
1236
1237 //==========
1238 //PGM
1239 void WINAPI QERApp_BuildBrush (void* pv)
1240 {
1241   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1242   if (pBrush != NULL)
1243   {
1244     Brush_Build(pBrush);
1245     Sys_UpdateWindows(W_ALL);
1246   }
1247 }
1248
1249 //Timo : another version with bConvert flag
1250 //++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
1251 void WINAPI QERApp_BuildBrush2 (void* pv, int bConvert)
1252 {
1253   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1254   if (pBrush != NULL)
1255   {
1256     Brush_Build( pBrush, true, true, bConvert );
1257     Sys_UpdateWindows(W_ALL);
1258   }
1259 }
1260
1261 void WINAPI QERApp_SelectBrush (void* pv)
1262 {
1263   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1264   if (pBrush != NULL)
1265   {
1266     Select_Brush(pBrush, false);
1267     Sys_UpdateWindows(W_ALL);
1268   }
1269
1270 }
1271
1272 void WINAPI QERApp_DeselectBrush (void* pv)
1273 {
1274   // FIXME - implement this!
1275 }
1276
1277 void WINAPI QERApp_ResetPlugins()
1278 {
1279   g_pParentWnd->OnPluginsRefresh();
1280 }
1281
1282 void WINAPI QERApp_DeselectAllBrushes ()
1283 {
1284   Select_Deselect();
1285   Sys_UpdateWindows(W_ALL);
1286 }
1287 //PGM
1288 //==========
1289
1290 void WINAPI QERApp_TextureBrush(void* pv, char* pName)
1291 {
1292   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
1293   if (pBrush != NULL)
1294   {
1295     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
1296     {
1297       //strcpy(f->texdef.name, pName);
1298       f->texdef.SetName(pName);
1299     }
1300     Sys_MarkMapModified();    // PGM
1301   }
1302 }
1303
1304 int WINAPI QERApp_SelectedBrushCount()
1305 {
1306   int n = 0;
1307   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
1308   {
1309     n++;
1310   }
1311   return n;
1312 }
1313
1314 int WINAPI QERApp_ActiveBrushCount()
1315 {
1316   int n = 0;
1317   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
1318   {
1319     n++;
1320   }
1321   return n;
1322 }
1323
1324 int WINAPI QERApp_AllocateSelectedBrushHandles()
1325 {
1326   int n = 0;
1327   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
1328   {
1329     n++;
1330     g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
1331   }
1332   return n;
1333 }
1334
1335 int WINAPI QERApp_AllocateActiveBrushHandles()
1336 {
1337   int n = 0;
1338   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
1339   {
1340     n++;
1341     g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
1342   }
1343   return n;
1344 }
1345
1346 void WINAPI QERApp_ReleaseSelectedBrushHandles()
1347 {
1348   g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
1349   Sys_UpdateWindows(W_ALL);
1350 }
1351
1352 void WINAPI QERApp_ReleaseActiveBrushHandles()
1353 {
1354   g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
1355   Sys_UpdateWindows(W_ALL);
1356 }
1357
1358 void* WINAPI QERApp_GetActiveBrushHandle(int nIndex)
1359 {
1360   if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
1361   {
1362     return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
1363   }
1364   return NULL;
1365 }
1366
1367 void* WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
1368 {
1369   if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
1370   {
1371     return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
1372   }
1373   return NULL;
1374 }
1375
1376 int WINAPI QERApp_TextureCount()
1377 {
1378   //++timo TODO: replace by QERApp_GetActiveShaderCount and verify
1379   Texture_StartPos ();
1380   int x, y;
1381   int n = 0;
1382   while (1)
1383   {
1384     IShader *pShader = Texture_NextPos (&x, &y);
1385     if (!pShader)
1386       break;
1387     n++;
1388   }
1389   return n;
1390 }
1391
1392 char* WINAPI QERApp_GetTexture(int nIndex)
1393 {
1394   //++timo TODO: replace by QERApp_ActiveShader_ForIndex
1395   // these funcs would end up being provided for backward compatibility
1396   static char name[QER_MAX_NAMELEN];
1397   Texture_StartPos ();
1398   int x, y;
1399   int n = 0;
1400   while (1)
1401   {
1402     IShader *pShader = Texture_NextPos (&x, &y);
1403     if (!pShader)
1404       break;
1405     if (n == nIndex)
1406     {
1407       strcpy(name, pShader->getName());
1408       return name;
1409     }
1410     n++;
1411   }
1412   return NULL;
1413 }
1414
1415 char* WINAPI QERApp_GetCurrentTexture()
1416 {
1417   static char current_tex[1024];
1418   strcpy(current_tex,g_qeglobals.d_texturewin.texdef.GetName());
1419   return current_tex;
1420 }
1421
1422 void WINAPI QERApp_SetCurrentTexture(char* strName)
1423 {
1424   //++timo hu ?? tex is not initialized ?? can be any value ..
1425   texdef_t tex;
1426   //++timo added a brushprimit_texdef ..
1427   // smthg to be done here
1428   brushprimit_texdef_t brushprimit_tex;
1429   //strcpy(tex.name, strName);
1430   tex.SetName(strName);
1431   Texture_SetTexture(&tex,&brushprimit_tex);
1432 }
1433
1434 int WINAPI QERApp_GetEClassCount()
1435 {
1436   int n = 0;
1437   for (eclass_t *e = eclass ; e ; e = e->next)
1438   {
1439     n++;
1440   }
1441   return n;
1442 }
1443
1444 char* WINAPI QERApp_GetEClass(int nIndex)
1445 {
1446   int n = 0;
1447   for (eclass_t *e = eclass ; e ; e = e->next)
1448   {
1449     if (n == nIndex)
1450     {
1451       return e->name;
1452     }
1453   }
1454   return NULL;
1455 }
1456
1457 // v1.70 code
1458 // world_entity holds the worldspawn and is indexed as 0
1459 // other entities are in the entities doubly linked list
1460 // QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
1461 int WINAPI QERApp_GetEntityCount()
1462 {
1463   int n = 1;
1464   for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
1465   {
1466     n++;
1467   }
1468   return n;
1469 }
1470
1471 // We don't store entities in CPtrArray, we need to walk the list
1472 void* WINAPI QERApp_GetEntityHandle(int nIndex)
1473 {
1474   if (nIndex==0)
1475     // looks for the worldspawn
1476     return static_cast<void*>(world_entity);
1477   entity_t *pe = &entities;
1478   int n = 0;
1479   while ( n < nIndex )
1480   {
1481     pe = pe->next;
1482     n++;
1483   }
1484   return static_cast<void*>(pe);
1485 }
1486
1487 epair_t* WINAPI QERApp_AllocateEpair( const char *key, const char *val )
1488 {
1489   epair_t *e = (epair_t*)qmalloc (sizeof(*e));
1490   e->key = (char*)qmalloc(strlen(key)+1);
1491   strcpy (e->key, key);
1492   e->value = (char*)qmalloc(strlen(val)+1);
1493   strcpy (e->value, val);
1494   return e;
1495 }
1496
1497 /*
1498 IEpair* WINAPI QERApp_IEpairForEntityHandle(void *vp)
1499 {
1500   entity_t *pe = static_cast<entity_t *>(vp);
1501   CEpairsWrapper *pEp = new CEpairsWrapper(pe);
1502   pEp->IncRef();
1503   return pEp;
1504 }
1505
1506 IEpair* WINAPI QERApp_IEpairForProjectKeys()
1507 {
1508   CEpairsWrapper *pEp = new CEpairsWrapper(g_qeglobals.d_project_entity);
1509   pEp->IncRef();
1510   return pEp;
1511 }
1512 */
1513
1514 int WINAPI QERApp_AllocateEntityBrushHandles(void* vp)
1515 {
1516   entity_t *pe = static_cast<entity_t *>(vp);
1517   int n = 0;
1518   if (!pe->brushes.onext)
1519     return 0;
1520   g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
1521   for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
1522   {
1523     n++;
1524     g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
1525   }
1526   return n;
1527 }
1528
1529 void WINAPI QERApp_ReleaseEntityBrushHandles()
1530 {
1531   g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
1532 }
1533
1534 void* WINAPI QERApp_GetEntityBrushHandle(int nIndex)
1535 {
1536   if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
1537     return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
1538   return NULL;
1539 }
1540
1541 // FIXME TTimo that entity handles thing sucks .. we should get rid of it ..
1542
1543 void* WINAPI QERApp_CreateEntityHandle()
1544 {
1545   entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
1546   pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
1547   g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<void*>(pe));
1548   return static_cast<void*>(pe);
1549 }
1550
1551 // the vpBrush needs to be in m_BrushHandles
1552 //++timo we don't have allocation nor storage for vpEntity, no checks for this one
1553 void WINAPI QERApp_CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
1554 {
1555   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
1556   return;
1557 }
1558
1559 const char* QERApp_ReadProjectKey(const char* key)
1560 {
1561   return ValueForKey(g_qeglobals.d_project_entity, key);
1562 }
1563
1564 #ifdef USEPLUGINENTITIES
1565
1566 int WINAPI QERApp_ScanFileForEClass(char *filename )
1567 {
1568   // set single class parsing
1569   parsing_single = true;
1570   Eclass_ScanFile(filename);
1571   if (eclass_found)
1572   {
1573     eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
1574     return 1;
1575   }
1576   return 0;
1577 }
1578 #endif // USEPLUGINENTITIES
1579
1580 // the vpBrush needs to be in m_BrushHandles
1581 //++timo add a debug check to see if we found the brush handle
1582 // NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
1583 // links the brush to its entity, everything else is done when commiting the entity to the map
1584 void CPlugInManager::CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
1585 {
1586   brush_t* pb;
1587   entity_t* pe;
1588   for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
1589   {
1590     if (vpBrush == m_BrushHandles.GetAt(i))
1591     {
1592       m_BrushHandles.RemoveAt(i);
1593       pb = reinterpret_cast<brush_t*>(vpBrush);
1594       pe = reinterpret_cast<entity_t *>(vpEntity);
1595       Entity_LinkBrush (pe, pb);
1596     }
1597   }
1598   Sys_UpdateWindows(W_ALL);
1599 }
1600
1601 // the vpEntity must be in m_EntityHandles
1602 void WINAPI QERApp_CommitEntityHandleToMap(void* vpEntity)
1603 {
1604   g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
1605   return;
1606 }
1607
1608 int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
1609 {
1610   int nSize = vfsLoadFile(pLocation, buffer, 0);
1611   return nSize;
1612 }
1613
1614 char * WINAPI QERApp_ExpandReletivePath (char *p)
1615 {
1616   return ExpandReletivePath(p);
1617 }
1618
1619 qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
1620 {
1621   // if the texture is not loaded yet, this call will get it loaded
1622   // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_xxxBase GL context
1623   // the plugin may set the GL context to whatever he likes, but then load would fail
1624   // NOTE: is context switching time-consuming? then maybe the plugin could handle the context
1625   // switch and only add a sanity check in debug mode here
1626   // read current context
1627   gtk_glwidget_make_current (g_qeglobals_gui.d_glBase);
1628
1629   //++timo debugging
1630   Sys_Printf("WARNING: QERApp_Texture_ForName ... don't call that!!\n");
1631   qtexture_t* qtex = QERApp_Texture_ForName2( name );
1632   return qtex;
1633 }
1634
1635 char* QERApp_Token()
1636 {
1637   return token;
1638 }
1639
1640 int QERApp_ScriptLine()
1641 {
1642   return scriptline;
1643 }
1644
1645 // we save the map and return the name .. either .map or .reg to support region compiling
1646 char* QERApp_GetMapName()
1647 {
1648   static char name[PATH_MAX];
1649   SaveWithRegion (name);
1650   return name;
1651 }
1652
1653 void CPlugInManager::CommitEntityHandleToMap(void* vpEntity)
1654 {
1655   entity_t *pe;
1656   eclass_t *e;
1657   brush_t   *b;
1658   vec3_t mins,maxs;
1659   bool has_brushes;
1660   for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
1661   {
1662     if (vpEntity == m_EntityHandles.GetAt(i))
1663     {
1664       m_EntityHandles.RemoveAt(i);
1665       pe = reinterpret_cast<entity_t*>(vpEntity);
1666       // fill additional fields
1667       // straight copy from Entity_Parse
1668       // entity_t::origin
1669       GetVectorForKey (pe, "origin", pe->origin);
1670       // entity_t::eclass
1671       if (pe->brushes.onext == &pe->brushes)
1672         has_brushes = false;
1673       else
1674         has_brushes = true;
1675       e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
1676       pe->eclass = e;
1677       // fixedsize
1678       if (e->fixedsize)
1679       {
1680         if (pe->brushes.onext != &pe->brushes)
1681         {
1682           Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
1683         }
1684         // create a custom brush
1685         VectorAdd(e->mins, pe->origin, mins);
1686         VectorAdd(e->maxs, pe->origin, maxs);
1687 /*
1688         float a = 0;
1689         if (e->nShowFlags & ECLASS_MISCMODEL)
1690         {
1691           char* p = ValueForKey(pe, "model");
1692           if (p != NULL && strlen(p) > 0)
1693           {
1694             vec3_t vMin, vMax;
1695             a = FloatForKey (pe, "angle");
1696             if (GetCachedModel(pe, p, vMin, vMax))
1697             {
1698               // create a custom brush
1699               VectorAdd (pe->md3Class->mins, pe->origin, mins);
1700               VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
1701             }
1702           }
1703         }
1704 */
1705         b = Brush_Create (mins, maxs, &e->texdef);
1706 /*
1707         if (a)
1708         {
1709           vec3_t vAngle;
1710           vAngle[0] = vAngle[1] = 0;
1711           vAngle[2] = a;
1712           Brush_Rotate(b, vAngle, pe->origin, false);
1713         }
1714 */
1715         b->owner = pe;
1716
1717         b->onext = pe->brushes.onext;
1718         b->oprev = &pe->brushes;
1719         pe->brushes.onext->oprev = b;
1720         pe->brushes.onext = b;
1721       } else
1722       { // brush entity
1723         if (pe->brushes.next == &pe->brushes)
1724           Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
1725       }
1726
1727       // add brushes to the active brushes list
1728       // and build them along the way
1729       for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
1730       {
1731         // convert between old brushes and brush primitive
1732         if (g_qeglobals.m_bBrushPrimitMode)
1733         {
1734           // we only filled the shift scale rot fields, needs conversion
1735           Brush_Build( b, true, true, true );
1736         } else
1737         {
1738           // we are using old brushes
1739           Brush_Build( b );
1740         }
1741         b->next = active_brushes.next;
1742         active_brushes.next->prev = b;
1743         b->prev = &active_brushes;
1744         active_brushes.next = b;
1745       }
1746
1747       // handle worldspawn entities
1748       // if worldspawn has no brushes, use the new one
1749       if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
1750       {
1751         if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
1752         {
1753           // worldspawn already has brushes
1754           Sys_Printf ("Commiting worldspawn as func_group\n");
1755           SetKeyValue(pe, "classname", "func_group");
1756           // add the entity to the end of the entity list
1757           pe->next = &entities;
1758           pe->prev = entities.prev;
1759           entities.prev->next = pe;
1760           entities.prev = pe;
1761           g_qeglobals.d_num_entities++;
1762         } else
1763         {
1764           // there's a worldspawn with no brushes, we assume the map is empty
1765           if ( world_entity )
1766           {
1767             Entity_Free( world_entity );
1768             world_entity = pe;
1769           } else
1770             Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
1771         }
1772       } else
1773       {
1774         // add the entity to the end of the entity list
1775         pe->next = &entities;
1776         pe->prev = entities.prev;
1777         entities.prev->next = pe;
1778         entities.prev = pe;
1779         g_qeglobals.d_num_entities++;
1780       }
1781     }
1782   }
1783 }
1784
1785 void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
1786 {
1787   g_bScreenUpdates = bScreenUpdates;
1788 }
1789
1790 texturewin_t* QERApp_QeglobalsTexturewin()
1791 {
1792   return &g_qeglobals.d_texturewin;
1793 }
1794
1795 texdef_t* QERApp_QeglobalsSavedinfo_SIInc()
1796 {
1797   return &g_qeglobals.d_savedinfo.m_SIIncrement;
1798 }
1799
1800 patchMesh_t* QERApp_GetSelectedPatch( )
1801 {
1802   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
1803   {
1804     if (pb->patchBrush)
1805     {
1806       return pb->pPatch;
1807     }
1808   }
1809 #ifdef _DEBUG
1810   Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
1811 #endif
1812   return NULL;
1813 }
1814
1815 const char* WINAPI QERApp_GetGamePath()
1816 {
1817   return g_pGameDescription->mEnginePath.GetBuffer();
1818 }
1819
1820 /*!
1821 \todo the name of this API should prolly be changed
1822 would also need to prompt g_strAppPath / g_strGameToolsPath independently?
1823 */
1824 // SPoG
1825 // changed g_strGameToolsPath to g_strAppPath
1826 const char* WINAPI QERApp_GetQERPath()
1827 {
1828   return g_strAppPath.GetBuffer();
1829 }
1830
1831 const char* WINAPI QERApp_GetGameFile()
1832 {
1833   // FIXME: Arnout: temp solution, need proper 'which game is this' indicator or a different solution for plugins/modules
1834   return g_pGameDescription->mGameFile.GetBuffer();
1835 }
1836
1837 // patches in/out -----------------------------------
1838 int WINAPI QERApp_AllocateActivePatchHandles()
1839 {
1840   return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
1841 }
1842
1843 // Grid Size
1844 float QERApp_QeglobalsGetGridSize()
1845 {
1846   return g_qeglobals.d_gridsize;
1847 }
1848
1849 int CPlugInManager::AllocateActivePatchHandles()
1850 {
1851   int n = 0;
1852   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
1853   {
1854     if (pb->patchBrush)
1855     {
1856       n++;
1857       m_PatchesHandles.Add(pb);
1858     }
1859   }
1860   return n;
1861 }
1862
1863 int WINAPI QERApp_AllocateSelectedPatchHandles()
1864 {
1865   return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
1866 }
1867
1868 int CPlugInManager::AllocateSelectedPatchHandles()
1869 {
1870   int n = 0;
1871   // change mode
1872   PatchesMode = ESelectedPatches;
1873   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
1874   {
1875     if (pb->patchBrush)
1876     {
1877       n++;
1878       m_PatchesHandles.Add(pb);
1879     }
1880   }
1881   return n;
1882 }
1883
1884 void WINAPI QERApp_ReleasePatchHandles()
1885 {
1886   g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
1887 }
1888
1889 patchMesh_t* WINAPI QERApp_GetPatchData(int index)
1890 {
1891   static patchMesh_t patch;
1892   patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
1893   if (pPatch)
1894   {
1895     memcpy( &patch, pPatch, sizeof(patchMesh_t) );
1896     return &patch;
1897   }
1898   return NULL;
1899 }
1900
1901 patchMesh_t* WINAPI QERApp_GetPatchHandle(int index)
1902 {
1903   return g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
1904 }
1905
1906 void WINAPI QERApp_DeletePatch(int index)
1907 {
1908   patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
1909   if (pPatch)
1910   {
1911     brush_t *pb = pPatch->pSymbiot;
1912     Patch_Delete( pPatch );
1913     if (pb)
1914       Brush_Free( pb );
1915   }
1916 #ifdef _DEBUG
1917   Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
1918 #endif
1919 }
1920
1921 int WINAPI QERApp_CreatePatchHandle()
1922 {
1923   return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
1924 }
1925
1926 int CPlugInManager::CreatePatchHandle()
1927 {
1928   // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
1929   patchMesh_t *pPatch = MakeNewPatch();
1930   m_PluginPatches.Add( pPatch );
1931   // change mode
1932   PatchesMode = EAllocatedPatches;
1933   return m_PluginPatches.GetSize()-1;
1934 }
1935
1936 void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
1937 {
1938 #ifdef DBG_PAPI
1939   Sys_Printf ("QERApp_CommitPatchHandleToMap %i..", index);
1940 #endif
1941   g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
1942 #ifdef DBG_PAPI
1943   Sys_Printf ("Done\n");
1944 #endif
1945 }
1946
1947 void WINAPI QERApp_CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void* vpEntity)
1948 {
1949 #ifdef DBG_PAPI
1950   Sys_Printf ("QERApp_CommitPatchHandleToEntity %i..", index);
1951 #endif
1952   g_pParentWnd->GetPlugInMgr().CommitPatchHandleToEntity(index, pMesh, texName, vpEntity);
1953 #ifdef DBG_PAPI
1954   Sys_Printf ("Done\n");
1955 #endif
1956 }
1957
1958 void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
1959 {
1960   if (PatchesMode==EAllocatedPatches)
1961   {
1962     patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
1963     memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
1964     // patch texturing, if none given use current texture
1965     if (texName)
1966       pPatch->pShader = QERApp_Shader_ForName (texName);
1967     else
1968       pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
1969     pPatch->d_texture = pPatch->pShader->getTexture();
1970     pPatch->pShader->IncRef();
1971     g_bScreenUpdates = false;
1972     // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
1973     brush_t *pb = AddBrushForPatch( pPatch, true );
1974     Select_Brush( pb );
1975     g_bScreenUpdates = true;
1976     Sys_UpdateWindows(W_ALL);
1977   } else
1978   {
1979     brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
1980     patchMesh_t *pPatch = pBrush->pPatch;
1981     pPatch->width = pMesh->width;
1982     pPatch->height = pMesh->height;
1983     pPatch->contents = pMesh->contents;
1984     pPatch->flags = pMesh->flags;
1985     pPatch->value = pMesh->value;
1986     pPatch->type = pMesh->type;
1987     memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
1988     pPatch->bDirty = true;
1989   }
1990 }
1991
1992 void CPlugInManager::CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity)
1993 {
1994   entity_t* pe = reinterpret_cast<entity_t *>(vpEntity);
1995
1996   if (PatchesMode==EAllocatedPatches)
1997   {
1998     patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
1999     memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
2000     // patch texturing, if none given use current texture
2001     if (texName)
2002       pPatch->pShader = QERApp_Shader_ForName (texName);
2003     else
2004       pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
2005     pPatch->d_texture = pPatch->pShader->getTexture();
2006     pPatch->pShader->IncRef();
2007     g_bScreenUpdates = false;
2008     brush_t *pb = AddBrushForPatch( pPatch, false );  // false, sp have to do the brush building/entity linking ourself
2009     Brush_AddToList (pb, &active_brushes);
2010     Entity_LinkBrush (pe, pb);
2011     Brush_Build( pb );
2012     g_bScreenUpdates = true;
2013     Sys_UpdateWindows(W_ALL);
2014   } else
2015   {
2016     brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
2017     patchMesh_t *pPatch = pBrush->pPatch;
2018     pPatch->width = pMesh->width;
2019     pPatch->height = pMesh->height;
2020     pPatch->contents = pMesh->contents;
2021     pPatch->flags = pMesh->flags;
2022     pPatch->value = pMesh->value;
2023     pPatch->type = pMesh->type;
2024     memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
2025     pPatch->bDirty = true;
2026   }
2027 }
2028
2029 #if 0
2030
2031 #if defined (__linux__) || defined (__APPLE__)
2032   #include <gdk/gdkx.h>
2033
2034 XVisualInfo* QEX_ChooseVisual (bool zbuffer)
2035 {
2036   int attrlist_z[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0};
2037   int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0};
2038   XVisualInfo *vi;
2039   Display *dpy;
2040
2041   dpy = GDK_DISPLAY();
2042   if (dpy == NULL)
2043     Error ("OpenGL fatal error: Cannot get display.\n");
2044   vi = qglXChooseVisual(dpy, DefaultScreen(dpy), zbuffer ? attrlist_z : attrlist);
2045   if (vi == NULL)
2046     Error ("OpenGL fatal error: glXChooseVisual failed.\n");
2047
2048   return vi;
2049 }
2050 #endif
2051
2052 #endif
2053
2054 /*!
2055 \todo FIXME TTimo broken most likely
2056 actually .. that's not enough, you have to go down for the game pack specific?
2057 */
2058 const char* WINAPI QERApp_ProfileGetDirectory ()
2059 {
2060   return g_strTempPath;
2061 }
2062
2063 GtkWidget* WINAPI QERApp_GetQeGlobalsGLWidget ()
2064 {
2065   return g_qeglobals_gui.d_glBase;
2066 }
2067
2068 qboolean WINAPI BrushPrimitMode ()
2069 {
2070   return g_qeglobals.m_bBrushPrimitMode;
2071 }
2072
2073 brush_t* WINAPI QERApp_ActiveBrushes()
2074 {
2075   return &active_brushes;
2076 }
2077
2078 brush_t* WINAPI QERApp_SelectedBrushes()
2079 {
2080   return &selected_brushes;
2081 }
2082
2083 brush_t* WINAPI QERApp_FilteredBrushes()
2084 {
2085   return &filtered_brushes;
2086 }
2087
2088 CPtrArray* WINAPI QERApp_LstSkinCache()
2089 {
2090   return &g_lstSkinCache;
2091 }
2092
2093 qtexture_t** WINAPI QERApp_QTextures()
2094 {
2095   return &g_qeglobals.d_qtextures;
2096 }
2097
2098 GHashTable* WINAPI QERApp_QTexmap()
2099 {
2100   return g_qeglobals.d_qtexmap;
2101 }
2102
2103 // a simplified version of Texture_SetTexture
2104 void WINAPI QERApp_Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef)
2105 {
2106   Texture_SetTexture (texdef, brushprimit_texdef);
2107 }
2108
2109 void QERApp_LoadImage (const char *name, unsigned char **pic, int *width, int *height)
2110 {
2111   g_ImageManager.LoadImage(name, pic, width, height);
2112 }
2113
2114 unsigned long QERApp_GetTickCount()
2115 {
2116 #ifdef _WIN32
2117         return GetTickCount();
2118 #else
2119   struct timeval      tp;
2120   struct timezone     tzp;
2121   static int          basetime=0;
2122
2123   gettimeofday(&tp, &tzp);
2124   if (!basetime)
2125     basetime = tp.tv_sec;
2126   return (tp.tv_sec-basetime) + tp.tv_usec/1000;
2127 #endif
2128 }
2129
2130 bool CSynapseClientRadiant::RequestAPI(APIDescriptor_t *pAPI)
2131 {
2132   if (!strcmp(pAPI->major_name, RADIANT_MAJOR))
2133   {
2134     _QERFuncTable_1* pTable= static_cast<_QERFuncTable_1*>(pAPI->mpTable);
2135     pTable->m_pfnCreateBrush = &QERApp_CreateBrush;
2136     pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;
2137     pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;
2138     pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;
2139     pTable->m_pfnAddFace = &QERApp_AddFace;
2140     pTable->m_pfnAddFaceData = &QERApp_AddFaceData;
2141     pTable->m_pfnGetFaceData = &QERApp_GetFaceData;
2142     pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;
2143     pTable->m_pfnSetFaceData = &QERApp_SetFaceData;
2144     pTable->m_pfnDeleteFace = &QERApp_DeleteFace;
2145     pTable->m_pfnTextureBrush = &QERApp_TextureBrush;
2146     pTable->m_pfnBuildBrush = &QERApp_BuildBrush;           // PGM
2147     pTable->m_pfnSelectBrush = &QERApp_SelectBrush;         // PGM
2148     pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush;       // PGM
2149     pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes;   // PGM
2150     pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;
2151     pTable->m_pfnGetPoints = &QERApp_GetPoints;
2152     pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;
2153     pTable->m_pfnAllocateSelectedBrushHandles  = &QERApp_AllocateSelectedBrushHandles;
2154     pTable->m_pfnReleaseSelectedBrushHandles  = &QERApp_ReleaseSelectedBrushHandles;
2155     pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;
2156     pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;
2157     pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;
2158     pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;
2159     pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;
2160     pTable->m_pfnTextureCount = &QERApp_TextureCount;
2161     pTable->m_pfnGetTexture = &QERApp_GetTexture;
2162     pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;
2163     pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;
2164     pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;
2165     pTable->m_pfnGetEClass = &QERApp_GetEClass;
2166     pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;
2167     pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;
2168     pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;
2169     pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;
2170     pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;
2171     pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;
2172     pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;
2173     pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;
2174     pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;
2175     pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;
2176     pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;
2177     pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;
2178     pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;
2179         pTable->m_pfnGetDispatchParams = &QERApp_GetDispatchParams;
2180 //    pTable->m_pfnRequestInterface = &QERApp_RequestInterface;
2181     pTable->m_pfnError = &Error;
2182     pTable->m_pfnLoadFile = &QERApp_LoadFile;
2183     pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;
2184     pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;
2185     pTable->m_pfnHasShader = QERApp_HasShader;
2186     pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;
2187     pTable->m_pfnGetGamePath = &QERApp_GetGamePath;
2188     pTable->m_pfnGetQERPath = &QERApp_GetQERPath;
2189     pTable->m_pfnGetGameFile = &QERApp_GetGameFile;
2190     pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;
2191     pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;
2192     pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;
2193     pTable->m_pfnGetPatchData = &QERApp_GetPatchData;
2194     pTable->m_pfnGetPatchHandle = &QERApp_GetPatchHandle;
2195     pTable->m_pfnDeletePatch = &QERApp_DeletePatch;
2196     pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;
2197     pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;
2198     pTable->m_pfnLoadImage = &QERApp_LoadImage;
2199     pTable->m_pfnMessageBox = &gtk_MessageBox;
2200     pTable->m_pfnFileDialog = &file_dialog;
2201     pTable->m_pfnColorDialog = &color_dialog;
2202     pTable->m_pfnDirDialog = &dir_dialog;
2203     pTable->m_pfnLoadBitmap = &load_plugin_bitmap;
2204     pTable->m_pfnProfileGetDirectory = &QERApp_ProfileGetDirectory;
2205     pTable->m_pfnProfileSaveInt = &profile_save_int;
2206     pTable->m_pfnProfileSaveString = &profile_save_string;
2207     pTable->m_pfnProfileLoadInt = &profile_load_int;
2208     pTable->m_pfnProfileLoadString = &profile_load_string;
2209     pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;
2210     pTable->m_pfnSysPrintf = &Sys_Printf;
2211     pTable->m_pfnSysFPrintf = &Sys_FPrintf;
2212     pTable->m_pfnSysBeginWait = &Sys_BeginWait;
2213     pTable->m_pfnSysEndWait = &Sys_EndWait;
2214     pTable->m_pfnSys_SetTitle = &Sys_SetTitle;
2215     pTable->m_pfnSysBeep = &Sys_Beep;
2216     pTable->m_pfnSys_Status = &Sys_Status;
2217     pTable->m_pfnMapFree = &Map_Free;
2218     pTable->m_pfnMapNew = &Map_New;
2219     pTable->m_pfnMapBuildBrushData = &Map_BuildBrushData;
2220     pTable->m_pfnMap_IsBrushFiltered = &Map_IsBrushFiltered;
2221     pTable->m_pfnMapStartPosition = &Map_StartPosition;
2222     pTable->m_pfnMapRegionOff = &Map_RegionOff;
2223     pTable->m_pfnSetBuildWindingsNoTexBuild = &Brush_SetBuildWindingsNoTexBuild;
2224     pTable->m_pfnPointFileClear = &Pointfile_Clear;
2225     pTable->m_pfnCSG_MakeHollow = &CSG_MakeHollow;
2226     pTable->m_pfnRegionSpawnPoint = &Region_SpawnPoint;
2227     pTable->m_pfnQGetTickCount = &QERApp_GetTickCount;
2228     pTable->m_pfnGetModelCache = &GetModelCache;
2229     pTable->m_pfnGetFileTypeRegistry = &GetFileTypeRegistry;
2230     pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;
2231     pTable->m_pfnGetMapName = &QERApp_GetMapName;
2232     pTable->m_pfnFilterAdd = &FilterCreate;
2233     pTable->m_pfnFiltersActivate = &FiltersActivate;
2234
2235     return true;
2236   }
2237   if (!strcmp(pAPI->major_name, SCRIPLIB_MAJOR))
2238   {
2239     _QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pAPI->mpTable);
2240     pScripLibTable->m_pfnGetToken = &GetToken;
2241     pScripLibTable->m_pfnGetTokenExtra = &GetTokenExtra;
2242     pScripLibTable->m_pfnToken = &QERApp_Token;
2243     pScripLibTable->m_pfnUnGetToken = &UngetToken;
2244     pScripLibTable->m_pfnStartTokenParsing = &StartTokenParsing;
2245     pScripLibTable->m_pfnScriptLine = &QERApp_ScriptLine;
2246     pScripLibTable->m_pfnTokenAvailable = &TokenAvailable;
2247     pScripLibTable->m_pfnCOM_Parse = &COM_Parse;
2248     pScripLibTable->m_pfnGet_COM_Token = &Get_COM_Token;
2249
2250     return true;
2251   }
2252   if (!strcmp(pAPI->major_name, BRUSH_MAJOR))
2253   {
2254     _QERBrushTable *pBrushTable = static_cast<_QERBrushTable *>(pAPI->mpTable);
2255     pBrushTable->m_pfnBP_MessageBox = &BP_MessageBox;
2256     pBrushTable->m_pfnBrush_AddToList = &Brush_AddToList;
2257     pBrushTable->m_pfnBrush_Build = &Brush_Build;
2258     pBrushTable->m_pfnBrush_Create = &Brush_Create;
2259     pBrushTable->m_pfnBrush_Free = &Brush_Free;
2260     pBrushTable->m_pfnBrush_Rotate = &Brush_Rotate;
2261     pBrushTable->m_pfnBrushAlloc = &Brush_Alloc;
2262     pBrushTable->m_pfnFace_Alloc = &Face_Alloc;
2263     pBrushTable->m_pfnHasModel = NULL;// &HasModel;
2264
2265     return true;
2266   }
2267   if (!strcmp(pAPI->major_name, APPSHADERS_MAJOR))
2268   {
2269     _QERAppShadersTable *pShadersTable = static_cast<_QERAppShadersTable*>(pAPI->mpTable);
2270     pShadersTable->m_pfnQTextures = QERApp_QTextures;
2271     pShadersTable->m_pfnQTexmap = QERApp_QTexmap;
2272     pShadersTable->m_pfnQeglobalsTexturewin = QERApp_QeglobalsTexturewin;
2273     pShadersTable->m_pfnTexture_SetTexture = QERApp_Texture_SetTexture;
2274     pShadersTable->m_pfnTexture_ShowInuse = Texture_ShowInuse;
2275     pShadersTable->m_pfnBuildShaderList = &BuildShaderList;
2276     pShadersTable->m_pfnPreloadShaders = &PreloadShaders;
2277
2278     return true;
2279   }
2280   if (!strcmp(pAPI->major_name, QGL_MAJOR))
2281   {
2282     _QERQglTable *pQglTable = static_cast<_QERQglTable *>(pAPI->mpTable);
2283     pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;
2284     pQglTable->m_pfn_qglBegin = qglBegin;
2285     pQglTable->m_pfn_qglBindTexture = qglBindTexture;
2286     pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;
2287     pQglTable->m_pfn_qglCallList = qglCallList;
2288     pQglTable->m_pfn_qglCallLists = qglCallLists;
2289     pQglTable->m_pfn_qglClear = qglClear;
2290     pQglTable->m_pfn_qglClearColor = qglClearColor;
2291     pQglTable->m_pfn_qglClearDepth = qglClearDepth;
2292     pQglTable->m_pfn_qglColor3f = qglColor3f;
2293     pQglTable->m_pfn_qglColor3fv = qglColor3fv;
2294     pQglTable->m_pfn_qglColor4f = qglColor4f;
2295     pQglTable->m_pfn_qglColor4fv = qglColor4fv;
2296         pQglTable->m_pfn_qglColor4ubv = qglColor4ubv;
2297     pQglTable->m_pfn_qglColorPointer = qglColorPointer;
2298     pQglTable->m_pfn_qglCullFace = qglCullFace;
2299     pQglTable->m_pfn_qglDepthFunc = qglDepthFunc;
2300     pQglTable->m_pfn_qglDepthMask = qglDepthMask;
2301     pQglTable->m_pfn_qglDisable = qglDisable;
2302     pQglTable->m_pfn_qglDisableClientState = qglDisableClientState;
2303     pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;
2304     pQglTable->m_pfn_qglDeleteTextures = qglDeleteTextures;
2305     pQglTable->m_pfn_qglDrawElements = qglDrawElements;
2306     pQglTable->m_pfn_qglEnable = qglEnable;
2307     pQglTable->m_pfn_qglEnableClientState = qglEnableClientState;
2308     pQglTable->m_pfn_qglEnd = qglEnd;
2309     pQglTable->m_pfn_qglEndList = qglEndList;
2310     pQglTable->m_pfn_qglFogf = qglFogf;
2311     pQglTable->m_pfn_qglFogfv = qglFogfv;
2312     pQglTable->m_pfn_qglFogi = qglFogi;
2313     pQglTable->m_pfn_qglGenLists = qglGenLists;
2314     pQglTable->m_pfn_qglGenTextures = qglGenTextures;
2315     pQglTable->m_pfn_qglGetDoublev = qglGetDoublev;
2316     pQglTable->m_pfn_qglGetIntegerv = qglGetIntegerv;
2317     pQglTable->m_pfn_qglHint = qglHint;
2318     pQglTable->m_pfn_qglLightfv = qglLightfv;
2319     pQglTable->m_pfn_qglLineStipple = qglLineStipple;
2320     pQglTable->m_pfn_qglLineWidth = qglLineWidth;
2321     pQglTable->m_pfn_qglListBase = qglListBase;
2322     pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;
2323     pQglTable->m_pfn_qglMaterialf = qglMaterialf;
2324     pQglTable->m_pfn_qglMaterialfv = qglMaterialfv;
2325     pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;
2326     pQglTable->m_pfn_qglMultMatrixf = qglMultMatrixf;
2327     pQglTable->m_pfn_qglNewList = qglNewList;
2328     pQglTable->m_pfn_qglNormal3f = qglNormal3f;
2329     pQglTable->m_pfn_qglNormal3fv = qglNormal3fv;
2330     pQglTable->m_pfn_qglNormalPointer = qglNormalPointer;
2331     pQglTable->m_pfn_qglOrtho = qglOrtho;
2332     pQglTable->m_pfn_qglPointSize = qglPointSize;
2333     pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;
2334     pQglTable->m_pfn_qglPopAttrib = qglPopAttrib;
2335     pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;
2336     pQglTable->m_pfn_qglPushAttrib = qglPushAttrib;
2337     pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;
2338     pQglTable->m_pfn_qglRasterPos3fv = qglRasterPos3fv;
2339     pQglTable->m_pfn_qglRotated = qglRotated;
2340     pQglTable->m_pfn_qglRotatef = qglRotatef;
2341     pQglTable->m_pfn_qglScalef = qglScalef;
2342     pQglTable->m_pfn_qglScissor = qglScissor;
2343     pQglTable->m_pfn_qglShadeModel = qglShadeModel;
2344     pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;
2345     pQglTable->m_pfn_qglTexCoord2fv = qglTexCoord2fv;
2346     pQglTable->m_pfn_qglTexCoordPointer = qglTexCoordPointer;
2347     pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;
2348     pQglTable->m_pfn_qglTexGenf = qglTexGenf;
2349     pQglTable->m_pfn_qglTexImage1D = qglTexImage1D;
2350     pQglTable->m_pfn_qglTexImage2D = qglTexImage2D;
2351     pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;
2352     pQglTable->m_pfn_qglTexParameterfv = qglTexParameterfv;
2353     pQglTable->m_pfn_qglTexParameteri = qglTexParameteri;
2354     pQglTable->m_pfn_qglTexParameteriv = qglTexParameteriv;
2355     pQglTable->m_pfn_qglTexSubImage1D = qglTexSubImage1D;
2356     pQglTable->m_pfn_qglTexSubImage2D = qglTexSubImage2D;
2357     pQglTable->m_pfn_qglTranslated = qglTranslated;
2358     pQglTable->m_pfn_qglTranslatef = qglTranslatef;
2359     pQglTable->m_pfn_qglVertex2f = qglVertex2f;
2360     pQglTable->m_pfn_qglVertex3f = qglVertex3f;
2361     pQglTable->m_pfn_qglVertex3fv = qglVertex3fv;
2362     pQglTable->m_pfn_qglVertexPointer = qglVertexPointer;
2363     pQglTable->m_pfn_qglViewport = qglViewport;
2364
2365     pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;
2366
2367     pQglTable->m_pfn_qgluPerspective = qgluPerspective;
2368     pQglTable->m_pfn_qgluLookAt = qgluLookAt;
2369     pQglTable->m_pfnHookGL2DWindow = QERApp_HookGL2DWindow;
2370     pQglTable->m_pfnUnHookGL2DWindow = QERApp_UnHookGL2DWindow;
2371     pQglTable->m_pfnHookGL3DWindow = QERApp_HookGL3DWindow;
2372     pQglTable->m_pfnUnHookGL3DWindow = QERApp_UnHookGL3DWindow;
2373
2374     return true;
2375   }
2376   if (!strcmp(pAPI->major_name, DATA_MAJOR))
2377   {
2378     _QERAppDataTable *pDataTable = static_cast<_QERAppDataTable *>(pAPI->mpTable);
2379     pDataTable->m_pfnActiveBrushes = QERApp_ActiveBrushes;
2380     pDataTable->m_pfnSelectedBrushes = QERApp_SelectedBrushes;
2381     pDataTable->m_pfnFilteredBrushes = QERApp_FilteredBrushes;
2382     pDataTable->m_pfnLstSkinCache = QERApp_LstSkinCache;
2383
2384     return true;
2385   }
2386   if (!strcmp(pAPI->major_name, PATCH_MAJOR))
2387   {
2388     _QERPatchTable *pPatchTable = static_cast<_QERPatchTable *>(pAPI->mpTable);
2389     pPatchTable->m_pfnPatch_Alloc = &Patch_Alloc;
2390     pPatchTable->m_pfnAddBrushForPatch = &AddBrushForPatch;
2391     pPatchTable->m_pfnMakeNewPatch = &MakeNewPatch;
2392
2393     return true;
2394   }
2395   if (!strcmp(pAPI->major_name, ECLASSMANAGER_MAJOR))
2396   {
2397     _EClassManagerTable *pEClassManTable = static_cast<_EClassManagerTable *>(pAPI->mpTable);
2398
2399     pEClassManTable->m_pfnEclass_InsertAlphabetized = &Eclass_InsertAlphabetized;
2400     pEClassManTable->m_pfnGet_Eclass_E = &Get_EClass_E;
2401     pEClassManTable->m_pfnSet_Eclass_Found = &Set_Eclass_Found;
2402     pEClassManTable->m_pfnGet_Parsing_Single = &Get_Parsing_Single;
2403     pEClassManTable->m_pfnEClass_Create = &EClass_Create;
2404     pEClassManTable->m_pfnEclass_ForName = &Eclass_ForName;
2405
2406     return true;
2407   }
2408   if (!strcmp(pAPI->major_name, SELECTEDFACE_MAJOR))
2409   {
2410     _QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pAPI->mpTable);
2411
2412     pSelectedFaceTable->m_pfnGetSelectedFaceCount = &QERApp_GetSelectedFaceCount;
2413     pSelectedFaceTable->m_pfnGetFaceBrush = &QERApp_GetSelectedFaceBrush;
2414     pSelectedFaceTable->m_pfnGetFace = &QERApp_GetSelectedFace;
2415     pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;
2416     pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;
2417     pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;
2418     pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;
2419     pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;
2420     return true;
2421   }
2422   if (!strcmp(pAPI->major_name, APPSURFACEDIALOG_MAJOR))
2423   {
2424     _QERAppSurfaceTable *pSurfDialogTable = static_cast<_QERAppSurfaceTable *>(pAPI->mpTable);
2425     pSurfDialogTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;
2426     pSurfDialogTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;
2427     pSurfDialogTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;
2428     pSurfDialogTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;
2429     pSurfDialogTable->m_pfnTexMatToFakeTexCoords = &TexMatToFakeTexCoords;
2430     pSurfDialogTable->m_pfnConvertTexMatWithQTexture = &ConvertTexMatWithQTexture;
2431     pSurfDialogTable->m_pfnFakeTexCoordsToTexMat = &FakeTexCoordsToTexMat;
2432     pSurfDialogTable->m_pfnPatch_ResetTexturing = &Patch_ResetTexturing;
2433     pSurfDialogTable->m_pfnPatch_FitTexturing = &Patch_FitTexturing;
2434     pSurfDialogTable->m_pfnPatch_NaturalizeSelected = &Patch_NaturalizeSelected;
2435     pSurfDialogTable->m_pfnPatch_GetTextureName = &Patch_GetTextureName;
2436     pSurfDialogTable->m_pfnQE_SingleBrush = &QE_SingleBrush;
2437     pSurfDialogTable->m_pfnIsBrushPrimitMode = &IsBrushPrimitMode;
2438     pSurfDialogTable->m_pfnComputeAxisBase = &ComputeAxisBase;
2439     pSurfDialogTable->m_pfnBPMatMul = &BPMatMul;
2440     pSurfDialogTable->m_pfnEmitBrushPrimitTextureCoordinates = &EmitBrushPrimitTextureCoordinates;
2441     pSurfDialogTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;
2442     pSurfDialogTable->m_pfnSelect_FitTexture = &Select_FitTexture;
2443     pSurfDialogTable->m_pfnQERApp_QeglobalsSavedinfo_SIInc = &QERApp_QeglobalsSavedinfo_SIInc;
2444     pSurfDialogTable->m_pfnQeglobalsGetGridSize = &QERApp_QeglobalsGetGridSize;
2445     pSurfDialogTable->m_pfnFaceList_FitTexture = &SI_FaceList_FitTexture;
2446     pSurfDialogTable->m_pfnGetMainWindow = &SI_GetMainWindow;
2447     pSurfDialogTable->m_pfnSetWinPos_From_Prefs = &SI_SetWinPos_from_Prefs;
2448     pSurfDialogTable->m_pfnGetSelectedFaceCountfromBrushes = &SI_GetSelectedFaceCountfromBrushes;
2449     pSurfDialogTable->m_pfnGetSelFacesTexdef = &SI_GetSelFacesTexdef;
2450     pSurfDialogTable->m_pfnSetTexdef_FaceList = &SI_SetTexdef_FaceList;
2451
2452     return true;
2453   }
2454   if (!strcmp(pAPI->major_name, UNDO_MAJOR))
2455   {
2456     _QERUndoTable *pUndoTable = static_cast<_QERUndoTable *>(pAPI->mpTable);
2457
2458     pUndoTable->m_pfnUndo_Start = &Undo_Start;
2459     pUndoTable->m_pfnUndo_End = &Undo_End;
2460     pUndoTable->m_pfnUndo_AddBrush = &Undo_AddBrush;
2461     pUndoTable->m_pfnUndo_EndBrush = &Undo_EndBrush;
2462     pUndoTable->m_pfnUndo_AddBrushList = &Undo_AddBrushList;
2463     pUndoTable->m_pfnUndo_EndBrushList = &Undo_EndBrushList;
2464     pUndoTable->m_pfnUndo_AddEntity = &Undo_AddEntity;
2465     pUndoTable->m_pfnUndo_EndEntity = &Undo_EndEntity;
2466     pUndoTable->m_pfnUndo_Undo = &Undo_Undo;                     // Nurail
2467     pUndoTable->m_pfnUndo_Redo = &Undo_Redo;                     // Nurail
2468     pUndoTable->m_pfnUndo_GetUndoId = &Undo_GetUndoId;           // Nurail
2469     pUndoTable->m_pfnUndo_UndoAvailable = &Undo_UndoAvailable;   // Nurail
2470     pUndoTable->m_pfnUndo_RedoAvailable = &Undo_RedoAvailable;   // Nurail
2471
2472     return true;
2473   }
2474   if (!strcmp(pAPI->major_name, CAMERA_MAJOR))
2475   {
2476     _QERCameraTable *pCameraTable = static_cast<_QERCameraTable *>(pAPI->mpTable);
2477
2478     pCameraTable->m_pfnGetCamera = &QERApp_GetCamera;
2479     pCameraTable->m_pfnSetCamera = &QERApp_SetCamera;
2480     pCameraTable->m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;
2481
2482     return true;
2483   }
2484   if (!strcmp(pAPI->major_name, UI_MAJOR))
2485   {
2486     _QERUITable *pUITable = static_cast<_QERUITable *>(pAPI->mpTable);
2487
2488     pUITable->m_pfnCreateGLWindow = QERApp_CreateGLWindow;
2489     pUITable->m_pfnHookWindow = QERApp_HookWindow;
2490     pUITable->m_pfnUnHookWindow = QERApp_UnHookWindow;
2491     pUITable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;
2492     pUITable->m_pfnHookListener = QERApp_HookListener;
2493     pUITable->m_pfnUnHookListener = QERApp_UnHookListener;
2494
2495     return true;
2496   }
2497   if (!strcmp(pAPI->major_name, UIGTK_MAJOR))
2498   {
2499     _QERUIGtkTable *pUIGtkTable = static_cast<_QERUIGtkTable *>(pAPI->mpTable);
2500
2501     pUIGtkTable->m_pfn_GetQeglobalsGLWidget = &QERApp_GetQeGlobalsGLWidget;
2502     pUIGtkTable->m_pfn_glwidget_new = &gtk_glwidget_new;
2503     pUIGtkTable-> m_pfn_glwidget_swap_buffers = &gtk_glwidget_swap_buffers;
2504     pUIGtkTable->m_pfn_glwidget_make_current = &gtk_glwidget_make_current;
2505     pUIGtkTable->m_pfn_glwidget_destroy_context = &gtk_glwidget_destroy_context;
2506     pUIGtkTable->m_pfn_glwidget_create_context = &gtk_glwidget_create_context;
2507 #if 0
2508     pUIGtkTable->m_pfn_glwidget_get_context = &gtk_glwidget_get_context;
2509 #endif
2510
2511     return true;
2512   }
2513
2514   return false;
2515 }
2516
2517 const char* CSynapseClientRadiant::GetInfo()
2518 {
2519   return "Radiant - synapse core built " __DATE__ " " RADIANT_VERSION;
2520 }
2521
2522 const char* CSynapseClientRadiant::GetName()
2523 {
2524   return "core";
2525 }