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