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