]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/pluginmanager.cpp
* fixed warnings
[xonotic/netradiant.git] / radiant / pluginmanager.cpp
index 7840b0b5ebcdb71a66bdc6b921de697c4df42911..021531ac1c7319068a90ef64d5b7902b40270e62 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-// PlugInManager.cpp: implementation of the CPlugInManager class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "stdafx.h"\r
-#if defined (__linux__) || defined (__APPLE__)\r
-  #include <dirent.h>\r
-  #include <sys/time.h>\r
-#endif\r
-#ifdef __APPLE__\r
-  #ifdef __cplusplus\r
-    extern "C" {\r
-    #endif\r
-    #include <dlfcn.h>\r
-    #ifdef __cplusplus\r
-    }\r
-  #endif\r
-#endif\r
-#ifdef _WIN32\r
-  #include "objbase.h"\r
-#endif\r
-#include "pluginmanager.h"\r
-#include "plugin.h"\r
-#include "missing.h"\r
-\r
-#include "version.h"\r
-\r
-CRadiantImageManager g_ImageManager;\r
-CRadiantPluginManager g_PluginsManager;    \r
-\r
-_QERPlugSurfaceTable g_SurfaceTable;\r
-_QERFileSystemTable g_FileSystemTable;\r
-_QERShadersTable g_ShadersTable;\r
-_QERPlugMapTable g_MapTable;\r
-_QERPlugMapTable g_MapTable2;\r
-_QEREntityTable g_EntityTable;\r
-_EClassTable g_EClassDefTable;\r
-\r
-/*!\r
-  extending entity class formats\r
-  this approach only allows a single additional format, but it is enough for now\r
-*/\r
-bool g_bHaveEClassExt = false;\r
-_EClassTable g_EClassExtTable;\r
-\r
-\r
-filetype_t g_pattern_all("all files", "*.*");\r
-filetype_t g_pattern_projqe4v2("qe4 v2 project files", "*.qe4");\r
-filetype_t g_pattern_projxml("xml project files", "*.proj");\r
-filetype_t g_pattern_mapq3("quake3 maps", "*.map");\r
-filetype_t g_pattern_mapxml("xml quake3 maps", "*.xmap");\r
-filetype_t g_pattern_modelmd3("md3 models", "*.md3");\r
-filetype_t g_pattern_modelmdc("mdc models", "*.mdc");\r
-filetype_t g_pattern_modelmd2("md2 models", "*.md2");\r
-filetype_t g_pattern_modelmdl("mdl models", "*.mdl");\r
-//filetype_t g_pattern_modelea3("EA3 models", "*.ea3");\r
-filetype_t g_pattern_soundwav("PCM sound files", "*.wav");\r
-filetype_t g_pattern_regq3("quake3 region", "*.reg");\r
-\r
-#include <map>\r
-\r
-class RadiantFileTypeRegistry : public IFileTypeRegistry\r
-{\r
-public:\r
-  virtual ~RadiantFileTypeRegistry() {}\r
-  virtual void addType(const char* key, filetype_t type)\r
-  {\r
-    m_typelists[key].push_back(type);\r
-  }\r
-  virtual void getTypeList(const char* key, IFileTypeList* typelist)\r
-  {\r
-    filetype_list_t& list_ref = m_typelists[key];\r
-    for(unsigned int i=0; i<list_ref.size(); ++i)\r
-      typelist->addType(list_ref[i].getType());\r
-  }\r
-private:\r
-  struct filetype_copy_t\r
-  {\r
-    inline filetype_copy_t(const filetype_t other)\r
-      : m_name(other.name), m_pattern(other.pattern)\r
-    {}\r
-    inline filetype_t getType() const\r
-    {\r
-      return filetype_t(m_name.c_str(), m_pattern.c_str());\r
-    }\r
-  private:\r
-    string_t m_name;\r
-    string_t m_pattern;\r
-  };\r
-  typedef vector<filetype_copy_t> filetype_list_t;\r
-  map<string_t, filetype_list_t> m_typelists;\r
-};\r
-\r
-static RadiantFileTypeRegistry g_patterns;\r
-\r
-IFileTypeRegistry* GetFileTypeRegistry()\r
-{\r
-  return &g_patterns;\r
-}\r
-\r
-void InitFileTypes()\r
-{\r
-  //GetFileTypeRegistry()->addType("project", g_pattern_projqe4v2);\r
-  GetFileTypeRegistry()->addType("project", g_pattern_projxml);\r
-\r
-  GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapq3);\r
-  GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapxml);\r
-  \r
-  GetFileTypeRegistry()->addType("region", g_pattern_regq3);\r
-/*\r
-  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd3);\r
-  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd2);\r
-  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdl);\r
-  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdc);\r
-  //GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelea3);\r
-  */\r
-\r
-  GetFileTypeRegistry()->addType("sound", g_pattern_soundwav);\r
-}\r
-\r
-\r
-class CRadiantModelModuleManager : public CSynapseAPIManager\r
-{\r
-  typedef list<APIDescriptor_t*> APIDescriptorList;\r
-\r
-  APIDescriptorList mAPIs;\r
-public:\r
-  CRadiantModelModuleManager()\r
-  {\r
-    SetMatchAPI(MODEL_MAJOR, "*");\r
-  }\r
-  virtual ~CRadiantModelModuleManager()\r
-  {\r
-    APIDescriptorList::iterator i;\r
-    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
-    {\r
-      delete (_QERPlugModelTable*)(*i)->mpTable;\r
-      delete *i;\r
-      *i = NULL;\r
-    }\r
-    mAPIs.clear();\r
-  }\r
-\r
-  // CSynapseAPIManager interface -------------------\r
-  APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)\r
-  {\r
-    APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
-    pRequireAPI->mpTable = new _QERPlugModelTable;\r
-    ((_QERPlugModelTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugModelTable);\r
-    pRequireAPI->mSize = sizeof(_QERPlugModelTable);\r
-    mAPIs.push_front(pRequireAPI);\r
-    return pRequireAPI;\r
-  }\r
-\r
-  // Model Manager specific\r
-  const _QERPlugModelTable* GetModelTable(const char* version)\r
-  {\r
-    APIDescriptorList::iterator i;\r
-    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
-      if(strcmp(version, (*i)->minor_name) == 0)\r
-        return ((_QERPlugModelTable*)(*i)->mpTable);\r
-    return NULL;\r
-  }\r
-};\r
-\r
-CRadiantModelModuleManager g_ModelManager;\r
-\r
-/*! One of these exists for each unique model ID in use */\r
-class CModelWrapper\r
-{\r
-  friend class CModelManager;\r
-public:\r
-  CModelWrapper (const char *id, const char* version) : refcount(1)\r
-  {\r
-    copy(id, version);\r
-    construct();\r
-  }\r
-  void Refresh()\r
-  {\r
-    destroy();\r
-    construct();\r
-  }\r
-  ~CModelWrapper ()\r
-  {\r
-    destroy();\r
-  }\r
-private:\r
-  void copy(const char* id, const char* version)\r
-  {\r
-    m_id = id;\r
-    m_version = version;\r
-  }\r
-  void construct()\r
-  {\r
-    m_model.pRender = NULL;\r
-    m_model.pSelect = NULL;\r
-    m_model.pEdit = NULL;\r
-\r
-    const _QERPlugModelTable* pTable = g_ModelManager.GetModelTable(m_version.c_str());\r
-\r
-    if(pTable != NULL)\r
-      pTable->m_pfnLoadModel(&m_model, m_id.c_str());\r
-  }\r
-  void destroy()\r
-  {\r
-    if (m_model.pRender) m_model.pRender->DecRef();\r
-    if (m_model.pSelect) m_model.pSelect->DecRef();\r
-    if (m_model.pEdit) m_model.pEdit->DecRef();\r
-  }\r
-  string_t m_id;\r
-  string_t m_version;\r
-  entity_interfaces_t m_model;\r
-  int refcount;\r
-};\r
-\r
-/*! Creates and tracks CModelWrapper instances.\r
-Creates a new instance for each unique ID requested, keeps count of the number of\r
-times an ID is being referenced, and destroys any instance that is no longer in use */\r
-class CModelManager : public IModelCache\r
-{\r
-public:\r
-  CModelManager()\r
-  {\r
-    m_ptrs = g_ptr_array_new ();\r
-  }\r
-  virtual ~CModelManager()\r
-  {\r
-    g_ptr_array_free(m_ptrs, FALSE);\r
-  }\r
-\r
-  virtual void DeleteByID(const char *id, const char* version)\r
-  {\r
-    unsigned int i;\r
-    CModelWrapper *elem;\r
-    for(i=0; i<m_ptrs->len; i++)\r
-    {\r
-      elem = (CModelWrapper*)m_ptrs->pdata[i];\r
-      if(strcmp(elem->m_version.c_str(), version) == 0\r
-        && strcmp(elem->m_id.c_str(), id) == 0\r
-        && --elem->refcount == 0)\r
-      {\r
-        g_ptr_array_remove_index_fast(m_ptrs, i);\r
-        delete elem;\r
-        return;\r
-      }\r
-    }\r
-  }\r
-\r
-  virtual entity_interfaces_t *GetByID(const char *id, const char* version)\r
-  {\r
-    unsigned int i;\r
-    CModelWrapper *elem;\r
-    for(i=0; i<m_ptrs->len; i++)\r
-    {\r
-      elem = (CModelWrapper*)m_ptrs->pdata[i];\r
-      if(strcmp(elem->m_version.c_str(), version) == 0\r
-        && strcmp(elem->m_id.c_str(), id) == 0)\r
-      {\r
-        elem->refcount++;\r
-        return &elem->m_model;\r
-      }\r
-    }\r
-    \r
-    elem = new CModelWrapper(id, version);\r
-    g_ptr_array_add(m_ptrs, elem);\r
-\r
-    return &elem->m_model;\r
-  }\r
-\r
-  virtual void RefreshAll()\r
-  {\r
-    for(unsigned int i=0; i<m_ptrs->len; ++i)\r
-      ((CModelWrapper*)m_ptrs->pdata[i])->Refresh();\r
-  }\r
-private:\r
-  GPtrArray *m_ptrs; // array of CModelWrapper*\r
-};\r
-\r
-CModelManager g_model_cache;\r
-\r
-IModelCache* GetModelCache()\r
-{\r
-  return &g_model_cache;\r
-}\r
-\r
-// toolbar manager\r
-class CRadiantToolbarModuleManager : public CSynapseAPIManager\r
-{\r
-  typedef list<APIDescriptor_t*> APIDescriptorList;\r
-\r
-  APIDescriptorList mAPIs;\r
-public:\r
-  CRadiantToolbarModuleManager()\r
-  {\r
-    SetMatchAPI(TOOLBAR_MAJOR, "*");\r
-  }\r
-  virtual ~CRadiantToolbarModuleManager()\r
-  {\r
-    APIDescriptorList::iterator i;\r
-    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
-    {\r
-      delete (_QERPlugToolbarTable*)(*i)->mpTable;\r
-      delete *i;\r
-      *i = NULL;\r
-    }\r
-    mAPIs.clear();\r
-  }\r
-  \r
-  // CSynapseAPIManager interface -------------------\r
-  APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)\r
-  {\r
-    APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
-    pRequireAPI->mpTable = new _QERPlugToolbarTable;\r
-    ((_QERPlugToolbarTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugToolbarTable);\r
-    pRequireAPI->mSize = sizeof(_QERPlugToolbarTable);\r
-    mAPIs.push_front(pRequireAPI);\r
-    return pRequireAPI;\r
-  }\r
-\r
-  // Toolbar Manager specific\r
-  void ConstructToolbar()\r
-  {\r
-    APIDescriptorList::iterator i;\r
-    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
-      AddItem((_QERPlugToolbarTable*)(*i)->mpTable);\r
-  }\r
-  \r
-private:\r
-\r
-  void AddItem(_QERPlugToolbarTable* pTable)\r
-  {\r
-    const unsigned int count = pTable->m_pfnToolbarButtonCount();\r
-    for(unsigned int i=0; i<count; ++i)\r
-    {\r
-      const IToolbarButton* button = pTable->m_pfnGetToolbarButton(i);\r
-      g_pParentWnd->AddPlugInToolbarButton(button);\r
-    }\r
-  }\r
-};\r
-\r
-CRadiantToolbarModuleManager g_ToolbarModuleManager;\r
-\r
-\r
-/* image manager ---------------------------------------- */\r
-\r
-CRadiantImageManager::~CRadiantImageManager()\r
-{\r
-  list<CImageTableSlot *>::iterator iSlot;\r
-  for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
-  {\r
-    delete *iSlot;\r
-    *iSlot = NULL;\r
-  }\r
-}\r
-\r
-void CImageTableSlot::InitForFillAPITable(APIDescriptor_t *pAPI)\r
-{\r
-  mpAPI = pAPI;\r
-  mpTable = new _QERPlugImageTable;\r
-  mpTable->m_nSize = sizeof(_QERPlugImageTable);\r
-  mpAPI->mSize = sizeof(_QERPlugImageTable);\r
-  mpAPI->mpTable = mpTable;\r
-}\r
-\r
-void CRadiantImageManager::FillAPITable(APIDescriptor_t *pAPI)\r
-{\r
-  CImageTableSlot *pSlot = new CImageTableSlot();\r
-  pSlot->InitForFillAPITable(pAPI);\r
-  mSlots.push_front(pSlot);\r
-}\r
-\r
-/*!\r
-  Loads an image by calling the module that handles the extension extracted from the filename\r
-  \param name The filename to load. If no extension is provided, we walk the list of supported extensions.\r
-  \param pic The returned image data\r
-  \param width The returned width of the image\r
-  \param height The returned height of the image\r
-*/\r
-void CRadiantImageManager::LoadImage(const char *name, byte **pic, int *width, int *height)\r
-{\r
-  const char *ext = NULL;\r
-  int len;\r
-\r
-  // extract extension\r
-  len = strlen (name);\r
-  if ((len > 5) && (name[len-4] == '.'))\r
-    ext = &name[len-3];\r
-\r
-  if (ext == NULL)\r
-  {\r
-    // if no extension is provided, start walking through the list\r
-    Str fullname;\r
-    list<CImageTableSlot *>::iterator iSlot;\r
-    for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
-    {\r
-      APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();\r
-      fullname.Format("%s.%s", name, pAPI->minor_name);\r
-      (*iSlot)->GetTable()->m_pfnLoadImage(fullname.GetBuffer(), pic, width, height);\r
-      if (*pic)\r
-        return; // this was the right extension, we loaded\r
-    }\r
-    return;\r
-  }\r
-  \r
-  // start walking the interfaces\r
-  list<CImageTableSlot *>::iterator iSlot;\r
-  for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
-  {\r
-    APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();\r
-    if (!strcmp(pAPI->minor_name, ext))\r
-    {\r
-      (*iSlot)->GetTable()->m_pfnLoadImage(name, pic, width, height);\r
-      return;\r
-    }\r
-  }\r
-  Sys_FPrintf(SYS_WRN, "WARNING: no image table for extension '%s'\n", ext);\r
-}\r
-\r
-void CRadiantImageManager::BeginExtensionsScan()\r
-{\r
-  mExtScanSlot = mSlots.begin();\r
-}\r
-\r
-const char* CRadiantImageManager::GetNextExtension()\r
-{\r
-  if (mExtScanSlot != mSlots.end())\r
-  {\r
-    char *ext = (*mExtScanSlot)->GetDescriptor()->minor_name;\r
-    mExtScanSlot++;\r
-    return ext;\r
-  }\r
-  return NULL;\r
-}\r
-\r
-/* plugin manager --------------------------------------- */\r
-APIDescriptor_t* CRadiantPluginManager::BuildRequireAPI(APIDescriptor_t *pAPI)\r
-{  \r
-  CPluginSlot *pSlot = new CPluginSlot(pAPI);\r
-  mSlots.push_front(pSlot);\r
-  return pSlot->GetDescriptor();\r
-}\r
-\r
-void CRadiantPluginManager::PopulateMenu()\r
-{\r
-  list<CPluginSlot *>::iterator iPlug;\r
-  for(iPlug=mSlots.begin(); iPlug != mSlots.end(); iPlug++)\r
-  {\r
-    g_pParentWnd->AddPlugInMenuItem(*iPlug);\r
-  }\r
-}\r
-\r
-void CSynapseClientRadiant::ImportMap(IDataStream *in, CPtrArray *ents, const char *type)\r
-{\r
-  if (strcmp(type,"map")==0)\r
-  {\r
-    g_MapTable.m_pfnMap_Read(in, ents);\r
-  }\r
-  else if (strcmp(type,"xmap")==0)\r
-  {\r
-    g_MapTable2.m_pfnMap_Read(in, ents);    \r
-  }\r
-  else\r
-    Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);\r
-}\r
-\r
-void CSynapseClientRadiant::ExportMap(CPtrArray *ents, IDataStream *out, const char *type)\r
-{\r
-  if (strcmp(type,"map")==0)\r
-  {\r
-    g_MapTable.m_pfnMap_Write(ents, out);\r
-  }\r
-  else if (strcmp(type,"xmap")==0)\r
-  {\r
-    g_MapTable2.m_pfnMap_Write(ents, out);\r
-  }\r
-  else\r
-    Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);\r
-}\r
-\r
-CPluginSlot::CPluginSlot(APIDescriptor_t *pAPI)\r
-{\r
-  mpAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
-  mpTable = new _QERPluginTable;\r
-  mpTable->m_nSize = sizeof(_QERPluginTable);\r
-  mpAPI->mSize = sizeof(_QERPluginTable);\r
-  mpAPI->mpTable = mpTable;\r
-  m_CommandStrings = NULL;\r
-  m_CommandIDs = NULL;\r
-  m_bReady = false;\r
-}\r
-\r
-CPluginSlot::~CPluginSlot()\r
-{  \r
-  delete mpAPI;\r
-  delete mpTable;\r
-  while (m_CommandStrings)\r
-  {\r
-    ::free (m_CommandStrings->data);\r
-    m_CommandStrings = g_slist_remove (m_CommandStrings, m_CommandStrings->data);\r
-  }\r
-}\r
-\r
-void CPluginSlot::Init()\r
-{\r
-  CString str =   mpTable->m_pfnQERPlug_GetCommandList();\r
-  char cTemp[1024];\r
-  strcpy(cTemp, str);\r
-  char* token = strtok(cTemp, ",;");\r
-  if (token && *token == ' ')\r
-  {\r
-    while (*token == ' ')\r
-    token++;\r
-  }\r
-  while (token != NULL)\r
-  {\r
-    m_CommandStrings = g_slist_append (m_CommandStrings, strdup (token));\r
-    token = strtok(NULL, ",;");\r
-  }\r
-  mpTable->m_pfnQERPlug_Init(NULL, (void*)g_pParentWnd->m_pWidget);\r
-  m_bReady = true;\r
-}\r
-\r
-const char* CPluginSlot::getMenuName()\r
-{\r
-  return mpAPI->minor_name;\r
-}\r
-\r
-int CPluginSlot::getCommandCount()\r
-{\r
-  if (!m_bReady)\r
-    Init();\r
-  return g_slist_length (m_CommandStrings);  \r
-}\r
-  \r
-const char* CPluginSlot::getCommand(int n)\r
-{\r
-  if (!m_bReady)\r
-    Init();\r
-  return (char*)g_slist_nth_data (m_CommandStrings, n);  \r
-}\r
-\r
-void CPluginSlot::addMenuID(int n)\r
-{\r
-  m_CommandIDs = g_slist_append (m_CommandIDs, GINT_TO_POINTER (n));\r
-}\r
-\r
-bool CPluginSlot::ownsCommandID(int n)\r
-{\r
-  GSList* lst;\r
-\r
-  for (lst = m_CommandIDs; lst != NULL; lst = g_slist_next (lst))\r
-  {\r
-    if (GPOINTER_TO_INT (lst->data) == n)\r
-      return true;\r
-  }\r
-  return false;\r
-}\r
-\r
-void CPluginSlot::Dispatch(const char *p)\r
-{\r
-  vec3_t vMin, vMax;\r
-  if (selected_brushes.next == &selected_brushes)\r
-  {\r
-    vMin[0] = vMin[1] = vMin[2] = 0;\r
-    VectorCopy(vMin, vMax);\r
-  } else\r
-  {\r
-    Select_GetBounds (vMin, vMax);\r
-  }\r
-  mpTable->m_pfnQERPlug_Dispatch(p, vMin, vMax, QE_SingleBrush(true));\r
-}\r
-\r
-CRadiantPluginManager::~CRadiantPluginManager()\r
-{\r
-  list<CPluginSlot *>::iterator iSlot;\r
-  for(iSlot=mSlots.begin(); iSlot!=mSlots.end(); iSlot++)\r
-  {\r
-    delete *iSlot;\r
-    *iSlot = NULL;\r
-  }\r
-}\r
-\r
-bool CRadiantPluginManager::Dispatch(int n, const char* p)\r
-{\r
-  list<CPluginSlot *>::iterator iPlug;\r
-  for(iPlug=mSlots.begin(); iPlug!=mSlots.end(); iPlug++)\r
-  {\r
-    CPluginSlot *pPlug = *iPlug;\r
-    if (pPlug->ownsCommandID(n))\r
-    {\r
-      pPlug->Dispatch(p);\r
-      return true;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-CPlugInManager::CPlugInManager()\r
-{\r
-  PatchesMode = EActivePatches;\r
-  m_PlugIns = NULL;\r
-}\r
-\r
-CPlugInManager::~CPlugInManager()\r
-{\r
-  Cleanup();\r
-}\r
-\r
-void CPlugInManager::InitForDir(const Str &dir)\r
-{\r
-  Str path;\r
-\r
-  path = dir;\r
-  path += g_strPluginsDir;\r
-  // SYNAPSE\r
-  g_pParentWnd->GetSynapseServer().AddSearchPath(path);\r
-\r
-  if (strcmp(g_strPluginsDir.GetBuffer(), g_strModulesDir.GetBuffer()) != 0)\r
-  {\r
-    path = dir;\r
-    path += g_strModulesDir;\r
-    // SYNAPSE\r
-    g_pParentWnd->GetSynapseServer().AddSearchPath(path);\r
-  } \r
-}\r
-\r
-static const XMLConfigEntry_t manager_entries[] = \r
-  { \r
-    { VFS_MAJOR,            SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },\r
-    { SHADERS_MAJOR,        SYN_REQUIRE, sizeof(g_ShadersTable),    &g_ShadersTable },\r
-    { MAP_MAJOR,            SYN_REQUIRE, sizeof(g_MapTable),        &g_MapTable },\r
-    { ECLASS_MAJOR,         SYN_REQUIRE, sizeof(g_EClassDefTable),  &g_EClassDefTable },\r
-    { SURFACEDIALOG_MAJOR,  SYN_REQUIRE, sizeof(g_SurfaceTable),    &g_SurfaceTable },\r
-    { NULL, SYN_UNKNOWN, 0, NULL } };\r
-\r
-void CPlugInManager::Init()\r
-{\r
-  Str synapse_config;\r
-  \r
-  Cleanup();\r
-  \r
-  // set some globals\r
-  g_qeglobals.bBSPFrontendPlugin = false;\r
-\r
-  InitForDir(g_strGameToolsPath);\r
-  InitForDir(g_strAppPath);\r
-\r
-  synapse_config = g_strGameToolsPath;\r
-  synapse_config += "synapse.config";\r
-  if (!g_pParentWnd->GetSynapseServer().Initialize(synapse_config.GetBuffer(), &Sys_Printf_VA))\r
-    Error("Synpase server initialization failed (see console)\n");\r
-  \r
-  // builtin modules\r
-  g_pParentWnd->GetSynapseServer().EnumerateBuiltinModule(&eclass_def);\r
-  \r
-  // APIs we provide\r
-  g_pParentWnd->GetSynapseClient().AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(_QERScripLibTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(BRUSH_MAJOR, NULL, sizeof(_QERBrushTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(APPSHADERS_MAJOR, NULL, sizeof(_QERAppShadersTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(DATA_MAJOR, NULL, sizeof(_QERAppDataTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(PATCH_MAJOR, NULL, sizeof(_QERPatchTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(_EClassManagerTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(_QERSelectedFaceTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(APPSURFACEDIALOG_MAJOR, NULL, sizeof(_QERAppSurfaceTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(UNDO_MAJOR, NULL, sizeof(_QERUndoTable));\r
-  g_pParentWnd->GetSynapseClient().AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable));  \r
-  g_pParentWnd->GetSynapseClient().AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable));  \r
-  g_pParentWnd->GetSynapseClient().AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable));  \r
-  \r
-  // modules configured by XML\r
-  if ( !g_pParentWnd->GetSynapseClient().ConfigXML( &g_pParentWnd->GetSynapseServer(), "core", manager_entries ) ) {\r
-    Error("Synapse server initialization failed (see console)\n");\r
-  }\r
-  \r
-  // adding a manager is a special case that ConfigXML doesn't take care of\r
-  g_pParentWnd->GetSynapseServer().SelectClientConfig( "core" );\r
-  char *minor;\r
-  if ( !g_pParentWnd->GetSynapseServer().GetConfigForAPI( IMAGE_MAJOR, &minor ) ) {\r
-    Syn_Printf( "GetConfigForAPI '%s' failed - invalid XML config file?\n", IMAGE_MAJOR );\r
-    Error("Synapse server initialization failed (see console)\n");\r
-  }\r
-  g_ImageManager.SetMatchAPI( IMAGE_MAJOR, minor );\r
-  g_pParentWnd->GetSynapseClient().AddManager( &g_ImageManager );\r
-  \r
-  // SYN_REQUIRE entries which are still hardcoded\r
-  g_pParentWnd->GetSynapseClient().AddAPI(MAP_MAJOR, "mapxml", sizeof(g_MapTable2), SYN_REQUIRE, &g_MapTable2);\r
-  g_pParentWnd->GetSynapseClient().AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);\r
-  \r
-  // plugins: load anything that claims to be a plugin\r
-  // minor becomes some kind of matching pattern\r
-  // g_PluginsManager is an API any class, it receives several function tables as needed\r
-  // you can't do a SYN_PROVIDE with that, has to be a SYN_REQUIRE ?\r
-  g_PluginsManager.SetMatchAPI(PLUGIN_MAJOR, "*");\r
-  g_pParentWnd->GetSynapseClient().AddManager(&g_PluginsManager);\r
-  g_pParentWnd->GetSynapseClient().AddManager(&g_ToolbarModuleManager);\r
-  g_pParentWnd->GetSynapseClient().AddManager(&g_ModelManager);\r
-  if (!g_pParentWnd->GetSynapseServer().Resolve(&g_pParentWnd->GetSynapseClient()))\r
-  {\r
-    Error("synapse initialization fail (see console)");\r
-  }\r
-  g_PluginsManager.PopulateMenu();\r
-  g_ToolbarModuleManager.ConstructToolbar();\r
-  InitFileTypes();\r
-}\r
-\r
-void CPlugInManager::Shutdown()\r
-{\r
-  g_pParentWnd->GetSynapseServer().Shutdown();\r
-}\r
-\r
-void CPlugInManager::Cleanup()\r
-{\r
-  int i;\r
-\r
-  for (i = 0; i < m_BrushHandles.GetSize(); i++)\r
-  {\r
-    brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));\r
-    Brush_Free(pb);\r
-  }\r
-  m_BrushHandles.RemoveAll();\r
-\r
-  for (i = 0; i < m_EntityHandles.GetSize(); i++)\r
-  {\r
-    entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));\r
-    Entity_Free(pe);\r
-  }\r
-  m_EntityHandles.RemoveAll();\r
-\r
-  // patches\r
-  // these are linked into the map\r
-  m_PatchesHandles.RemoveAll();\r
-  // these patches were allocated by Radiant on plugin request\r
-  // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map\r
-  // in which case we are supposed to delete them\r
-  // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been\r
-  // erased and we are trying a second time, therefore crashing ..\r
-  //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches\r
-#ifdef _DEBUG\r
-  if (m_PluginPatches.GetSize() != 0)\r
-    Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");\r
-#endif\r
-\r
-/*     for (i = 0; i < m_PluginPatches.GetSize(); i++)\r
-  {\r
-    patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));\r
-    if (pMesh->pSymbiot)\r
-      delete pMesh;\r
-  }\r
-  m_PluginPatches.RemoveAll(); */\r
-}\r
-\r
-void CPlugInManager::Dispatch(int n, const char * p)\r
-{\r
-  g_PluginsManager.Dispatch(n, p);\r
-}\r
-\r
-void WINAPI QERApp_GetDispatchParams(vec3_t vMin, vec3_t vMax, bool *bSingleBrush)\r
-{\r
-  if (selected_brushes.next == &selected_brushes)\r
-  {\r
-    vMin[0] = vMin[1] = vMin[2] = 0;\r
-    VectorCopy(vMin, vMax);\r
-  } else\r
-  {\r
-    Select_GetBounds (vMin, vMax);\r
-  }\r
-\r
-  if( bSingleBrush )\r
-    *bSingleBrush = QE_SingleBrush(true);\r
-}\r
-\r
-\r
-// creates a dummy brush in the active brushes list\r
-// FIXME : is this one really USED ?\r
-void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)\r
-{\r
-\r
-  brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);\r
-  Entity_LinkBrush (world_entity, pBrush);\r
-  Brush_Build(pBrush);\r
-  Brush_AddToList (pBrush, &active_brushes);\r
-  Select_Brush(pBrush);\r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-void* CPlugInManager::CreateBrushHandle()\r
-{\r
-  brush_t *pb = Brush_Alloc();\r
-  pb->numberId = g_nBrushId++;\r
-  m_BrushHandles.Add(pb);\r
-  return(void*)pb;\r
-}\r
-\r
-void CPlugInManager::DeleteBrushHandle(void * vp)\r
-{\r
-  CPtrArray* pHandles[3];\r
-  pHandles[0] = &m_SelectedBrushHandles;\r
-  pHandles[1] = &m_ActiveBrushHandles;\r
-  pHandles[2] = &m_BrushHandles;\r
-\r
-  for (int j = 0; j < 3; j++)\r
-  {\r
-    for (int i = 0; i < pHandles[j]->GetSize(); i++)\r
-    {\r
-      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));\r
-      if (pb == reinterpret_cast<brush_t*>(vp))\r
-      {\r
-        if (j == 2)\r
-        {\r
-          // only remove it from the list if it is work area\r
-          // this allows the selected and active list indexes to remain constant\r
-          // throughout a session (i.e. between an allocate and release)\r
-          pHandles[j]->RemoveAt(i);\r
-        }\r
-        Brush_Free(pb);\r
-        Sys_MarkMapModified();    // PGM\r
-        return;\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-void CPlugInManager::CommitBrushHandleToMap(void * vp)\r
-{\r
-  g_bScreenUpdates = false; \r
-  for (int i = 0; i < m_BrushHandles.GetSize(); i++)\r
-  {\r
-    brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));\r
-    if (pb == reinterpret_cast<brush_t*>(vp))\r
-    {\r
-      m_BrushHandles.RemoveAt(i);\r
-      Entity_LinkBrush (world_entity, pb);\r
-      Brush_Build(pb);\r
-      Brush_AddToList (pb, &active_brushes);\r
-      Select_Brush(pb);\r
-    }\r
-  }\r
-  g_bScreenUpdates = true; \r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)\r
-{\r
-  brush_t *bp = FindBrushHandle(vp);\r
-  if (bp != NULL)\r
-  {\r
-    face_t *f = Face_Alloc();\r
-    f->texdef = g_qeglobals.d_texturewin.texdef;\r
-    f->texdef.flags &= ~SURF_KEEP;\r
-    f->texdef.contents &= ~CONTENTS_KEEP;\r
-    f->next = bp->brush_faces;\r
-    bp->brush_faces = f;\r
-    VectorCopy (v1, f->planepts[0]);\r
-    VectorCopy (v2, f->planepts[1]);\r
-    VectorCopy (v3, f->planepts[2]);\r
-  }\r
-}\r
-\r
-brush_t* CPlugInManager::FindBrushHandle(void * vp)\r
-{\r
-  CPtrArray* pHandles[4];\r
-  pHandles[0] = &m_SelectedBrushHandles;\r
-  pHandles[1] = &m_ActiveBrushHandles;\r
-  pHandles[2] = &m_BrushHandles;\r
-  pHandles[3] = &m_EntityBrushHandles;\r
-\r
-  for (int j = 0; j < 4; j++)\r
-  {\r
-    for (int i = 0; i < pHandles[j]->GetSize(); i++)\r
-    {\r
-      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));\r
-      if (pb == reinterpret_cast<brush_t*>(vp))\r
-      {\r
-        return pb;\r
-      }\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-patchMesh_t* CPlugInManager::FindPatchHandle(int index)\r
-{\r
-  switch (PatchesMode)\r
-  {\r
-  case EActivePatches:\r
-  case ESelectedPatches:\r
-    if ( index < m_PatchesHandles.GetSize() )\r
-    {\r
-      brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));\r
-      return pb->pPatch;\r
-    }\r
-#ifdef _DEBUG\r
-    Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");\r
-#endif\r
-    break;\r
-  case EAllocatedPatches:\r
-    if ( index < m_PluginPatches.GetSize() )\r
-    {\r
-      patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));\r
-      return pPatch;\r
-    }\r
-#ifdef _DEBUG\r
-    Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");\r
-#endif\r
-    break;\r
-  }\r
-  return NULL;\r
-}\r
-\r
-void* WINAPI QERApp_CreateBrushHandle()\r
-{\r
-  return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();\r
-}\r
-\r
-void WINAPI QERApp_DeleteBrushHandle(void* vp)\r
-{\r
-  g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);\r
-}\r
-\r
-void WINAPI QERApp_CommitBrushHandleToMap(void* vp)\r
-{\r
-  g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);\r
-}\r
-\r
-void WINAPI QERApp_AddFace(void* vp, vec3_t v1, vec3_t v2, vec3_t v3)\r
-{\r
-  g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);\r
-}\r
-\r
-void WINAPI QERApp_DeleteSelection()\r
-{\r
-  Select_Delete();\r
-}\r
-\r
-void QERApp_GetCamera( vec3_t origin, vec3_t angles )\r
-{\r
-  VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->origin, origin );\r
-  VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->angles, angles );\r
-}\r
-\r
-void QERApp_SetCamera( vec3_t origin, vec3_t angles )\r
-{\r
-  VectorCopy( origin, g_pParentWnd->GetCamWnd()->Camera()->origin );\r
-  VectorCopy( angles, g_pParentWnd->GetCamWnd()->Camera()->angles );\r
-\r
-  Sys_UpdateWindows( W_ALL ); // specify \r
-  g_pParentWnd->OnTimer();\r
-}\r
-\r
-void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )\r
-{\r
-  GtkWidget *widget;\r
-\r
-  if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)\r
-    widget = g_pParentWnd->GetCamWnd()->m_pParent;\r
-  else\r
-    widget = g_pParentWnd->GetCamWnd()->GetWidget();\r
-\r
-  get_window_pos (widget, x, y);\r
-\r
-  *width = g_pParentWnd->GetCamWnd()->Camera()->width;\r
-  *height = g_pParentWnd->GetCamWnd()->Camera()->height;\r
-}\r
-\r
-//FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up\r
-bool g_bPlugWait = false;\r
-bool g_bPlugOK = false;\r
-int  g_nPlugCount = 0;\r
-\r
-void _PlugDone(bool b, int n)\r
-{\r
-  g_bPlugWait = false;\r
-  g_bPlugOK = b;\r
-  g_nPlugCount = n;\r
-}\r
-\r
-void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, char* pMsg)\r
-{\r
-  ShowInfoDialog(pMsg);\r
-  g_bPlugWait = true;\r
-  g_bPlugOK = false;\r
-  g_nPlugCount = 0;\r
-//  g_nPlugCount=nMax-1;\r
-  AcquirePath(nMax, &_PlugDone);\r
-\r
-  while (g_bPlugWait)\r
-    gtk_main_iteration ();\r
-\r
-  HideInfoDialog();\r
-\r
-  pData->m_nCount = 0;\r
-  pData->m_pVectors = NULL;\r
-\r
-  if (g_bPlugOK && g_nPlugCount > 0)\r
-  {\r
-    pData->m_nCount = g_nPlugCount;\r
-    pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));\r
-    vec3_t *pOut = pData->m_pVectors;\r
-    for (int i = 0; i < g_nPlugCount; i++)\r
-    {\r
-      memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));\r
-      pOut++;\r
-    }\r
-  }\r
-}\r
-\r
-//#define DBG_PAPI\r
-\r
-void CheckTexture(face_t *f)\r
-{\r
-  if (!f->d_texture)\r
-  {\r
-#ifdef DBG_PAPI\r
-    Sys_Printf("CheckTexture: requesting %s\n", f->texdef.name);\r
-#endif\r
-    f->pShader = QERApp_Shader_ForName (f->texdef.GetName());\r
-    f->pShader->IncRef();\r
-    f->d_texture = f->pShader->getTexture();\r
-  }\r
-}\r
-\r
-// expects pData->m_TextureName to be relative to "textures/"\r
-void WINAPI QERApp_AddFaceData(void* pv, _QERFaceData *pData)\r
-{\r
-#ifdef DBG_PAPI\r
-  Sys_Printf("FindBrushHandle...");\r
-#endif\r
-  brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-#ifdef DBG_PAPI\r
-  Sys_Printf("Done\n");\r
-#endif\r
-  if (pBrush != NULL)\r
-  {\r
-    face_t *f = Face_Alloc();\r
-    f->texdef = g_qeglobals.d_texturewin.texdef;\r
-    f->texdef.flags = pData->m_nFlags;\r
-    f->texdef.contents = pData->m_nContents;\r
-    f->texdef.value = pData->m_nValue;\r
-    f->texdef.SetName(pData->m_TextureName);\r
-    f->next = pBrush->brush_faces;\r
-    pBrush->brush_faces = f;\r
-    VectorCopy (pData->m_v1, f->planepts[0]);\r
-    VectorCopy (pData->m_v2, f->planepts[1]);\r
-    VectorCopy (pData->m_v3, f->planepts[2]);\r
-    // we might need to convert one way or the other if the input and the brush coordinates setting don't match\r
-    if (pData->m_bBPrimit == true)\r
-    {\r
-      f->brushprimit_texdef = pData->brushprimit_texdef;\r
-      if (!g_qeglobals.m_bBrushPrimitMode)\r
-      {\r
-        // before calling into the conversion, make sure we have a texture!\r
-        CheckTexture (f);\r
-#ifdef DBG_PAPI\r
-        Sys_Printf("BrushPrimitFaceToFace...");\r
-#endif\r
-\r
-        // convert BP to regular\r
-        BrushPrimitFaceToFace (f);\r
-#ifdef DBG_PAPI\r
-        Sys_Printf("Done\n");\r
-#endif\r
-      }\r
-    } else\r
-    {\r
-#ifdef _DEBUG\r
-      if (pData->m_bBPrimit != false)\r
-        Sys_FPrintf (SYS_WRN, "non-initialized pData->m_bBPrimit in QERApp_AddFaceData\n");\r
-#endif\r
-      f->texdef.rotate = pData->m_fRotate;\r
-      f->texdef.shift[0] = pData->m_fShift[0];\r
-      f->texdef.shift[1] = pData->m_fShift[1];\r
-      f->texdef.scale[0] = pData->m_fScale[0];\r
-      f->texdef.scale[1] = pData->m_fScale[1];\r
-      if (g_qeglobals.m_bBrushPrimitMode)\r
-      {\r
-        CheckTexture (f);\r
-#ifdef DBG_PAPI\r
-        Sys_Printf("FaceToBrushPrimitFace...");\r
-#endif\r
-\r
-        // convert regular to BP\r
-        FaceToBrushPrimitFace (f);\r
-#ifdef DBG_PAPI\r
-        Sys_Printf("Done\n");\r
-#endif\r
-      }\r
-    }\r
-    Sys_MarkMapModified();    // PGM\r
-  }\r
-}\r
-\r
-int WINAPI QERApp_GetFaceCount(void* pv)\r
-{\r
-  int n = 0;\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
-    {\r
-      n++;\r
-    }\r
-  }\r
-  return n;\r
-}\r
-\r
-_QERFaceData* WINAPI QERApp_GetFaceData(void* pv, int nFaceIndex)\r
-{\r
-  static _QERFaceData face;\r
-  int n = 0;\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-\r
-  if (pBrush != NULL)\r
-  {\r
-    for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
-    {\r
-\r
-#ifdef _DEBUG\r
-      if (!pBrush->brush_faces)\r
-      {\r
-        Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );\r
-        return NULL;\r
-      }\r
-#endif\r
-\r
-      if (n == nFaceIndex)\r
-      {\r
-        face.m_nContents = f->texdef.contents;\r
-        face.m_nFlags = f->texdef.flags;\r
-        face.m_nValue = f->texdef.value;\r
-        if (g_qeglobals.m_bBrushPrimitMode)\r
-        {\r
-          //++timo NOTE: we may want to convert back to old format for backward compatibility with some old plugins?\r
-          face.m_bBPrimit = true;\r
-          face.brushprimit_texdef = f->brushprimit_texdef;\r
-        } else\r
-        {\r
-          face.m_fRotate = f->texdef.rotate;\r
-          face.m_fScale[0] = f->texdef.scale[0];\r
-          face.m_fScale[1] = f->texdef.scale[1];\r
-          face.m_fShift[0] = f->texdef.shift[0];\r
-          face.m_fShift[1] = f->texdef.shift[1];\r
-        }\r
-        strcpy(face.m_TextureName, f->texdef.GetName());\r
-        VectorCopy(f->planepts[0], face.m_v1);\r
-        VectorCopy(f->planepts[1], face.m_v2);\r
-        VectorCopy(f->planepts[2], face.m_v3);\r
-        return &face;\r
-      }\r
-      n++;\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-void WINAPI QERApp_SetFaceData(void* pv, int nFaceIndex, _QERFaceData *pData)\r
-{\r
-  int n = 0;\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-\r
-  if (pBrush != NULL)\r
-  {\r
-    for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
-    {\r
-      if (n == nFaceIndex)\r
-      {\r
-        f->texdef.flags = pData->m_nFlags;\r
-        f->texdef.contents = pData->m_nContents;\r
-        f->texdef.value = pData->m_nValue;\r
-        f->texdef.rotate = pData->m_fRotate;\r
-        f->texdef.shift[0] = pData->m_fShift[0];\r
-        f->texdef.shift[1] = pData->m_fShift[1];\r
-        f->texdef.scale[0] = pData->m_fScale[0];\r
-        f->texdef.scale[1] = pData->m_fScale[1];\r
-        //strcpy(f->texdef.name, pData->m_TextureName);\r
-        f->texdef.SetName(pData->m_TextureName);\r
-        VectorCopy(pData->m_v1, f->planepts[0]);\r
-        VectorCopy(pData->m_v2, f->planepts[1]);\r
-        VectorCopy(pData->m_v3, f->planepts[2]);\r
-        Sys_MarkMapModified();    // PGM\r
-        return;           // PGM\r
-      }\r
-      n++;\r
-    }\r
-  }\r
-}\r
-\r
-void WINAPI QERApp_DeleteFace(void* pv, int nFaceIndex)\r
-{\r
-  int n = 0;\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    face_t *pPrev = pBrush->brush_faces;\r
-    for (face_t *f = pBrush->brush_faces; f; f = f->next)\r
-    {\r
-      if (n == nFaceIndex)\r
-      {\r
-        pPrev->next = f->next;\r
-        Face_Free (f);\r
-        Sys_MarkMapModified();    // PGM\r
-        return;\r
-      }\r
-      n++;\r
-      pPrev = f;\r
-    }\r
-  }\r
-}\r
-\r
-//==========\r
-//PGM\r
-void WINAPI QERApp_BuildBrush (void* pv)\r
-{\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    Brush_Build(pBrush);\r
-    Sys_UpdateWindows(W_ALL);\r
-  }\r
-}\r
-\r
-//Timo : another version with bConvert flag\r
-//++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush\r
-void WINAPI QERApp_BuildBrush2 (void* pv, int bConvert)\r
-{\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    Brush_Build( pBrush, true, true, bConvert );\r
-    Sys_UpdateWindows(W_ALL);\r
-  }\r
-}\r
-\r
-void WINAPI QERApp_SelectBrush (void* pv)\r
-{\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    Select_Brush(pBrush, false);\r
-    Sys_UpdateWindows(W_ALL);\r
-  }\r
-\r
-}\r
-\r
-void WINAPI QERApp_DeselectBrush (void* pv)\r
-{\r
-  // FIXME - implement this!\r
-}\r
-\r
-void WINAPI QERApp_ResetPlugins()\r
-{\r
-  g_pParentWnd->OnPluginsRefresh();\r
-}\r
-\r
-void WINAPI QERApp_DeselectAllBrushes ()\r
-{\r
-  Select_Deselect();\r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-//PGM\r
-//==========\r
-\r
-void WINAPI QERApp_TextureBrush(void* pv, char* pName)\r
-{\r
-  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
-  if (pBrush != NULL)\r
-  {\r
-    for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
-    {\r
-      //strcpy(f->texdef.name, pName);\r
-      f->texdef.SetName(pName);\r
-    }\r
-    Sys_MarkMapModified();    // PGM\r
-  }\r
-}\r
-\r
-int WINAPI QERApp_SelectedBrushCount()\r
-{\r
-  int n = 0;\r
-  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
-  {\r
-    n++;\r
-  }\r
-  return n;\r
-}\r
-\r
-int WINAPI QERApp_ActiveBrushCount()\r
-{\r
-  int n = 0;\r
-  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
-  {\r
-    n++;\r
-  }\r
-  return n;\r
-}\r
-\r
-int WINAPI QERApp_AllocateSelectedBrushHandles()\r
-{\r
-  int n = 0;\r
-  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
-  {\r
-    n++;\r
-    g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);\r
-  }\r
-  return n;\r
-}\r
-\r
-int WINAPI QERApp_AllocateActiveBrushHandles()\r
-{\r
-  int n = 0;\r
-  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
-  {\r
-    n++;\r
-    g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);\r
-  }\r
-  return n;\r
-}\r
-\r
-void WINAPI QERApp_ReleaseSelectedBrushHandles()\r
-{\r
-  g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();\r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-void WINAPI QERApp_ReleaseActiveBrushHandles()\r
-{\r
-  g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();\r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-void* WINAPI QERApp_GetActiveBrushHandle(int nIndex)\r
-{\r
-  if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())\r
-  {\r
-    return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));\r
-  }\r
-  return NULL;\r
-}\r
-\r
-void* WINAPI QERApp_GetSelectedBrushHandle(int nIndex)\r
-{\r
-  if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())\r
-  {\r
-    return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));\r
-  }\r
-  return NULL;\r
-}\r
-\r
-int WINAPI QERApp_TextureCount()\r
-{\r
-  //++timo TODO: replace by QERApp_GetActiveShaderCount and verify\r
-  Texture_StartPos ();\r
-  int x, y;\r
-  int n = 0;\r
-  while (1)\r
-  {\r
-    IShader *pShader = Texture_NextPos (&x, &y);\r
-    if (!pShader)\r
-      break;\r
-    n++;\r
-  }\r
-  return n;\r
-}\r
-\r
-char* WINAPI QERApp_GetTexture(int nIndex)\r
-{\r
-  //++timo TODO: replace by QERApp_ActiveShader_ForIndex\r
-  // these funcs would end up being provided for backward compatibility\r
-  static char name[QER_MAX_NAMELEN];\r
-  Texture_StartPos ();\r
-  int x, y;\r
-  int n = 0;\r
-  while (1)\r
-  {\r
-    IShader *pShader = Texture_NextPos (&x, &y);\r
-    if (!pShader)\r
-      break;\r
-    if (n == nIndex)\r
-    {\r
-      strcpy(name, pShader->getName());\r
-      return name;\r
-    }\r
-    n++;\r
-  }\r
-  return NULL;\r
-}\r
-\r
-char* WINAPI QERApp_GetCurrentTexture()\r
-{\r
-  static char current_tex[1024];\r
-  strcpy(current_tex,g_qeglobals.d_texturewin.texdef.GetName());\r
-  return current_tex;\r
-}\r
-\r
-void WINAPI QERApp_SetCurrentTexture(char* strName)\r
-{\r
-  //++timo hu ?? tex is not initialized ?? can be any value ..\r
-  texdef_t tex;\r
-  //++timo added a brushprimit_texdef ..\r
-  // smthg to be done here\r
-  brushprimit_texdef_t brushprimit_tex;\r
-  //strcpy(tex.name, strName);\r
-  tex.SetName(strName);\r
-  Texture_SetTexture(&tex,&brushprimit_tex);\r
-}\r
-\r
-int WINAPI QERApp_GetEClassCount()\r
-{\r
-  int n = 0;\r
-  for (eclass_t *e = eclass ; e ; e = e->next)\r
-  {\r
-    n++;\r
-  }\r
-  return n;\r
-}\r
-\r
-char* WINAPI QERApp_GetEClass(int nIndex)\r
-{\r
-  int n = 0;\r
-  for (eclass_t *e = eclass ; e ; e = e->next)\r
-  {\r
-    if (n == nIndex)\r
-    {\r
-      return e->name;\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-// v1.70 code\r
-// world_entity holds the worldspawn and is indexed as 0\r
-// other entities are in the entities doubly linked list\r
-// QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]\r
-int WINAPI QERApp_GetEntityCount()\r
-{\r
-  int n = 1;\r
-  for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)\r
-  {\r
-    n++;\r
-  }\r
-  return n;\r
-}\r
-\r
-// We don't store entities in CPtrArray, we need to walk the list\r
-void* WINAPI QERApp_GetEntityHandle(int nIndex)\r
-{\r
-  if (nIndex==0)\r
-    // looks for the worldspawn\r
-    return static_cast<void*>(world_entity);\r
-  entity_t *pe = &entities;\r
-  int n = 0;\r
-  while ( n < nIndex )\r
-  {\r
-    pe = pe->next;\r
-    n++;\r
-  }\r
-  return static_cast<void*>(pe);\r
-}\r
-\r
-epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )\r
-{\r
-  epair_t *e = (epair_t*)qmalloc (sizeof(*e));\r
-  e->key = (char*)qmalloc(strlen(key)+1);\r
-  strcpy (e->key, key);\r
-  e->value = (char*)qmalloc(strlen(val)+1);\r
-  strcpy (e->value, val);\r
-  return e;\r
-}\r
-\r
-/*\r
-IEpair* WINAPI QERApp_IEpairForEntityHandle(void *vp)\r
-{\r
-  entity_t *pe = static_cast<entity_t *>(vp);\r
-  CEpairsWrapper *pEp = new CEpairsWrapper(pe);\r
-  pEp->IncRef();\r
-  return pEp;\r
-}\r
-\r
-IEpair* WINAPI QERApp_IEpairForProjectKeys()   \r
-{\r
-  CEpairsWrapper *pEp = new CEpairsWrapper(g_qeglobals.d_project_entity);\r
-  pEp->IncRef();\r
-  return pEp;\r
-}\r
-*/\r
-\r
-int WINAPI QERApp_AllocateEntityBrushHandles(void* vp)\r
-{\r
-  entity_t *pe = static_cast<entity_t *>(vp);\r
-  int n = 0;\r
-  if (!pe->brushes.onext)\r
-    return 0;\r
-  g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();\r
-  for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)\r
-  {\r
-    n++;\r
-    g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);\r
-  }\r
-  return n;\r
-}\r
-\r
-void WINAPI QERApp_ReleaseEntityBrushHandles()\r
-{\r
-  g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();\r
-}\r
-\r
-void* WINAPI QERApp_GetEntityBrushHandle(int nIndex)\r
-{\r
-  if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())\r
-    return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);\r
-  return NULL;\r
-}\r
-\r
-// FIXME TTimo that entity handles thing sucks .. we should get rid of it ..\r
-\r
-void* WINAPI QERApp_CreateEntityHandle()\r
-{\r
-  entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));\r
-  pe->brushes.onext = pe->brushes.oprev = &pe->brushes;\r
-  g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<void*>(pe));\r
-  return static_cast<void*>(pe);\r
-}\r
-\r
-// the vpBrush needs to be in m_BrushHandles\r
-//++timo we don't have allocation nor storage for vpEntity, no checks for this one\r
-void WINAPI QERApp_CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)\r
-{\r
-  g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);\r
-  return;\r
-}\r
-\r
-const char* QERApp_ReadProjectKey(const char* key)\r
-{\r
-  return ValueForKey(g_qeglobals.d_project_entity, key);\r
-}\r
-\r
-#ifdef USEPLUGINENTITIES\r
-\r
-int WINAPI QERApp_ScanFileForEClass(char *filename )\r
-{\r
-  // set single class parsing\r
-  parsing_single = true;\r
-  Eclass_ScanFile(filename);\r
-  if (eclass_found)\r
-  {\r
-    eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;\r
-    return 1;\r
-  }\r
-  return 0;\r
-}\r
-#endif // USEPLUGINENTITIES\r
-\r
-// the vpBrush needs to be in m_BrushHandles\r
-//++timo add a debug check to see if we found the brush handle\r
-// NOTE : seems there's no way to check vpEntity is valid .. this is dangerous\r
-// links the brush to its entity, everything else is done when commiting the entity to the map\r
-void CPlugInManager::CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)\r
-{\r
-  brush_t* pb;\r
-  entity_t* pe;\r
-  for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)\r
-  {\r
-    if (vpBrush == m_BrushHandles.GetAt(i))\r
-    {\r
-      m_BrushHandles.RemoveAt(i);\r
-      pb = reinterpret_cast<brush_t*>(vpBrush);\r
-      pe = reinterpret_cast<entity_t *>(vpEntity);\r
-      Entity_LinkBrush (pe, pb);\r
-    }\r
-  }\r
-  Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-// the vpEntity must be in m_EntityHandles\r
-void WINAPI QERApp_CommitEntityHandleToMap(void* vpEntity)\r
-{\r
-  g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);\r
-  return;\r
-}\r
-\r
-int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )\r
-{\r
-  int nSize = vfsLoadFile(pLocation, buffer, 0);\r
-  return nSize;\r
-}\r
-\r
-char * WINAPI QERApp_ExpandReletivePath (char *p)\r
-{\r
-  return ExpandReletivePath(p);\r
-}\r
-\r
-qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)\r
-{\r
-  // if the texture is not loaded yet, this call will get it loaded\r
-  // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_xxxBase GL context\r
-  // the plugin may set the GL context to whatever he likes, but then load would fail\r
-  // NOTE: is context switching time-consuming? then maybe the plugin could handle the context\r
-  // switch and only add a sanity check in debug mode here\r
-  // read current context\r
-  gtk_glwidget_make_current (g_qeglobals_gui.d_glBase);\r
-\r
-  //++timo debugging\r
-  Sys_Printf("WARNING: QERApp_Texture_ForName ... don't call that!!\n");\r
-  qtexture_t* qtex = QERApp_Texture_ForName2( name );\r
-  return qtex;\r
-}\r
-\r
-char* QERApp_Token()\r
-{\r
-  return token;\r
-}\r
-\r
-int QERApp_ScriptLine()\r
-{\r
-  return scriptline;\r
-}\r
-\r
-// we save the map and return the name .. either .map or .reg to support region compiling\r
-char* QERApp_GetMapName()\r
-{\r
-  static char name[PATH_MAX];\r
-  SaveWithRegion (name);\r
-  return name;\r
-}\r
-\r
-void CPlugInManager::CommitEntityHandleToMap(void* vpEntity)\r
-{\r
-  entity_t *pe;\r
-  eclass_t *e;\r
-  brush_t   *b;\r
-  vec3_t mins,maxs;\r
-  bool has_brushes;\r
-  for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )\r
-  {\r
-    if (vpEntity == m_EntityHandles.GetAt(i))\r
-    {\r
-      m_EntityHandles.RemoveAt(i);\r
-      pe = reinterpret_cast<entity_t*>(vpEntity);\r
-      // fill additional fields\r
-      // straight copy from Entity_Parse\r
-      // entity_t::origin\r
-      GetVectorForKey (pe, "origin", pe->origin);\r
-      // entity_t::eclass\r
-      if (pe->brushes.onext == &pe->brushes)\r
-        has_brushes = false;\r
-      else\r
-        has_brushes = true;\r
-      e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);\r
-      pe->eclass = e;\r
-      // fixedsize\r
-      if (e->fixedsize)\r
-      {\r
-        if (pe->brushes.onext != &pe->brushes)\r
-        {\r
-          Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");\r
-        }\r
-        // create a custom brush\r
-        VectorAdd(e->mins, pe->origin, mins);\r
-        VectorAdd(e->maxs, pe->origin, maxs);\r
-/*\r
-        float a = 0;\r
-        if (e->nShowFlags & ECLASS_MISCMODEL)\r
-        {\r
-          char* p = ValueForKey(pe, "model");\r
-          if (p != NULL && strlen(p) > 0)\r
-          {\r
-            vec3_t vMin, vMax;\r
-            a = FloatForKey (pe, "angle");\r
-            if (GetCachedModel(pe, p, vMin, vMax))\r
-            {\r
-              // create a custom brush\r
-              VectorAdd (pe->md3Class->mins, pe->origin, mins);\r
-              VectorAdd (pe->md3Class->maxs, pe->origin, maxs);\r
-            }\r
-          }\r
-        }\r
-*/\r
-        b = Brush_Create (mins, maxs, &e->texdef);\r
-/*\r
-        if (a)\r
-        {\r
-          vec3_t vAngle;\r
-          vAngle[0] = vAngle[1] = 0;\r
-          vAngle[2] = a;\r
-          Brush_Rotate(b, vAngle, pe->origin, false);\r
-        }\r
-*/\r
-        b->owner = pe;\r
-\r
-        b->onext = pe->brushes.onext;\r
-        b->oprev = &pe->brushes;\r
-        pe->brushes.onext->oprev = b;\r
-        pe->brushes.onext = b;\r
-      } else\r
-      { // brush entity\r
-        if (pe->brushes.next == &pe->brushes)\r
-          Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");\r
-      }\r
-\r
-      // add brushes to the active brushes list\r
-      // and build them along the way\r
-      for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)\r
-      {\r
-        // convert between old brushes and brush primitive\r
-        if (g_qeglobals.m_bBrushPrimitMode)\r
-        {\r
-          // we only filled the shift scale rot fields, needs conversion\r
-          Brush_Build( b, true, true, true );\r
-        } else\r
-        {\r
-          // we are using old brushes\r
-          Brush_Build( b );\r
-        }\r
-        b->next = active_brushes.next;\r
-        active_brushes.next->prev = b;\r
-        b->prev = &active_brushes;\r
-        active_brushes.next = b;\r
-      }\r
-\r
-      // handle worldspawn entities\r
-      // if worldspawn has no brushes, use the new one\r
-      if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))\r
-      {\r
-        if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )\r
-        {\r
-          // worldspawn already has brushes\r
-          Sys_Printf ("Commiting worldspawn as func_group\n");\r
-          SetKeyValue(pe, "classname", "func_group");\r
-          // add the entity to the end of the entity list\r
-          pe->next = &entities;\r
-          pe->prev = entities.prev;\r
-          entities.prev->next = pe;\r
-          entities.prev = pe;\r
-          g_qeglobals.d_num_entities++;\r
-        } else\r
-        {\r
-          // there's a worldspawn with no brushes, we assume the map is empty\r
-          if ( world_entity )\r
-          {\r
-            Entity_Free( world_entity );\r
-            world_entity = pe;\r
-          } else\r
-            Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");\r
-        }\r
-      } else\r
-      {\r
-        // add the entity to the end of the entity list\r
-        pe->next = &entities;\r
-        pe->prev = entities.prev;\r
-        entities.prev->next = pe;\r
-        entities.prev = pe;\r
-        g_qeglobals.d_num_entities++;\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)\r
-{\r
-  g_bScreenUpdates = bScreenUpdates; \r
-}\r
-\r
-texturewin_t* QERApp_QeglobalsTexturewin()\r
-{\r
-  return &g_qeglobals.d_texturewin;\r
-}\r
-\r
-texdef_t* QERApp_QeglobalsSavedinfo_SIInc()\r
-{\r
-  return &g_qeglobals.d_savedinfo.m_SIIncrement;\r
-}\r
-\r
-patchMesh_t* QERApp_GetSelectedPatch( )\r
-{\r
-  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
-  {\r
-    if (pb->patchBrush)\r
-    {\r
-      return pb->pPatch;\r
-    }\r
-  }\r
-#ifdef _DEBUG\r
-  Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");\r
-#endif\r
-  return NULL;\r
-}\r
-\r
-const char* WINAPI QERApp_GetGamePath()\r
-{\r
-  return g_pGameDescription->mEnginePath.GetBuffer();\r
-}\r
-\r
-/*!\r
-\todo the name of this API should prolly be changed\r
-would also need to prompt g_strAppPath / g_strGameToolsPath independently?\r
-*/\r
-// SPoG\r
-// changed g_strGameToolsPath to g_strAppPath\r
-const char* WINAPI QERApp_GetQERPath()\r
-{\r
-  return g_strAppPath.GetBuffer();\r
-}\r
-\r
-const char* WINAPI QERApp_GetGameFile()\r
-{\r
-  // FIXME: Arnout: temp solution, need proper 'which game is this' indicator or a different solution for plugins/modules\r
-  return g_pGameDescription->mGameFile.GetBuffer();\r
-}\r
-\r
-// patches in/out -----------------------------------\r
-int WINAPI QERApp_AllocateActivePatchHandles()\r
-{\r
-  return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();\r
-}\r
-\r
-// Grid Size\r
-float QERApp_QeglobalsGetGridSize()\r
-{\r
-  return g_qeglobals.d_gridsize;\r
-}\r
-\r
-int CPlugInManager::AllocateActivePatchHandles()\r
-{\r
-  int n = 0;\r
-  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
-  {\r
-    if (pb->patchBrush)\r
-    {\r
-      n++;\r
-      m_PatchesHandles.Add(pb);\r
-    }\r
-  }\r
-  return n;\r
-}\r
-\r
-int WINAPI QERApp_AllocateSelectedPatchHandles()\r
-{\r
-  return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();\r
-}\r
-\r
-int CPlugInManager::AllocateSelectedPatchHandles()\r
-{\r
-  int n = 0;\r
-  // change mode\r
-  PatchesMode = ESelectedPatches;\r
-  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
-  {\r
-    if (pb->patchBrush)\r
-    {\r
-      n++;\r
-      m_PatchesHandles.Add(pb);\r
-    }\r
-  }\r
-  return n;\r
-}\r
-\r
-void WINAPI QERApp_ReleasePatchHandles()\r
-{\r
-  g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();\r
-}\r
-\r
-patchMesh_t* WINAPI QERApp_GetPatchData(int index)\r
-{\r
-  static patchMesh_t patch;\r
-  patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
-  if (pPatch)\r
-  {\r
-    memcpy( &patch, pPatch, sizeof(patchMesh_t) );\r
-    return &patch;\r
-  }\r
-  return NULL;\r
-}\r
-\r
-patchMesh_t* WINAPI QERApp_GetPatchHandle(int index)\r
-{\r
-  return g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
-}\r
-\r
-void WINAPI QERApp_DeletePatch(int index)\r
-{\r
-  patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
-  if (pPatch)\r
-  {\r
-    brush_t *pb = pPatch->pSymbiot;\r
-    Patch_Delete( pPatch );\r
-    if (pb)\r
-      Brush_Free( pb );\r
-  }\r
-#ifdef _DEBUG\r
-  Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");\r
-#endif\r
-}\r
-\r
-int WINAPI QERApp_CreatePatchHandle()\r
-{\r
-  return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();\r
-}\r
-\r
-int CPlugInManager::CreatePatchHandle()\r
-{\r
-  // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure\r
-  patchMesh_t *pPatch = MakeNewPatch();\r
-  m_PluginPatches.Add( pPatch );\r
-  // change mode\r
-  PatchesMode = EAllocatedPatches;\r
-  return m_PluginPatches.GetSize()-1;\r
-}\r
-\r
-void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)\r
-{\r
-#ifdef DBG_PAPI\r
-  Sys_Printf ("QERApp_CommitPatchHandleToMap %i..", index);\r
-#endif\r
-  g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);\r
-#ifdef DBG_PAPI\r
-  Sys_Printf ("Done\n");\r
-#endif\r
-}\r
-\r
-void WINAPI QERApp_CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void* vpEntity)\r
-{\r
-#ifdef DBG_PAPI\r
-  Sys_Printf ("QERApp_CommitPatchHandleToEntity %i..", index);\r
-#endif\r
-  g_pParentWnd->GetPlugInMgr().CommitPatchHandleToEntity(index, pMesh, texName, vpEntity);\r
-#ifdef DBG_PAPI\r
-  Sys_Printf ("Done\n");\r
-#endif\r
-}\r
-\r
-void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)\r
-{\r
-  if (PatchesMode==EAllocatedPatches)\r
-  {\r
-    patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );\r
-    memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );\r
-    // patch texturing, if none given use current texture\r
-    if (texName)\r
-      pPatch->pShader = QERApp_Shader_ForName (texName);\r
-    else\r
-      pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());\r
-    pPatch->d_texture = pPatch->pShader->getTexture();\r
-    pPatch->pShader->IncRef();\r
-    g_bScreenUpdates = false;\r
-    // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build\r
-    brush_t *pb = AddBrushForPatch( pPatch, true );\r
-    Select_Brush( pb );\r
-    g_bScreenUpdates = true;\r
-    Sys_UpdateWindows(W_ALL);\r
-  } else\r
-  {\r
-    brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );\r
-    patchMesh_t *pPatch = pBrush->pPatch;\r
-    pPatch->width = pMesh->width;\r
-    pPatch->height = pMesh->height;\r
-    pPatch->contents = pMesh->contents;\r
-    pPatch->flags = pMesh->flags;\r
-    pPatch->value = pMesh->value;\r
-    pPatch->type = pMesh->type;\r
-    memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );\r
-    pPatch->bDirty = true;\r
-  }\r
-}\r
-\r
-void CPlugInManager::CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity)\r
-{\r
-  entity_t* pe = reinterpret_cast<entity_t *>(vpEntity);\r
-\r
-  if (PatchesMode==EAllocatedPatches)\r
-  {\r
-    patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );\r
-    memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );\r
-    // patch texturing, if none given use current texture\r
-    if (texName)\r
-      pPatch->pShader = QERApp_Shader_ForName (texName);\r
-    else\r
-      pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());\r
-    pPatch->d_texture = pPatch->pShader->getTexture();\r
-    pPatch->pShader->IncRef();\r
-    g_bScreenUpdates = false;\r
-    brush_t *pb = AddBrushForPatch( pPatch, false );  // false, sp have to do the brush building/entity linking ourself\r
-    Brush_AddToList (pb, &active_brushes);\r
-    Entity_LinkBrush (pe, pb);\r
-    Brush_Build( pb );\r
-    g_bScreenUpdates = true;\r
-    Sys_UpdateWindows(W_ALL);\r
-  } else\r
-  {\r
-    brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );\r
-    patchMesh_t *pPatch = pBrush->pPatch;\r
-    pPatch->width = pMesh->width;\r
-    pPatch->height = pMesh->height;\r
-    pPatch->contents = pMesh->contents;\r
-    pPatch->flags = pMesh->flags;\r
-    pPatch->value = pMesh->value;\r
-    pPatch->type = pMesh->type;\r
-    memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );\r
-    pPatch->bDirty = true;\r
-  }\r
-}\r
-\r
-#if 0\r
-\r
-#if defined (__linux__) || defined (__APPLE__)\r
-  #include <gdk/gdkx.h>\r
-\r
-XVisualInfo* QEX_ChooseVisual (bool zbuffer)\r
-{\r
-  int attrlist_z[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0};\r
-  int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0};\r
-  XVisualInfo *vi;\r
-  Display *dpy;\r
-\r
-  dpy = GDK_DISPLAY();\r
-  if (dpy == NULL)\r
-    Error ("OpenGL fatal error: Cannot get display.\n");\r
-  vi = qglXChooseVisual(dpy, DefaultScreen(dpy), zbuffer ? attrlist_z : attrlist);\r
-  if (vi == NULL)\r
-    Error ("OpenGL fatal error: glXChooseVisual failed.\n");\r
-\r
-  return vi;\r
-}\r
-#endif\r
-\r
-#endif\r
-\r
-/*!\r
-\todo FIXME TTimo broken most likely\r
-actually .. that's not enough, you have to go down for the game pack specific?\r
-*/\r
-const char* WINAPI QERApp_ProfileGetDirectory ()\r
-{\r
-  return g_strTempPath;\r
-}\r
-\r
-GtkWidget* WINAPI QERApp_GetQeGlobalsGLWidget ()\r
-{\r
-  return g_qeglobals_gui.d_glBase;\r
-}\r
-\r
-qboolean WINAPI BrushPrimitMode ()\r
-{\r
-  return g_qeglobals.m_bBrushPrimitMode;\r
-}\r
-\r
-brush_t* WINAPI QERApp_ActiveBrushes()\r
-{\r
-  return &active_brushes;\r
-}\r
-\r
-brush_t* WINAPI QERApp_SelectedBrushes()\r
-{\r
-  return &selected_brushes;\r
-}\r
-\r
-brush_t* WINAPI QERApp_FilteredBrushes()\r
-{\r
-  return &filtered_brushes;\r
-}\r
-\r
-CPtrArray* WINAPI QERApp_LstSkinCache()\r
-{\r
-  return &g_lstSkinCache;\r
-}\r
-\r
-qtexture_t** WINAPI QERApp_QTextures()\r
-{\r
-  return &g_qeglobals.d_qtextures;\r
-}\r
-\r
-GHashTable* WINAPI QERApp_QTexmap()\r
-{\r
-  return g_qeglobals.d_qtexmap;\r
-}\r
-\r
-// a simplified version of Texture_SetTexture\r
-void WINAPI QERApp_Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef)\r
-{\r
-  Texture_SetTexture (texdef, brushprimit_texdef);\r
-}\r
-\r
-void QERApp_LoadImage (const char *name, unsigned char **pic, int *width, int *height)\r
-{\r
-  g_ImageManager.LoadImage(name, pic, width, height);\r
-}\r
-\r
-unsigned long QERApp_GetTickCount()\r
-{\r
-#ifdef _WIN32\r
-       return GetTickCount();\r
-#else\r
-  struct timeval      tp;\r
-  struct timezone     tzp;\r
-  static int          basetime=0;\r
-\r
-  gettimeofday(&tp, &tzp);\r
-  if (!basetime)\r
-    basetime = tp.tv_sec;\r
-  return (tp.tv_sec-basetime) + tp.tv_usec/1000;       \r
-#endif\r
-}\r
-\r
-bool CSynapseClientRadiant::RequestAPI(APIDescriptor_t *pAPI)\r
-{\r
-  if (!strcmp(pAPI->major_name, RADIANT_MAJOR))\r
-  {\r
-    _QERFuncTable_1* pTable= static_cast<_QERFuncTable_1*>(pAPI->mpTable);\r
-    pTable->m_pfnCreateBrush = &QERApp_CreateBrush;\r
-    pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;\r
-    pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;\r
-    pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;\r
-    pTable->m_pfnAddFace = &QERApp_AddFace;\r
-    pTable->m_pfnAddFaceData = &QERApp_AddFaceData;\r
-    pTable->m_pfnGetFaceData = &QERApp_GetFaceData;\r
-    pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;\r
-    pTable->m_pfnSetFaceData = &QERApp_SetFaceData;\r
-    pTable->m_pfnDeleteFace = &QERApp_DeleteFace;\r
-    pTable->m_pfnTextureBrush = &QERApp_TextureBrush;\r
-    pTable->m_pfnBuildBrush = &QERApp_BuildBrush;           // PGM\r
-    pTable->m_pfnSelectBrush = &QERApp_SelectBrush;         // PGM\r
-    pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush;       // PGM\r
-    pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes;   // PGM\r
-    pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;\r
-    pTable->m_pfnGetPoints = &QERApp_GetPoints;\r
-    pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;\r
-    pTable->m_pfnAllocateSelectedBrushHandles  = &QERApp_AllocateSelectedBrushHandles;\r
-    pTable->m_pfnReleaseSelectedBrushHandles  = &QERApp_ReleaseSelectedBrushHandles;\r
-    pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;\r
-    pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;\r
-    pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;\r
-    pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;\r
-    pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;\r
-    pTable->m_pfnTextureCount = &QERApp_TextureCount;\r
-    pTable->m_pfnGetTexture = &QERApp_GetTexture;\r
-    pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;\r
-    pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;\r
-    pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;\r
-    pTable->m_pfnGetEClass = &QERApp_GetEClass;\r
-    pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;\r
-    pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;\r
-    pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;\r
-    pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;\r
-    pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;\r
-    pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;\r
-    pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;\r
-    pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;\r
-    pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;\r
-    pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;\r
-    pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;\r
-    pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;\r
-    pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;\r
-       pTable->m_pfnGetDispatchParams = &QERApp_GetDispatchParams;\r
-//    pTable->m_pfnRequestInterface = &QERApp_RequestInterface;\r
-    pTable->m_pfnError = &Error;\r
-    pTable->m_pfnLoadFile = &QERApp_LoadFile;\r
-    pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;\r
-    pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;\r
-    pTable->m_pfnHasShader = QERApp_HasShader;\r
-    pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;\r
-    pTable->m_pfnGetGamePath = &QERApp_GetGamePath;\r
-    pTable->m_pfnGetQERPath = &QERApp_GetQERPath;\r
-    pTable->m_pfnGetGameFile = &QERApp_GetGameFile;\r
-    pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;\r
-    pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;\r
-    pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;\r
-    pTable->m_pfnGetPatchData = &QERApp_GetPatchData;\r
-    pTable->m_pfnGetPatchHandle = &QERApp_GetPatchHandle;\r
-    pTable->m_pfnDeletePatch = &QERApp_DeletePatch;\r
-    pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;\r
-    pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;\r
-    pTable->m_pfnLoadImage = &QERApp_LoadImage;\r
-    pTable->m_pfnMessageBox = &gtk_MessageBox;\r
-    pTable->m_pfnFileDialog = &file_dialog;\r
-    pTable->m_pfnColorDialog = &color_dialog;\r
-    pTable->m_pfnDirDialog = &dir_dialog;\r
-    pTable->m_pfnLoadBitmap = &load_plugin_bitmap;\r
-    pTable->m_pfnProfileGetDirectory = &QERApp_ProfileGetDirectory;\r
-    pTable->m_pfnProfileSaveInt = &profile_save_int;\r
-    pTable->m_pfnProfileSaveString = &profile_save_string;\r
-    pTable->m_pfnProfileLoadInt = &profile_load_int;\r
-    pTable->m_pfnProfileLoadString = &profile_load_string;\r
-    pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;\r
-    pTable->m_pfnSysPrintf = &Sys_Printf;\r
-    pTable->m_pfnSysFPrintf = &Sys_FPrintf;\r
-    pTable->m_pfnSysBeginWait = &Sys_BeginWait;\r
-    pTable->m_pfnSysEndWait = &Sys_EndWait;\r
-    pTable->m_pfnSys_SetTitle = &Sys_SetTitle;\r
-    pTable->m_pfnSysBeep = &Sys_Beep;\r
-    pTable->m_pfnSys_Status = &Sys_Status;\r
-    pTable->m_pfnMapFree = &Map_Free;\r
-    pTable->m_pfnMapNew = &Map_New;\r
-    pTable->m_pfnMapBuildBrushData = &Map_BuildBrushData;\r
-    pTable->m_pfnMap_IsBrushFiltered = &Map_IsBrushFiltered;\r
-    pTable->m_pfnMapStartPosition = &Map_StartPosition;\r
-    pTable->m_pfnMapRegionOff = &Map_RegionOff;\r
-    pTable->m_pfnSetBuildWindingsNoTexBuild = &Brush_SetBuildWindingsNoTexBuild;\r
-    pTable->m_pfnPointFileClear = &Pointfile_Clear;\r
-    pTable->m_pfnCSG_MakeHollow = &CSG_MakeHollow;\r
-    pTable->m_pfnRegionSpawnPoint = &Region_SpawnPoint;\r
-    pTable->m_pfnQGetTickCount = &QERApp_GetTickCount;\r
-    pTable->m_pfnGetModelCache = &GetModelCache;\r
-    pTable->m_pfnGetFileTypeRegistry = &GetFileTypeRegistry;\r
-    pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;\r
-    pTable->m_pfnGetMapName = &QERApp_GetMapName;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, SCRIPLIB_MAJOR))\r
-  {\r
-    _QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pAPI->mpTable);\r
-    pScripLibTable->m_pfnGetToken = &GetToken;\r
-    pScripLibTable->m_pfnGetTokenExtra = &GetTokenExtra;\r
-    pScripLibTable->m_pfnToken = &QERApp_Token;\r
-    pScripLibTable->m_pfnUnGetToken = &UngetToken;\r
-    pScripLibTable->m_pfnStartTokenParsing = &StartTokenParsing;\r
-    pScripLibTable->m_pfnScriptLine = &QERApp_ScriptLine;\r
-    pScripLibTable->m_pfnTokenAvailable = &TokenAvailable;\r
-    pScripLibTable->m_pfnCOM_Parse = &COM_Parse;\r
-    pScripLibTable->m_pfnGet_COM_Token = &Get_COM_Token;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, BRUSH_MAJOR))\r
-  {\r
-    _QERBrushTable *pBrushTable = static_cast<_QERBrushTable *>(pAPI->mpTable);\r
-    pBrushTable->m_pfnBP_MessageBox = &BP_MessageBox;\r
-    pBrushTable->m_pfnBrush_AddToList = &Brush_AddToList;\r
-    pBrushTable->m_pfnBrush_Build = &Brush_Build;\r
-    pBrushTable->m_pfnBrush_Create = &Brush_Create;\r
-    pBrushTable->m_pfnBrush_Free = &Brush_Free;\r
-    pBrushTable->m_pfnBrush_Rotate = &Brush_Rotate;\r
-    pBrushTable->m_pfnBrushAlloc = &Brush_Alloc;\r
-    pBrushTable->m_pfnFace_Alloc = &Face_Alloc;\r
-    pBrushTable->m_pfnHasModel = NULL;// &HasModel;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, APPSHADERS_MAJOR))\r
-  {\r
-    _QERAppShadersTable *pShadersTable = static_cast<_QERAppShadersTable*>(pAPI->mpTable);\r
-    pShadersTable->m_pfnQTextures = QERApp_QTextures;\r
-    pShadersTable->m_pfnQTexmap = QERApp_QTexmap;\r
-    pShadersTable->m_pfnQeglobalsTexturewin = QERApp_QeglobalsTexturewin;\r
-    pShadersTable->m_pfnTexture_SetTexture = QERApp_Texture_SetTexture;\r
-    pShadersTable->m_pfnTexture_ShowInuse = Texture_ShowInuse;\r
-    pShadersTable->m_pfnBuildShaderList = &BuildShaderList;\r
-    pShadersTable->m_pfnPreloadShaders = &PreloadShaders;\r
-    \r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, QGL_MAJOR))\r
-  {\r
-    _QERQglTable *pQglTable = static_cast<_QERQglTable *>(pAPI->mpTable);\r
-    pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;\r
-    pQglTable->m_pfn_qglBegin = qglBegin;\r
-    pQglTable->m_pfn_qglBindTexture = qglBindTexture;\r
-    pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;\r
-    pQglTable->m_pfn_qglCallList = qglCallList;\r
-    pQglTable->m_pfn_qglCallLists = qglCallLists;\r
-    pQglTable->m_pfn_qglClear = qglClear;\r
-    pQglTable->m_pfn_qglClearColor = qglClearColor;\r
-    pQglTable->m_pfn_qglClearDepth = qglClearDepth;\r
-    pQglTable->m_pfn_qglColor3f = qglColor3f;\r
-    pQglTable->m_pfn_qglColor3fv = qglColor3fv;\r
-    pQglTable->m_pfn_qglColor4f = qglColor4f;\r
-    pQglTable->m_pfn_qglColor4fv = qglColor4fv;\r
-       pQglTable->m_pfn_qglColor4ubv = qglColor4ubv;\r
-    pQglTable->m_pfn_qglColorPointer = qglColorPointer;\r
-    pQglTable->m_pfn_qglCullFace = qglCullFace;\r
-    pQglTable->m_pfn_qglDepthFunc = qglDepthFunc;\r
-    pQglTable->m_pfn_qglDepthMask = qglDepthMask;\r
-    pQglTable->m_pfn_qglDisable = qglDisable;\r
-    pQglTable->m_pfn_qglDisableClientState = qglDisableClientState;\r
-    pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;\r
-    pQglTable->m_pfn_qglDeleteTextures = qglDeleteTextures;\r
-    pQglTable->m_pfn_qglDrawElements = qglDrawElements;\r
-    pQglTable->m_pfn_qglEnable = qglEnable;\r
-    pQglTable->m_pfn_qglEnableClientState = qglEnableClientState;      \r
-    pQglTable->m_pfn_qglEnd = qglEnd;\r
-    pQglTable->m_pfn_qglEndList = qglEndList;\r
-    pQglTable->m_pfn_qglFogf = qglFogf;\r
-    pQglTable->m_pfn_qglFogfv = qglFogfv;\r
-    pQglTable->m_pfn_qglFogi = qglFogi;\r
-    pQglTable->m_pfn_qglGenLists = qglGenLists;\r
-    pQglTable->m_pfn_qglGenTextures = qglGenTextures;\r
-    pQglTable->m_pfn_qglGetDoublev = qglGetDoublev;\r
-    pQglTable->m_pfn_qglGetIntegerv = qglGetIntegerv;\r
-    pQglTable->m_pfn_qglHint = qglHint;\r
-    pQglTable->m_pfn_qglLightfv = qglLightfv;\r
-    pQglTable->m_pfn_qglLineStipple = qglLineStipple;\r
-    pQglTable->m_pfn_qglLineWidth = qglLineWidth;\r
-    pQglTable->m_pfn_qglListBase = qglListBase;\r
-    pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;\r
-    pQglTable->m_pfn_qglMaterialf = qglMaterialf;\r
-    pQglTable->m_pfn_qglMaterialfv = qglMaterialfv;\r
-    pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;\r
-    pQglTable->m_pfn_qglMultMatrixf = qglMultMatrixf;\r
-    pQglTable->m_pfn_qglNewList = qglNewList;\r
-    pQglTable->m_pfn_qglNormal3f = qglNormal3f;\r
-    pQglTable->m_pfn_qglNormal3fv = qglNormal3fv;\r
-    pQglTable->m_pfn_qglNormalPointer = qglNormalPointer;\r
-    pQglTable->m_pfn_qglOrtho = qglOrtho;\r
-    pQglTable->m_pfn_qglPointSize = qglPointSize;\r
-    pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;\r
-    pQglTable->m_pfn_qglPopAttrib = qglPopAttrib;\r
-    pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;\r
-    pQglTable->m_pfn_qglPushAttrib = qglPushAttrib;\r
-    pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;\r
-    pQglTable->m_pfn_qglRasterPos3fv = qglRasterPos3fv;\r
-    pQglTable->m_pfn_qglRotated = qglRotated;\r
-    pQglTable->m_pfn_qglRotatef = qglRotatef;\r
-    pQglTable->m_pfn_qglScalef = qglScalef;\r
-    pQglTable->m_pfn_qglScissor = qglScissor;\r
-    pQglTable->m_pfn_qglShadeModel = qglShadeModel;\r
-    pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;\r
-    pQglTable->m_pfn_qglTexCoord2fv = qglTexCoord2fv;\r
-    pQglTable->m_pfn_qglTexCoordPointer = qglTexCoordPointer;\r
-    pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;\r
-    pQglTable->m_pfn_qglTexGenf = qglTexGenf;\r
-    pQglTable->m_pfn_qglTexImage1D = qglTexImage1D;\r
-    pQglTable->m_pfn_qglTexImage2D = qglTexImage2D;\r
-    pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;\r
-    pQglTable->m_pfn_qglTexParameterfv = qglTexParameterfv;\r
-    pQglTable->m_pfn_qglTexParameteri = qglTexParameteri;\r
-    pQglTable->m_pfn_qglTexParameteriv = qglTexParameteriv;\r
-    pQglTable->m_pfn_qglTexSubImage1D = qglTexSubImage1D;\r
-    pQglTable->m_pfn_qglTexSubImage2D = qglTexSubImage2D;\r
-    pQglTable->m_pfn_qglTranslated = qglTranslated;\r
-    pQglTable->m_pfn_qglTranslatef = qglTranslatef;\r
-    pQglTable->m_pfn_qglVertex2f = qglVertex2f;\r
-    pQglTable->m_pfn_qglVertex3f = qglVertex3f;\r
-    pQglTable->m_pfn_qglVertex3fv = qglVertex3fv;\r
-    pQglTable->m_pfn_qglVertexPointer = qglVertexPointer;\r
-    pQglTable->m_pfn_qglViewport = qglViewport;\r
-\r
-    pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;\r
-\r
-    pQglTable->m_pfn_qgluPerspective = qgluPerspective;\r
-    pQglTable->m_pfn_qgluLookAt = qgluLookAt;\r
-    pQglTable->m_pfnHookGL2DWindow = QERApp_HookGL2DWindow;\r
-    pQglTable->m_pfnUnHookGL2DWindow = QERApp_UnHookGL2DWindow;\r
-    pQglTable->m_pfnHookGL3DWindow = QERApp_HookGL3DWindow;\r
-    pQglTable->m_pfnUnHookGL3DWindow = QERApp_UnHookGL3DWindow;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, DATA_MAJOR))\r
-  {\r
-    _QERAppDataTable *pDataTable = static_cast<_QERAppDataTable *>(pAPI->mpTable);\r
-    pDataTable->m_pfnActiveBrushes = QERApp_ActiveBrushes;\r
-    pDataTable->m_pfnSelectedBrushes = QERApp_SelectedBrushes;\r
-    pDataTable->m_pfnFilteredBrushes = QERApp_FilteredBrushes;\r
-    pDataTable->m_pfnLstSkinCache = QERApp_LstSkinCache;\r
-    \r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, PATCH_MAJOR))\r
-  {\r
-    _QERPatchTable *pPatchTable = static_cast<_QERPatchTable *>(pAPI->mpTable);\r
-    pPatchTable->m_pfnPatch_Alloc = &Patch_Alloc;\r
-    pPatchTable->m_pfnAddBrushForPatch = &AddBrushForPatch;\r
-    pPatchTable->m_pfnMakeNewPatch = &MakeNewPatch;\r
-  \r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, ECLASSMANAGER_MAJOR))\r
-  {\r
-    _EClassManagerTable *pEClassManTable = static_cast<_EClassManagerTable *>(pAPI->mpTable);\r
-    \r
-    pEClassManTable->m_pfnEclass_InsertAlphabetized = &Eclass_InsertAlphabetized;\r
-    pEClassManTable->m_pfnGet_Eclass_E = &Get_EClass_E;\r
-    pEClassManTable->m_pfnSet_Eclass_Found = &Set_Eclass_Found;\r
-    pEClassManTable->m_pfnGet_Parsing_Single = &Get_Parsing_Single;\r
-    pEClassManTable->m_pfnEClass_Create = &EClass_Create;\r
-    pEClassManTable->m_pfnEclass_ForName = &Eclass_ForName;\r
-  \r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, SELECTEDFACE_MAJOR))\r
-  { \r
-    _QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pAPI->mpTable);\r
-\r
-    pSelectedFaceTable->m_pfnGetSelectedFaceCount = &QERApp_GetSelectedFaceCount;\r
-    pSelectedFaceTable->m_pfnGetFaceBrush = &QERApp_GetSelectedFaceBrush;\r
-    pSelectedFaceTable->m_pfnGetFace = &QERApp_GetSelectedFace;\r
-    pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;\r
-    pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;\r
-    pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;\r
-    pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;\r
-    pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, APPSURFACEDIALOG_MAJOR))\r
-  {\r
-    _QERAppSurfaceTable *pSurfDialogTable = static_cast<_QERAppSurfaceTable *>(pAPI->mpTable);\r
-    pSurfDialogTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;\r
-    pSurfDialogTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;\r
-    pSurfDialogTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;\r
-    pSurfDialogTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;\r
-    pSurfDialogTable->m_pfnTexMatToFakeTexCoords = &TexMatToFakeTexCoords;\r
-    pSurfDialogTable->m_pfnConvertTexMatWithQTexture = &ConvertTexMatWithQTexture;\r
-    pSurfDialogTable->m_pfnFakeTexCoordsToTexMat = &FakeTexCoordsToTexMat;\r
-    pSurfDialogTable->m_pfnPatch_ResetTexturing = &Patch_ResetTexturing;\r
-    pSurfDialogTable->m_pfnPatch_FitTexturing = &Patch_FitTexturing;\r
-    pSurfDialogTable->m_pfnPatch_NaturalizeSelected = &Patch_NaturalizeSelected;\r
-    pSurfDialogTable->m_pfnPatch_GetTextureName = &Patch_GetTextureName;\r
-    pSurfDialogTable->m_pfnQE_SingleBrush = &QE_SingleBrush;\r
-    pSurfDialogTable->m_pfnIsBrushPrimitMode = &IsBrushPrimitMode;\r
-    pSurfDialogTable->m_pfnComputeAxisBase = &ComputeAxisBase;\r
-    pSurfDialogTable->m_pfnBPMatMul = &BPMatMul;\r
-    pSurfDialogTable->m_pfnEmitBrushPrimitTextureCoordinates = &EmitBrushPrimitTextureCoordinates;\r
-    pSurfDialogTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;\r
-    pSurfDialogTable->m_pfnSelect_FitTexture = &Select_FitTexture;\r
-    pSurfDialogTable->m_pfnQERApp_QeglobalsSavedinfo_SIInc = &QERApp_QeglobalsSavedinfo_SIInc;\r
-    pSurfDialogTable->m_pfnQeglobalsGetGridSize = &QERApp_QeglobalsGetGridSize;\r
-    pSurfDialogTable->m_pfnFaceList_FitTexture = &SI_FaceList_FitTexture;\r
-    pSurfDialogTable->m_pfnGetMainWindow = &SI_GetMainWindow;\r
-    pSurfDialogTable->m_pfnSetWinPos_From_Prefs = &SI_SetWinPos_from_Prefs;\r
-    pSurfDialogTable->m_pfnGetSelectedFaceCountfromBrushes = &SI_GetSelectedFaceCountfromBrushes;\r
-    pSurfDialogTable->m_pfnGetSelFacesTexdef = &SI_GetSelFacesTexdef;\r
-    pSurfDialogTable->m_pfnSetTexdef_FaceList = &SI_SetTexdef_FaceList;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, UNDO_MAJOR))\r
-  { \r
-    _QERUndoTable *pUndoTable = static_cast<_QERUndoTable *>(pAPI->mpTable);\r
-\r
-    pUndoTable->m_pfnUndo_Start = &Undo_Start;\r
-    pUndoTable->m_pfnUndo_End = &Undo_End;\r
-    pUndoTable->m_pfnUndo_AddBrush = &Undo_AddBrush;\r
-    pUndoTable->m_pfnUndo_EndBrush = &Undo_EndBrush;\r
-    pUndoTable->m_pfnUndo_AddBrushList = &Undo_AddBrushList;\r
-    pUndoTable->m_pfnUndo_EndBrushList = &Undo_EndBrushList;\r
-    pUndoTable->m_pfnUndo_AddEntity = &Undo_AddEntity;\r
-    pUndoTable->m_pfnUndo_EndEntity = &Undo_EndEntity;\r
-    pUndoTable->m_pfnUndo_Undo = &Undo_Undo;                     // Nurail\r
-    pUndoTable->m_pfnUndo_Redo = &Undo_Redo;                     // Nurail\r
-    pUndoTable->m_pfnUndo_GetUndoId = &Undo_GetUndoId;           // Nurail\r
-    pUndoTable->m_pfnUndo_UndoAvailable = &Undo_UndoAvailable;   // Nurail\r
-    pUndoTable->m_pfnUndo_RedoAvailable = &Undo_RedoAvailable;   // Nurail\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, CAMERA_MAJOR))\r
-  {\r
-    _QERCameraTable *pCameraTable = static_cast<_QERCameraTable *>(pAPI->mpTable);\r
-\r
-    pCameraTable->m_pfnGetCamera = &QERApp_GetCamera;\r
-    pCameraTable->m_pfnSetCamera = &QERApp_SetCamera;\r
-    pCameraTable->m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, UI_MAJOR))\r
-  { \r
-    _QERUITable *pUITable = static_cast<_QERUITable *>(pAPI->mpTable);\r
-\r
-    pUITable->m_pfnCreateGLWindow = QERApp_CreateGLWindow;\r
-    pUITable->m_pfnHookWindow = QERApp_HookWindow;\r
-    pUITable->m_pfnUnHookWindow = QERApp_UnHookWindow;\r
-    pUITable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;\r
-    pUITable->m_pfnHookListener = QERApp_HookListener;\r
-    pUITable->m_pfnUnHookListener = QERApp_UnHookListener;\r
-\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, UIGTK_MAJOR))\r
-  { \r
-    _QERUIGtkTable *pUIGtkTable = static_cast<_QERUIGtkTable *>(pAPI->mpTable);\r
-\r
-    pUIGtkTable->m_pfn_GetQeglobalsGLWidget = &QERApp_GetQeGlobalsGLWidget;\r
-    pUIGtkTable->m_pfn_glwidget_new = &gtk_glwidget_new;\r
-    pUIGtkTable-> m_pfn_glwidget_swap_buffers = &gtk_glwidget_swap_buffers;\r
-    pUIGtkTable->m_pfn_glwidget_make_current = &gtk_glwidget_make_current;\r
-    pUIGtkTable->m_pfn_glwidget_destroy_context = &gtk_glwidget_destroy_context;\r
-    pUIGtkTable->m_pfn_glwidget_create_context = &gtk_glwidget_create_context;\r
-#if 0\r
-    pUIGtkTable->m_pfn_glwidget_get_context = &gtk_glwidget_get_context;\r
-#endif\r
-\r
-    return true;\r
-  }\r
-\r
-  return false;\r
-}\r
-\r
-const char* CSynapseClientRadiant::GetInfo()\r
-{\r
-  return "Radiant - synapse core built " __DATE__ " " RADIANT_VERSION;\r
-}\r
-\r
-const char* CSynapseClientRadiant::GetName()\r
-{\r
-  return "core";\r
-}\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// PlugInManager.cpp: implementation of the CPlugInManager class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#if defined (__linux__) || defined (__APPLE__)
+  #include <dirent.h>
+  #include <sys/time.h>
+#endif
+#ifdef __APPLE__
+  #ifdef __cplusplus
+    extern "C" {
+    #endif
+    #include <dlfcn.h>
+    #ifdef __cplusplus
+    }
+  #endif
+#endif
+#ifdef _WIN32
+  #include "objbase.h"
+#endif
+#include "pluginmanager.h"
+#include "plugin.h"
+#include "missing.h"
+#include "filters.h"
+
+#include "version.h"
+
+CRadiantImageManager g_ImageManager;
+CRadiantPluginManager g_PluginsManager;    
+
+_QERPlugSurfaceTable g_SurfaceTable;
+_QERFileSystemTable g_FileSystemTable;
+_QERShadersTable g_ShadersTable;
+_QERPlugMapTable g_MapTable;
+_QERPlugMapTable g_MapTable2;
+_QEREntityTable g_EntityTable;
+_EClassTable g_EClassDefTable;
+
+/*!
+  extending entity class formats
+  this approach only allows a single additional format, but it is enough for now
+*/
+bool g_bHaveEClassExt = false;
+_EClassTable g_EClassExtTable;
+
+
+filetype_t g_pattern_all("all files", "*.*");
+filetype_t g_pattern_projqe4v2("qe4 v2 project files", "*.qe4");
+filetype_t g_pattern_projxml("xml project files", "*.proj");
+filetype_t g_pattern_mapq3("quake3 maps", "*.map");
+filetype_t g_pattern_mapxml("xml quake3 maps", "*.xmap");
+filetype_t g_pattern_modelmd3("md3 models", "*.md3");
+filetype_t g_pattern_modelmdc("mdc models", "*.mdc");
+filetype_t g_pattern_modelmd2("md2 models", "*.md2");
+filetype_t g_pattern_modelmdl("mdl models", "*.mdl");
+//filetype_t g_pattern_modelea3("EA3 models", "*.ea3");
+filetype_t g_pattern_soundwav("PCM sound files", "*.wav");
+filetype_t g_pattern_regq3("quake3 region", "*.reg");
+
+#include <map>
+
+class RadiantFileTypeRegistry : public IFileTypeRegistry
+{
+public:
+  virtual ~RadiantFileTypeRegistry() {}
+  virtual void addType(const char* key, filetype_t type)
+  {
+    m_typelists[key].push_back(type);
+  }
+  virtual void getTypeList(const char* key, IFileTypeList* typelist)
+  {
+    filetype_list_t& list_ref = m_typelists[key];
+    for(unsigned int i=0; i<list_ref.size(); ++i)
+      typelist->addType(list_ref[i].getType());
+  }
+private:
+  struct filetype_copy_t
+  {
+    inline filetype_copy_t(const filetype_t other)
+      : m_name(other.name), m_pattern(other.pattern)
+    {}
+    inline filetype_t getType() const
+    {
+      return filetype_t(m_name.c_str(), m_pattern.c_str());
+    }
+  private:
+    string_t m_name;
+    string_t m_pattern;
+  };
+  typedef vector<filetype_copy_t> filetype_list_t;
+  map<string_t, filetype_list_t> m_typelists;
+};
+
+static RadiantFileTypeRegistry g_patterns;
+
+IFileTypeRegistry* GetFileTypeRegistry()
+{
+  return &g_patterns;
+}
+
+void InitFileTypes()
+{
+  //GetFileTypeRegistry()->addType("project", g_pattern_projqe4v2);
+  GetFileTypeRegistry()->addType("project", g_pattern_projxml);
+
+  GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapq3);
+  GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapxml);
+  
+  GetFileTypeRegistry()->addType("region", g_pattern_regq3);
+/*
+  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd3);
+  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd2);
+  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdl);
+  GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdc);
+  //GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelea3);
+  */
+
+  GetFileTypeRegistry()->addType("sound", g_pattern_soundwav);
+}
+
+
+class CRadiantModelModuleManager : public CSynapseAPIManager
+{
+  typedef list<APIDescriptor_t*> APIDescriptorList;
+
+  APIDescriptorList mAPIs;
+public:
+  CRadiantModelModuleManager()
+  {
+    SetMatchAPI(MODEL_MAJOR, "*");
+  }
+  virtual ~CRadiantModelModuleManager()
+  {
+    APIDescriptorList::iterator i;
+    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
+    {
+      delete (_QERPlugModelTable*)(*i)->mpTable;
+      delete *i;
+      *i = NULL;
+    }
+    mAPIs.clear();
+  }
+
+  // CSynapseAPIManager interface -------------------
+  APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
+  {
+    APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
+    pRequireAPI->mpTable = new _QERPlugModelTable;
+    ((_QERPlugModelTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugModelTable);
+    pRequireAPI->mSize = sizeof(_QERPlugModelTable);
+    mAPIs.push_front(pRequireAPI);
+    return pRequireAPI;
+  }
+
+  // Model Manager specific
+  const _QERPlugModelTable* GetModelTable(const char* version)
+  {
+    APIDescriptorList::iterator i;
+    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
+      if(strcmp(version, (*i)->minor_name) == 0)
+        return ((_QERPlugModelTable*)(*i)->mpTable);
+    return NULL;
+  }
+};
+
+CRadiantModelModuleManager g_ModelManager;
+
+/*! One of these exists for each unique model ID in use */
+class CModelWrapper
+{
+  friend class CModelManager;
+public:
+  CModelWrapper (const char *id, const char* version) : refcount(1)
+  {
+    copy(id, version);
+    construct();
+  }
+  void Refresh()
+  {
+    destroy();
+    construct();
+  }
+  ~CModelWrapper ()
+  {
+    destroy();
+  }
+private:
+  void copy(const char* id, const char* version)
+  {
+    m_id = id;
+    m_version = version;
+  }
+  void construct()
+  {
+    m_model.pRender = NULL;
+    m_model.pSelect = NULL;
+    m_model.pEdit = NULL;
+
+    const _QERPlugModelTable* pTable = g_ModelManager.GetModelTable(m_version.c_str());
+
+    if(pTable != NULL)
+      pTable->m_pfnLoadModel(&m_model, m_id.c_str());
+  }
+  void destroy()
+  {
+    if (m_model.pRender) m_model.pRender->DecRef();
+    if (m_model.pSelect) m_model.pSelect->DecRef();
+    if (m_model.pEdit) m_model.pEdit->DecRef();
+  }
+  string_t m_id;
+  string_t m_version;
+  entity_interfaces_t m_model;
+  int refcount;
+};
+
+/*! Creates and tracks CModelWrapper instances.
+Creates a new instance for each unique ID requested, keeps count of the number of
+times an ID is being referenced, and destroys any instance that is no longer in use */
+class CModelManager : public IModelCache
+{
+public:
+  CModelManager()
+  {
+    m_ptrs = g_ptr_array_new ();
+  }
+  virtual ~CModelManager()
+  {
+    g_ptr_array_free(m_ptrs, FALSE);
+  }
+
+  virtual void DeleteByID(const char *id, const char* version)
+  {
+    unsigned int i;
+    CModelWrapper *elem;
+    for(i=0; i<m_ptrs->len; i++)
+    {
+      elem = (CModelWrapper*)m_ptrs->pdata[i];
+      if(strcmp(elem->m_version.c_str(), version) == 0
+        && strcmp(elem->m_id.c_str(), id) == 0
+        && --elem->refcount == 0)
+      {
+        g_ptr_array_remove_index_fast(m_ptrs, i);
+        delete elem;
+        return;
+      }
+    }
+  }
+
+  virtual entity_interfaces_t *GetByID(const char *id, const char* version)
+  {
+    unsigned int i;
+    CModelWrapper *elem;
+    for(i=0; i<m_ptrs->len; i++)
+    {
+      elem = (CModelWrapper*)m_ptrs->pdata[i];
+      if(strcmp(elem->m_version.c_str(), version) == 0
+        && strcmp(elem->m_id.c_str(), id) == 0)
+      {
+        elem->refcount++;
+        return &elem->m_model;
+      }
+    }
+    
+    elem = new CModelWrapper(id, version);
+    g_ptr_array_add(m_ptrs, elem);
+
+    return &elem->m_model;
+  }
+
+  virtual void RefreshAll()
+  {
+    for(unsigned int i=0; i<m_ptrs->len; ++i)
+      ((CModelWrapper*)m_ptrs->pdata[i])->Refresh();
+  }
+private:
+  GPtrArray *m_ptrs; // array of CModelWrapper*
+};
+
+CModelManager g_model_cache;
+
+IModelCache* GetModelCache()
+{
+  return &g_model_cache;
+}
+
+// toolbar manager
+class CRadiantToolbarModuleManager : public CSynapseAPIManager
+{
+  typedef list<APIDescriptor_t*> APIDescriptorList;
+
+  APIDescriptorList mAPIs;
+public:
+  CRadiantToolbarModuleManager()
+  {
+    SetMatchAPI(TOOLBAR_MAJOR, "*");
+  }
+  virtual ~CRadiantToolbarModuleManager()
+  {
+    APIDescriptorList::iterator i;
+    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
+    {
+      delete (_QERPlugToolbarTable*)(*i)->mpTable;
+      delete *i;
+      *i = NULL;
+    }
+    mAPIs.clear();
+  }
+  
+  // CSynapseAPIManager interface -------------------
+  APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
+  {
+    APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
+    pRequireAPI->mpTable = new _QERPlugToolbarTable;
+    ((_QERPlugToolbarTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugToolbarTable);
+    pRequireAPI->mSize = sizeof(_QERPlugToolbarTable);
+    mAPIs.push_front(pRequireAPI);
+    return pRequireAPI;
+  }
+
+  // Toolbar Manager specific
+  void ConstructToolbar()
+  {
+    APIDescriptorList::iterator i;
+    for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
+      AddItem((_QERPlugToolbarTable*)(*i)->mpTable);
+  }
+  
+private:
+
+  void AddItem(_QERPlugToolbarTable* pTable)
+  {
+    const unsigned int count = pTable->m_pfnToolbarButtonCount();
+    for(unsigned int i=0; i<count; ++i)
+    {
+      const IToolbarButton* button = pTable->m_pfnGetToolbarButton(i);
+      g_pParentWnd->AddPlugInToolbarButton(button);
+    }
+  }
+};
+
+CRadiantToolbarModuleManager g_ToolbarModuleManager;
+
+
+/* image manager ---------------------------------------- */
+
+CRadiantImageManager::~CRadiantImageManager()
+{
+  list<CImageTableSlot *>::iterator iSlot;
+  for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
+  {
+    delete *iSlot;
+    *iSlot = NULL;
+  }
+}
+
+void CImageTableSlot::InitForFillAPITable(APIDescriptor_t *pAPI)
+{
+  mpAPI = pAPI;
+  mpTable = new _QERPlugImageTable;
+  mpTable->m_nSize = sizeof(_QERPlugImageTable);
+  mpAPI->mSize = sizeof(_QERPlugImageTable);
+  mpAPI->mpTable = mpTable;
+}
+
+void CRadiantImageManager::FillAPITable(APIDescriptor_t *pAPI)
+{
+  CImageTableSlot *pSlot = new CImageTableSlot();
+  pSlot->InitForFillAPITable(pAPI);
+  mSlots.push_front(pSlot);
+}
+
+/*!
+  Loads an image by calling the module that handles the extension extracted from the filename
+  \param name The filename to load. If no extension is provided, we walk the list of supported extensions.
+  \param pic The returned image data
+  \param width The returned width of the image
+  \param height The returned height of the image
+*/
+void CRadiantImageManager::LoadImage(const char *name, byte **pic, int *width, int *height)
+{
+  const char *ext = NULL;
+  int len;
+
+  // extract extension
+  len = strlen (name);
+  if ((len > 5) && (name[len-4] == '.'))
+    ext = &name[len-3];
+
+  if (ext == NULL)
+  {
+    // if no extension is provided, start walking through the list
+    Str fullname;
+    list<CImageTableSlot *>::iterator iSlot;
+    for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
+    {
+      APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
+      fullname.Format("%s.%s", name, pAPI->minor_name);
+      (*iSlot)->GetTable()->m_pfnLoadImage(fullname.GetBuffer(), pic, width, height);
+      if (*pic)
+        return; // this was the right extension, we loaded
+    }
+    return;
+  }
+  
+  // start walking the interfaces
+  list<CImageTableSlot *>::iterator iSlot;
+  for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
+  {
+    APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
+    if (!strcmp(pAPI->minor_name, ext))
+    {
+      (*iSlot)->GetTable()->m_pfnLoadImage(name, pic, width, height);
+      return;
+    }
+  }
+  Sys_FPrintf(SYS_WRN, "WARNING: no image table for extension '%s'\n", ext);
+}
+
+void CRadiantImageManager::BeginExtensionsScan()
+{
+  mExtScanSlot = mSlots.begin();
+}
+
+const char* CRadiantImageManager::GetNextExtension()
+{
+  if (mExtScanSlot != mSlots.end())
+  {
+    char *ext = (*mExtScanSlot)->GetDescriptor()->minor_name;
+    mExtScanSlot++;
+    return ext;
+  }
+  return NULL;
+}
+
+/* plugin manager --------------------------------------- */
+APIDescriptor_t* CRadiantPluginManager::BuildRequireAPI(APIDescriptor_t *pAPI)
+{  
+  CPluginSlot *pSlot = new CPluginSlot(pAPI);
+  mSlots.push_front(pSlot);
+  return pSlot->GetDescriptor();
+}
+
+void CRadiantPluginManager::PopulateMenu()
+{
+  list<CPluginSlot *>::iterator iPlug;
+  for(iPlug=mSlots.begin(); iPlug != mSlots.end(); iPlug++)
+  {
+    g_pParentWnd->AddPlugInMenuItem(*iPlug);
+  }
+}
+
+void CSynapseClientRadiant::ImportMap(IDataStream *in, CPtrArray *ents, const char *type)
+{
+  if (strcmp(type,"map")==0)
+  {
+    g_MapTable.m_pfnMap_Read(in, ents);
+  }
+  else if (strcmp(type,"xmap")==0)
+  {
+    g_MapTable2.m_pfnMap_Read(in, ents);    
+  }
+  else
+    Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
+}
+
+void CSynapseClientRadiant::ExportMap(CPtrArray *ents, IDataStream *out, const char *type)
+{
+  if (strcmp(type,"map")==0)
+  {
+    g_MapTable.m_pfnMap_Write(ents, out);
+  }
+  else if (strcmp(type,"xmap")==0)
+  {
+    g_MapTable2.m_pfnMap_Write(ents, out);
+  }
+  else
+    Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
+}
+
+CPluginSlot::CPluginSlot(APIDescriptor_t *pAPI)
+{
+  mpAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
+  mpTable = new _QERPluginTable;
+  mpTable->m_nSize = sizeof(_QERPluginTable);
+  mpAPI->mSize = sizeof(_QERPluginTable);
+  mpAPI->mpTable = mpTable;
+  m_CommandStrings = NULL;
+  m_CommandIDs = NULL;
+  m_bReady = false;
+}
+
+CPluginSlot::~CPluginSlot()
+{  
+  delete mpAPI;
+  delete mpTable;
+  while (m_CommandStrings)
+  {
+    ::free (m_CommandStrings->data);
+    m_CommandStrings = g_slist_remove (m_CommandStrings, m_CommandStrings->data);
+  }
+}
+
+void CPluginSlot::Init()
+{
+  CString str =   mpTable->m_pfnQERPlug_GetCommandList();
+  char cTemp[1024];
+  strcpy(cTemp, str);
+  char* token = strtok(cTemp, ",;");
+  if (token && *token == ' ')
+  {
+    while (*token == ' ')
+    token++;
+  }
+  while (token != NULL)
+  {
+    m_CommandStrings = g_slist_append (m_CommandStrings, strdup (token));
+    token = strtok(NULL, ",;");
+  }
+  mpTable->m_pfnQERPlug_Init(NULL, (void*)g_pParentWnd->m_pWidget);
+  m_bReady = true;
+}
+
+const char* CPluginSlot::getMenuName()
+{
+  return mpAPI->minor_name;
+}
+
+int CPluginSlot::getCommandCount()
+{
+  if (!m_bReady)
+    Init();
+  return g_slist_length (m_CommandStrings);  
+}
+  
+const char* CPluginSlot::getCommand(int n)
+{
+  if (!m_bReady)
+    Init();
+  return (char*)g_slist_nth_data (m_CommandStrings, n);  
+}
+
+void CPluginSlot::addMenuID(int n)
+{
+  m_CommandIDs = g_slist_append (m_CommandIDs, GINT_TO_POINTER (n));
+}
+
+bool CPluginSlot::ownsCommandID(int n)
+{
+  GSList* lst;
+
+  for (lst = m_CommandIDs; lst != NULL; lst = g_slist_next (lst))
+  {
+    if (GPOINTER_TO_INT (lst->data) == n)
+      return true;
+  }
+  return false;
+}
+
+void CPluginSlot::Dispatch(const char *p)
+{
+  vec3_t vMin, vMax;
+  if (selected_brushes.next == &selected_brushes)
+  {
+    vMin[0] = vMin[1] = vMin[2] = 0;
+    VectorCopy(vMin, vMax);
+  } else
+  {
+    Select_GetBounds (vMin, vMax);
+  }
+  mpTable->m_pfnQERPlug_Dispatch(p, vMin, vMax, QE_SingleBrush(true));
+}
+
+CRadiantPluginManager::~CRadiantPluginManager()
+{
+  list<CPluginSlot *>::iterator iSlot;
+  for(iSlot=mSlots.begin(); iSlot!=mSlots.end(); iSlot++)
+  {
+    delete *iSlot;
+    *iSlot = NULL;
+  }
+}
+
+bool CRadiantPluginManager::Dispatch(int n, const char* p)
+{
+  list<CPluginSlot *>::iterator iPlug;
+  for(iPlug=mSlots.begin(); iPlug!=mSlots.end(); iPlug++)
+  {
+    CPluginSlot *pPlug = *iPlug;
+    if (pPlug->ownsCommandID(n))
+    {
+      pPlug->Dispatch(p);
+      return true;
+    }
+  }
+  return false;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPlugInManager::CPlugInManager()
+{
+  PatchesMode = EActivePatches;
+  m_PlugIns = NULL;
+}
+
+CPlugInManager::~CPlugInManager()
+{
+  Cleanup();
+}
+
+void CPlugInManager::InitForDir(const Str &dir)
+{
+  Str path;
+
+  path = dir;
+  path += g_strPluginsDir;
+  // SYNAPSE
+  g_pParentWnd->GetSynapseServer().AddSearchPath(path);
+
+  if (strcmp(g_strPluginsDir.GetBuffer(), g_strModulesDir.GetBuffer()) != 0)
+  {
+    path = dir;
+    path += g_strModulesDir;
+    // SYNAPSE
+    g_pParentWnd->GetSynapseServer().AddSearchPath(path);
+  } 
+}
+
+static const XMLConfigEntry_t manager_entries[] = 
+  { 
+    { VFS_MAJOR,            SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },
+    { SHADERS_MAJOR,        SYN_REQUIRE, sizeof(g_ShadersTable),    &g_ShadersTable },
+    { MAP_MAJOR,            SYN_REQUIRE, sizeof(g_MapTable),        &g_MapTable },
+    { ECLASS_MAJOR,         SYN_REQUIRE, sizeof(g_EClassDefTable),  &g_EClassDefTable },
+    { SURFACEDIALOG_MAJOR,  SYN_REQUIRE, sizeof(g_SurfaceTable),    &g_SurfaceTable },
+    { NULL, SYN_UNKNOWN, 0, NULL } };
+
+void CPlugInManager::Init()
+{
+  Str synapse_config;
+  
+  Cleanup();
+  
+  // set some globals
+  g_qeglobals.bBSPFrontendPlugin = false;
+
+  InitForDir(g_strGameToolsPath);
+  InitForDir(g_strAppPath);
+
+  synapse_config = g_strGameToolsPath;
+  synapse_config += "synapse.config";
+  if (!g_pParentWnd->GetSynapseServer().Initialize(synapse_config.GetBuffer(), &Sys_Printf_VA))
+    Error("Synpase server initialization failed (see console)\n");
+  
+  // builtin modules
+  g_pParentWnd->GetSynapseServer().EnumerateBuiltinModule(&eclass_def);
+  
+  // APIs we provide
+  g_pParentWnd->GetSynapseClient().AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1));
+  g_pParentWnd->GetSynapseClient().AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(_QERScripLibTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(BRUSH_MAJOR, NULL, sizeof(_QERBrushTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(APPSHADERS_MAJOR, NULL, sizeof(_QERAppShadersTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(DATA_MAJOR, NULL, sizeof(_QERAppDataTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(PATCH_MAJOR, NULL, sizeof(_QERPatchTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(_EClassManagerTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(_QERSelectedFaceTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(APPSURFACEDIALOG_MAJOR, NULL, sizeof(_QERAppSurfaceTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(UNDO_MAJOR, NULL, sizeof(_QERUndoTable));
+  g_pParentWnd->GetSynapseClient().AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable));  
+  g_pParentWnd->GetSynapseClient().AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable));  
+  g_pParentWnd->GetSynapseClient().AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable));  
+  
+  // modules configured by XML
+  if ( !g_pParentWnd->GetSynapseClient().ConfigXML( &g_pParentWnd->GetSynapseServer(), "core", manager_entries ) ) {
+    Error("Synapse server initialization failed (see console)\n");
+  }
+  
+  // adding a manager is a special case that ConfigXML doesn't take care of
+  g_pParentWnd->GetSynapseServer().SelectClientConfig( "core" );
+  char *minor;
+  if ( !g_pParentWnd->GetSynapseServer().GetConfigForAPI( IMAGE_MAJOR, &minor ) ) {
+    Syn_Printf( "GetConfigForAPI '%s' failed - invalid XML config file?\n", IMAGE_MAJOR );
+    Error("Synapse server initialization failed (see console)\n");
+  }
+  g_ImageManager.SetMatchAPI( IMAGE_MAJOR, minor );
+  g_pParentWnd->GetSynapseClient().AddManager( &g_ImageManager );
+  
+  // SYN_REQUIRE entries which are still hardcoded
+  g_pParentWnd->GetSynapseClient().AddAPI(MAP_MAJOR, "mapxml", sizeof(g_MapTable2), SYN_REQUIRE, &g_MapTable2);
+  g_pParentWnd->GetSynapseClient().AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);
+  
+  // plugins: load anything that claims to be a plugin
+  // minor becomes some kind of matching pattern
+  // g_PluginsManager is an API any class, it receives several function tables as needed
+  // you can't do a SYN_PROVIDE with that, has to be a SYN_REQUIRE ?
+  g_PluginsManager.SetMatchAPI(PLUGIN_MAJOR, "*");
+  g_pParentWnd->GetSynapseClient().AddManager(&g_PluginsManager);
+  g_pParentWnd->GetSynapseClient().AddManager(&g_ToolbarModuleManager);
+  g_pParentWnd->GetSynapseClient().AddManager(&g_ModelManager);
+  if (!g_pParentWnd->GetSynapseServer().Resolve(&g_pParentWnd->GetSynapseClient()))
+  {
+    Error("synapse initialization fail (see console)");
+  }
+  g_PluginsManager.PopulateMenu();
+  g_ToolbarModuleManager.ConstructToolbar();
+  InitFileTypes();
+}
+
+void CPlugInManager::Shutdown()
+{
+  g_pParentWnd->GetSynapseServer().Shutdown();
+}
+
+void CPlugInManager::Cleanup()
+{
+  int i;
+
+  for (i = 0; i < m_BrushHandles.GetSize(); i++)
+  {
+    brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
+    Brush_Free(pb);
+  }
+  m_BrushHandles.RemoveAll();
+
+  for (i = 0; i < m_EntityHandles.GetSize(); i++)
+  {
+    entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
+    Entity_Free(pe);
+  }
+  m_EntityHandles.RemoveAll();
+
+  // patches
+  // these are linked into the map
+  m_PatchesHandles.RemoveAll();
+  // these patches were allocated by Radiant on plugin request
+  // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
+  // in which case we are supposed to delete them
+  // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
+  // erased and we are trying a second time, therefore crashing ..
+  //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
+#ifdef _DEBUG
+  if (m_PluginPatches.GetSize() != 0)
+    Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
+#endif
+
+/*     for (i = 0; i < m_PluginPatches.GetSize(); i++)
+  {
+    patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
+    if (pMesh->pSymbiot)
+      delete pMesh;
+  }
+  m_PluginPatches.RemoveAll(); */
+}
+
+void CPlugInManager::Dispatch(int n, const char * p)
+{
+  g_PluginsManager.Dispatch(n, p);
+}
+
+void WINAPI QERApp_GetDispatchParams(vec3_t vMin, vec3_t vMax, bool *bSingleBrush)
+{
+  if (selected_brushes.next == &selected_brushes)
+  {
+    vMin[0] = vMin[1] = vMin[2] = 0;
+    VectorCopy(vMin, vMax);
+  } else
+  {
+    Select_GetBounds (vMin, vMax);
+  }
+
+  if( bSingleBrush )
+    *bSingleBrush = QE_SingleBrush(true);
+}
+
+
+// creates a dummy brush in the active brushes list
+// FIXME : is this one really USED ?
+void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
+{
+
+  brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
+  Entity_LinkBrush (world_entity, pBrush);
+  Brush_Build(pBrush);
+  Brush_AddToList (pBrush, &active_brushes);
+  Select_Brush(pBrush);
+  Sys_UpdateWindows(W_ALL);
+}
+
+void* CPlugInManager::CreateBrushHandle()
+{
+  brush_t *pb = Brush_Alloc();
+  pb->numberId = g_nBrushId++;
+  m_BrushHandles.Add(pb);
+  return(void*)pb;
+}
+
+void CPlugInManager::DeleteBrushHandle(void * vp)
+{
+  CPtrArray* pHandles[3];
+  pHandles[0] = &m_SelectedBrushHandles;
+  pHandles[1] = &m_ActiveBrushHandles;
+  pHandles[2] = &m_BrushHandles;
+
+  for (int j = 0; j < 3; j++)
+  {
+    for (int i = 0; i < pHandles[j]->GetSize(); i++)
+    {
+      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
+      if (pb == reinterpret_cast<brush_t*>(vp))
+      {
+        if (j == 2)
+        {
+          // only remove it from the list if it is work area
+          // this allows the selected and active list indexes to remain constant
+          // throughout a session (i.e. between an allocate and release)
+          pHandles[j]->RemoveAt(i);
+        }
+        Brush_Free(pb);
+        Sys_MarkMapModified();    // PGM
+        return;
+      }
+    }
+  }
+}
+
+void CPlugInManager::CommitBrushHandleToMap(void * vp)
+{
+  g_bScreenUpdates = false; 
+  for (int i = 0; i < m_BrushHandles.GetSize(); i++)
+  {
+    brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
+    if (pb == reinterpret_cast<brush_t*>(vp))
+    {
+      m_BrushHandles.RemoveAt(i);
+      Entity_LinkBrush (world_entity, pb);
+      Brush_Build(pb);
+      Brush_AddToList (pb, &active_brushes);
+      Select_Brush(pb);
+    }
+  }
+  g_bScreenUpdates = true; 
+  Sys_UpdateWindows(W_ALL);
+}
+
+void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
+{
+  brush_t *bp = FindBrushHandle(vp);
+  if (bp != NULL)
+  {
+    face_t *f = Face_Alloc();
+    f->texdef = g_qeglobals.d_texturewin.texdef;
+    f->texdef.flags &= ~SURF_KEEP;
+    f->texdef.contents &= ~CONTENTS_KEEP;
+    f->next = bp->brush_faces;
+    bp->brush_faces = f;
+    VectorCopy (v1, f->planepts[0]);
+    VectorCopy (v2, f->planepts[1]);
+    VectorCopy (v3, f->planepts[2]);
+  }
+}
+
+brush_t* CPlugInManager::FindBrushHandle(void * vp)
+{
+  CPtrArray* pHandles[4];
+  pHandles[0] = &m_SelectedBrushHandles;
+  pHandles[1] = &m_ActiveBrushHandles;
+  pHandles[2] = &m_BrushHandles;
+  pHandles[3] = &m_EntityBrushHandles;
+
+  for (int j = 0; j < 4; j++)
+  {
+    for (int i = 0; i < pHandles[j]->GetSize(); i++)
+    {
+      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
+      if (pb == reinterpret_cast<brush_t*>(vp))
+      {
+        return pb;
+      }
+    }
+  }
+  return NULL;
+}
+
+patchMesh_t* CPlugInManager::FindPatchHandle(int index)
+{
+  switch (PatchesMode)
+  {
+  case EActivePatches:
+  case ESelectedPatches:
+    if ( index < m_PatchesHandles.GetSize() )
+    {
+      brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
+      return pb->pPatch;
+    }
+#ifdef _DEBUG
+    Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
+#endif
+    break;
+  case EAllocatedPatches:
+    if ( index < m_PluginPatches.GetSize() )
+    {
+      patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
+      return pPatch;
+    }
+#ifdef _DEBUG
+    Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
+#endif
+    break;
+  }
+  return NULL;
+}
+
+void* WINAPI QERApp_CreateBrushHandle()
+{
+  return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
+}
+
+void WINAPI QERApp_DeleteBrushHandle(void* vp)
+{
+  g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
+}
+
+void WINAPI QERApp_CommitBrushHandleToMap(void* vp)
+{
+  g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
+}
+
+void WINAPI QERApp_AddFace(void* vp, vec3_t v1, vec3_t v2, vec3_t v3)
+{
+  g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
+}
+
+void WINAPI QERApp_DeleteSelection()
+{
+  Select_Delete();
+}
+
+void QERApp_GetCamera( vec3_t origin, vec3_t angles )
+{
+  VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->origin, origin );
+  VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->angles, angles );
+}
+
+void QERApp_SetCamera( vec3_t origin, vec3_t angles )
+{
+  VectorCopy( origin, g_pParentWnd->GetCamWnd()->Camera()->origin );
+  VectorCopy( angles, g_pParentWnd->GetCamWnd()->Camera()->angles );
+
+  Sys_UpdateWindows( W_ALL ); // specify 
+  g_pParentWnd->OnTimer();
+}
+
+void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )
+{
+  GtkWidget *widget;
+
+  if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
+    widget = g_pParentWnd->GetCamWnd()->m_pParent;
+  else
+    widget = g_pParentWnd->GetCamWnd()->GetWidget();
+
+  get_window_pos (widget, x, y);
+
+  *width = g_pParentWnd->GetCamWnd()->Camera()->width;
+  *height = g_pParentWnd->GetCamWnd()->Camera()->height;
+}
+
+//FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
+bool g_bPlugWait = false;
+bool g_bPlugOK = false;
+int  g_nPlugCount = 0;
+
+void _PlugDone(bool b, int n)
+{
+  g_bPlugWait = false;
+  g_bPlugOK = b;
+  g_nPlugCount = n;
+}
+
+void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, char* pMsg)
+{
+  ShowInfoDialog(pMsg);
+  g_bPlugWait = true;
+  g_bPlugOK = false;
+  g_nPlugCount = 0;
+//  g_nPlugCount=nMax-1;
+  AcquirePath(nMax, &_PlugDone);
+
+  while (g_bPlugWait)
+    gtk_main_iteration ();
+
+  HideInfoDialog();
+
+  pData->m_nCount = 0;
+  pData->m_pVectors = NULL;
+
+  if (g_bPlugOK && g_nPlugCount > 0)
+  {
+    pData->m_nCount = g_nPlugCount;
+    pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
+    vec3_t *pOut = pData->m_pVectors;
+    for (int i = 0; i < g_nPlugCount; i++)
+    {
+      memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
+      pOut++;
+    }
+  }
+}
+
+//#define DBG_PAPI
+
+void CheckTexture(face_t *f)
+{
+  if (!f->d_texture)
+  {
+#ifdef DBG_PAPI
+    Sys_Printf("CheckTexture: requesting %s\n", f->texdef.name);
+#endif
+    f->pShader = QERApp_Shader_ForName (f->texdef.GetName());
+    f->pShader->IncRef();
+    f->d_texture = f->pShader->getTexture();
+  }
+}
+
+// expects pData->m_TextureName to be relative to "textures/"
+void WINAPI QERApp_AddFaceData(void* pv, _QERFaceData *pData)
+{
+#ifdef DBG_PAPI
+  Sys_Printf("FindBrushHandle...");
+#endif
+  brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+#ifdef DBG_PAPI
+  Sys_Printf("Done\n");
+#endif
+  if (pBrush != NULL)
+  {
+    face_t *f = Face_Alloc();
+    f->texdef = g_qeglobals.d_texturewin.texdef;
+    f->texdef.flags = pData->m_nFlags;
+    f->texdef.contents = pData->m_nContents;
+    f->texdef.value = pData->m_nValue;
+    f->texdef.SetName(pData->m_TextureName);
+    f->next = pBrush->brush_faces;
+    pBrush->brush_faces = f;
+    VectorCopy (pData->m_v1, f->planepts[0]);
+    VectorCopy (pData->m_v2, f->planepts[1]);
+    VectorCopy (pData->m_v3, f->planepts[2]);
+    // we might need to convert one way or the other if the input and the brush coordinates setting don't match
+    if (pData->m_bBPrimit == true)
+    {
+      f->brushprimit_texdef = pData->brushprimit_texdef;
+      if (!g_qeglobals.m_bBrushPrimitMode)
+      {
+        // before calling into the conversion, make sure we have a texture!
+        CheckTexture (f);
+#ifdef DBG_PAPI
+        Sys_Printf("BrushPrimitFaceToFace...");
+#endif
+
+        // convert BP to regular
+        BrushPrimitFaceToFace (f);
+#ifdef DBG_PAPI
+        Sys_Printf("Done\n");
+#endif
+      }
+    } else
+    {
+#ifdef _DEBUG
+      if (pData->m_bBPrimit != false)
+        Sys_FPrintf (SYS_WRN, "non-initialized pData->m_bBPrimit in QERApp_AddFaceData\n");
+#endif
+      f->texdef.rotate = pData->m_fRotate;
+      f->texdef.shift[0] = pData->m_fShift[0];
+      f->texdef.shift[1] = pData->m_fShift[1];
+      f->texdef.scale[0] = pData->m_fScale[0];
+      f->texdef.scale[1] = pData->m_fScale[1];
+      if (g_qeglobals.m_bBrushPrimitMode)
+      {
+        CheckTexture (f);
+#ifdef DBG_PAPI
+        Sys_Printf("FaceToBrushPrimitFace...");
+#endif
+
+        // convert regular to BP
+        FaceToBrushPrimitFace (f);
+#ifdef DBG_PAPI
+        Sys_Printf("Done\n");
+#endif
+      }
+    }
+    Sys_MarkMapModified();    // PGM
+  }
+}
+
+int WINAPI QERApp_GetFaceCount(void* pv)
+{
+  int n = 0;
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+    {
+      n++;
+    }
+  }
+  return n;
+}
+
+_QERFaceData* WINAPI QERApp_GetFaceData(void* pv, int nFaceIndex)
+{
+  static _QERFaceData face;
+  int n = 0;
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+
+  if (pBrush != NULL)
+  {
+    for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+    {
+
+#ifdef _DEBUG
+      if (!pBrush->brush_faces)
+      {
+        Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
+        return NULL;
+      }
+#endif
+
+      if (n == nFaceIndex)
+      {
+        face.m_nContents = f->texdef.contents;
+        face.m_nFlags = f->texdef.flags;
+        face.m_nValue = f->texdef.value;
+        if (g_qeglobals.m_bBrushPrimitMode)
+        {
+          //++timo NOTE: we may want to convert back to old format for backward compatibility with some old plugins?
+          face.m_bBPrimit = true;
+          face.brushprimit_texdef = f->brushprimit_texdef;
+        } else
+        {
+          face.m_fRotate = f->texdef.rotate;
+          face.m_fScale[0] = f->texdef.scale[0];
+          face.m_fScale[1] = f->texdef.scale[1];
+          face.m_fShift[0] = f->texdef.shift[0];
+          face.m_fShift[1] = f->texdef.shift[1];
+        }
+        strcpy(face.m_TextureName, f->texdef.GetName());
+        VectorCopy(f->planepts[0], face.m_v1);
+        VectorCopy(f->planepts[1], face.m_v2);
+        VectorCopy(f->planepts[2], face.m_v3);
+        return &face;
+      }
+      n++;
+    }
+  }
+  return NULL;
+}
+
+void WINAPI QERApp_SetFaceData(void* pv, int nFaceIndex, _QERFaceData *pData)
+{
+  int n = 0;
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+
+  if (pBrush != NULL)
+  {
+    for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+    {
+      if (n == nFaceIndex)
+      {
+        f->texdef.flags = pData->m_nFlags;
+        f->texdef.contents = pData->m_nContents;
+        f->texdef.value = pData->m_nValue;
+        f->texdef.rotate = pData->m_fRotate;
+        f->texdef.shift[0] = pData->m_fShift[0];
+        f->texdef.shift[1] = pData->m_fShift[1];
+        f->texdef.scale[0] = pData->m_fScale[0];
+        f->texdef.scale[1] = pData->m_fScale[1];
+        //strcpy(f->texdef.name, pData->m_TextureName);
+        f->texdef.SetName(pData->m_TextureName);
+        VectorCopy(pData->m_v1, f->planepts[0]);
+        VectorCopy(pData->m_v2, f->planepts[1]);
+        VectorCopy(pData->m_v3, f->planepts[2]);
+        Sys_MarkMapModified();    // PGM
+        return;           // PGM
+      }
+      n++;
+    }
+  }
+}
+
+void WINAPI QERApp_DeleteFace(void* pv, int nFaceIndex)
+{
+  int n = 0;
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    face_t *pPrev = pBrush->brush_faces;
+    for (face_t *f = pBrush->brush_faces; f; f = f->next)
+    {
+      if (n == nFaceIndex)
+      {
+        pPrev->next = f->next;
+        Face_Free (f);
+        Sys_MarkMapModified();    // PGM
+        return;
+      }
+      n++;
+      pPrev = f;
+    }
+  }
+}
+
+//==========
+//PGM
+void WINAPI QERApp_BuildBrush (void* pv)
+{
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    Brush_Build(pBrush);
+    Sys_UpdateWindows(W_ALL);
+  }
+}
+
+//Timo : another version with bConvert flag
+//++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
+void WINAPI QERApp_BuildBrush2 (void* pv, int bConvert)
+{
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    Brush_Build( pBrush, true, true, bConvert );
+    Sys_UpdateWindows(W_ALL);
+  }
+}
+
+void WINAPI QERApp_SelectBrush (void* pv)
+{
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    Select_Brush(pBrush, false);
+    Sys_UpdateWindows(W_ALL);
+  }
+
+}
+
+void WINAPI QERApp_DeselectBrush (void* pv)
+{
+  // FIXME - implement this!
+}
+
+void WINAPI QERApp_ResetPlugins()
+{
+  g_pParentWnd->OnPluginsRefresh();
+}
+
+void WINAPI QERApp_DeselectAllBrushes ()
+{
+  Select_Deselect();
+  Sys_UpdateWindows(W_ALL);
+}
+//PGM
+//==========
+
+void WINAPI QERApp_TextureBrush(void* pv, char* pName)
+{
+  brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+  if (pBrush != NULL)
+  {
+    for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+    {
+      //strcpy(f->texdef.name, pName);
+      f->texdef.SetName(pName);
+    }
+    Sys_MarkMapModified();    // PGM
+  }
+}
+
+int WINAPI QERApp_SelectedBrushCount()
+{
+  int n = 0;
+  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+  {
+    n++;
+  }
+  return n;
+}
+
+int WINAPI QERApp_ActiveBrushCount()
+{
+  int n = 0;
+  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+  {
+    n++;
+  }
+  return n;
+}
+
+int WINAPI QERApp_AllocateSelectedBrushHandles()
+{
+  int n = 0;
+  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+  {
+    n++;
+    g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
+  }
+  return n;
+}
+
+int WINAPI QERApp_AllocateActiveBrushHandles()
+{
+  int n = 0;
+  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+  {
+    n++;
+    g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
+  }
+  return n;
+}
+
+void WINAPI QERApp_ReleaseSelectedBrushHandles()
+{
+  g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
+  Sys_UpdateWindows(W_ALL);
+}
+
+void WINAPI QERApp_ReleaseActiveBrushHandles()
+{
+  g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
+  Sys_UpdateWindows(W_ALL);
+}
+
+void* WINAPI QERApp_GetActiveBrushHandle(int nIndex)
+{
+  if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
+  {
+    return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
+  }
+  return NULL;
+}
+
+void* WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
+{
+  if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
+  {
+    return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
+  }
+  return NULL;
+}
+
+int WINAPI QERApp_TextureCount()
+{
+  //++timo TODO: replace by QERApp_GetActiveShaderCount and verify
+  Texture_StartPos ();
+  int x, y;
+  int n = 0;
+  while (1)
+  {
+    IShader *pShader = Texture_NextPos (&x, &y);
+    if (!pShader)
+      break;
+    n++;
+  }
+  return n;
+}
+
+char* WINAPI QERApp_GetTexture(int nIndex)
+{
+  //++timo TODO: replace by QERApp_ActiveShader_ForIndex
+  // these funcs would end up being provided for backward compatibility
+  static char name[QER_MAX_NAMELEN];
+  Texture_StartPos ();
+  int x, y;
+  int n = 0;
+  while (1)
+  {
+    IShader *pShader = Texture_NextPos (&x, &y);
+    if (!pShader)
+      break;
+    if (n == nIndex)
+    {
+      strcpy(name, pShader->getName());
+      return name;
+    }
+    n++;
+  }
+  return NULL;
+}
+
+char* WINAPI QERApp_GetCurrentTexture()
+{
+  static char current_tex[1024];
+  strcpy(current_tex,g_qeglobals.d_texturewin.texdef.GetName());
+  return current_tex;
+}
+
+void WINAPI QERApp_SetCurrentTexture(char* strName)
+{
+  //++timo hu ?? tex is not initialized ?? can be any value ..
+  texdef_t tex;
+  //++timo added a brushprimit_texdef ..
+  // smthg to be done here
+  brushprimit_texdef_t brushprimit_tex;
+  //strcpy(tex.name, strName);
+  tex.SetName(strName);
+  Texture_SetTexture(&tex,&brushprimit_tex);
+}
+
+int WINAPI QERApp_GetEClassCount()
+{
+  int n = 0;
+  for (eclass_t *e = eclass ; e ; e = e->next)
+  {
+    n++;
+  }
+  return n;
+}
+
+char* WINAPI QERApp_GetEClass(int nIndex)
+{
+  int n = 0;
+  for (eclass_t *e = eclass ; e ; e = e->next)
+  {
+    if (n == nIndex)
+    {
+      return e->name;
+    }
+  }
+  return NULL;
+}
+
+// v1.70 code
+// world_entity holds the worldspawn and is indexed as 0
+// other entities are in the entities doubly linked list
+// QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
+int WINAPI QERApp_GetEntityCount()
+{
+  int n = 1;
+  for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
+  {
+    n++;
+  }
+  return n;
+}
+
+// We don't store entities in CPtrArray, we need to walk the list
+void* WINAPI QERApp_GetEntityHandle(int nIndex)
+{
+  if (nIndex==0)
+    // looks for the worldspawn
+    return static_cast<void*>(world_entity);
+  entity_t *pe = &entities;
+  int n = 0;
+  while ( n < nIndex )
+  {
+    pe = pe->next;
+    n++;
+  }
+  return static_cast<void*>(pe);
+}
+
+epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )
+{
+  epair_t *e = (epair_t*)qmalloc (sizeof(*e));
+  e->key = (char*)qmalloc(strlen(key)+1);
+  strcpy (e->key, key);
+  e->value = (char*)qmalloc(strlen(val)+1);
+  strcpy (e->value, val);
+  return e;
+}
+
+/*
+IEpair* WINAPI QERApp_IEpairForEntityHandle(void *vp)
+{
+  entity_t *pe = static_cast<entity_t *>(vp);
+  CEpairsWrapper *pEp = new CEpairsWrapper(pe);
+  pEp->IncRef();
+  return pEp;
+}
+
+IEpair* WINAPI QERApp_IEpairForProjectKeys()   
+{
+  CEpairsWrapper *pEp = new CEpairsWrapper(g_qeglobals.d_project_entity);
+  pEp->IncRef();
+  return pEp;
+}
+*/
+
+int WINAPI QERApp_AllocateEntityBrushHandles(void* vp)
+{
+  entity_t *pe = static_cast<entity_t *>(vp);
+  int n = 0;
+  if (!pe->brushes.onext)
+    return 0;
+  g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
+  for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
+  {
+    n++;
+    g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
+  }
+  return n;
+}
+
+void WINAPI QERApp_ReleaseEntityBrushHandles()
+{
+  g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
+}
+
+void* WINAPI QERApp_GetEntityBrushHandle(int nIndex)
+{
+  if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
+    return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
+  return NULL;
+}
+
+// FIXME TTimo that entity handles thing sucks .. we should get rid of it ..
+
+void* WINAPI QERApp_CreateEntityHandle()
+{
+  entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
+  pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
+  g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<void*>(pe));
+  return static_cast<void*>(pe);
+}
+
+// the vpBrush needs to be in m_BrushHandles
+//++timo we don't have allocation nor storage for vpEntity, no checks for this one
+void WINAPI QERApp_CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
+{
+  g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
+  return;
+}
+
+const char* QERApp_ReadProjectKey(const char* key)
+{
+  return ValueForKey(g_qeglobals.d_project_entity, key);
+}
+
+#ifdef USEPLUGINENTITIES
+
+int WINAPI QERApp_ScanFileForEClass(char *filename )
+{
+  // set single class parsing
+  parsing_single = true;
+  Eclass_ScanFile(filename);
+  if (eclass_found)
+  {
+    eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
+    return 1;
+  }
+  return 0;
+}
+#endif // USEPLUGINENTITIES
+
+// the vpBrush needs to be in m_BrushHandles
+//++timo add a debug check to see if we found the brush handle
+// NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
+// links the brush to its entity, everything else is done when commiting the entity to the map
+void CPlugInManager::CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
+{
+  brush_t* pb;
+  entity_t* pe;
+  for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
+  {
+    if (vpBrush == m_BrushHandles.GetAt(i))
+    {
+      m_BrushHandles.RemoveAt(i);
+      pb = reinterpret_cast<brush_t*>(vpBrush);
+      pe = reinterpret_cast<entity_t *>(vpEntity);
+      Entity_LinkBrush (pe, pb);
+    }
+  }
+  Sys_UpdateWindows(W_ALL);
+}
+
+// the vpEntity must be in m_EntityHandles
+void WINAPI QERApp_CommitEntityHandleToMap(void* vpEntity)
+{
+  g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
+  return;
+}
+
+int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
+{
+  int nSize = vfsLoadFile(pLocation, buffer, 0);
+  return nSize;
+}
+
+char * WINAPI QERApp_ExpandReletivePath (char *p)
+{
+  return ExpandReletivePath(p);
+}
+
+qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
+{
+  // if the texture is not loaded yet, this call will get it loaded
+  // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_xxxBase GL context
+  // the plugin may set the GL context to whatever he likes, but then load would fail
+  // NOTE: is context switching time-consuming? then maybe the plugin could handle the context
+  // switch and only add a sanity check in debug mode here
+  // read current context
+  gtk_glwidget_make_current (g_qeglobals_gui.d_glBase);
+
+  //++timo debugging
+  Sys_Printf("WARNING: QERApp_Texture_ForName ... don't call that!!\n");
+  qtexture_t* qtex = QERApp_Texture_ForName2( name );
+  return qtex;
+}
+
+char* QERApp_Token()
+{
+  return token;
+}
+
+int QERApp_ScriptLine()
+{
+  return scriptline;
+}
+
+// we save the map and return the name .. either .map or .reg to support region compiling
+char* QERApp_GetMapName()
+{
+  static char name[PATH_MAX];
+  SaveWithRegion (name);
+  return name;
+}
+
+void CPlugInManager::CommitEntityHandleToMap(void* vpEntity)
+{
+  entity_t *pe;
+  eclass_t *e;
+  brush_t   *b;
+  vec3_t mins,maxs;
+  bool has_brushes;
+  for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
+  {
+    if (vpEntity == m_EntityHandles.GetAt(i))
+    {
+      m_EntityHandles.RemoveAt(i);
+      pe = reinterpret_cast<entity_t*>(vpEntity);
+      // fill additional fields
+      // straight copy from Entity_Parse
+      // entity_t::origin
+      GetVectorForKey (pe, "origin", pe->origin);
+      // entity_t::eclass
+      if (pe->brushes.onext == &pe->brushes)
+        has_brushes = false;
+      else
+        has_brushes = true;
+      e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
+      pe->eclass = e;
+      // fixedsize
+      if (e->fixedsize)
+      {
+        if (pe->brushes.onext != &pe->brushes)
+        {
+          Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
+        }
+        // create a custom brush
+        VectorAdd(e->mins, pe->origin, mins);
+        VectorAdd(e->maxs, pe->origin, maxs);
+/*
+        float a = 0;
+        if (e->nShowFlags & ECLASS_MISCMODEL)
+        {
+          char* p = ValueForKey(pe, "model");
+          if (p != NULL && strlen(p) > 0)
+          {
+            vec3_t vMin, vMax;
+            a = FloatForKey (pe, "angle");
+            if (GetCachedModel(pe, p, vMin, vMax))
+            {
+              // create a custom brush
+              VectorAdd (pe->md3Class->mins, pe->origin, mins);
+              VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
+            }
+          }
+        }
+*/
+        b = Brush_Create (mins, maxs, &e->texdef);
+/*
+        if (a)
+        {
+          vec3_t vAngle;
+          vAngle[0] = vAngle[1] = 0;
+          vAngle[2] = a;
+          Brush_Rotate(b, vAngle, pe->origin, false);
+        }
+*/
+        b->owner = pe;
+
+        b->onext = pe->brushes.onext;
+        b->oprev = &pe->brushes;
+        pe->brushes.onext->oprev = b;
+        pe->brushes.onext = b;
+      } else
+      { // brush entity
+        if (pe->brushes.next == &pe->brushes)
+          Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
+      }
+
+      // add brushes to the active brushes list
+      // and build them along the way
+      for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
+      {
+        // convert between old brushes and brush primitive
+        if (g_qeglobals.m_bBrushPrimitMode)
+        {
+          // we only filled the shift scale rot fields, needs conversion
+          Brush_Build( b, true, true, true );
+        } else
+        {
+          // we are using old brushes
+          Brush_Build( b );
+        }
+        b->next = active_brushes.next;
+        active_brushes.next->prev = b;
+        b->prev = &active_brushes;
+        active_brushes.next = b;
+      }
+
+      // handle worldspawn entities
+      // if worldspawn has no brushes, use the new one
+      if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
+      {
+        if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
+        {
+          // worldspawn already has brushes
+          Sys_Printf ("Commiting worldspawn as func_group\n");
+          SetKeyValue(pe, "classname", "func_group");
+          // add the entity to the end of the entity list
+          pe->next = &entities;
+          pe->prev = entities.prev;
+          entities.prev->next = pe;
+          entities.prev = pe;
+          g_qeglobals.d_num_entities++;
+        } else
+        {
+          // there's a worldspawn with no brushes, we assume the map is empty
+          if ( world_entity )
+          {
+            Entity_Free( world_entity );
+            world_entity = pe;
+          } else
+            Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
+        }
+      } else
+      {
+        // add the entity to the end of the entity list
+        pe->next = &entities;
+        pe->prev = entities.prev;
+        entities.prev->next = pe;
+        entities.prev = pe;
+        g_qeglobals.d_num_entities++;
+      }
+    }
+  }
+}
+
+void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
+{
+  g_bScreenUpdates = bScreenUpdates; 
+}
+
+texturewin_t* QERApp_QeglobalsTexturewin()
+{
+  return &g_qeglobals.d_texturewin;
+}
+
+texdef_t* QERApp_QeglobalsSavedinfo_SIInc()
+{
+  return &g_qeglobals.d_savedinfo.m_SIIncrement;
+}
+
+patchMesh_t* QERApp_GetSelectedPatch( )
+{
+  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+  {
+    if (pb->patchBrush)
+    {
+      return pb->pPatch;
+    }
+  }
+#ifdef _DEBUG
+  Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
+#endif
+  return NULL;
+}
+
+const char* WINAPI QERApp_GetGamePath()
+{
+  return g_pGameDescription->mEnginePath.GetBuffer();
+}
+
+/*!
+\todo the name of this API should prolly be changed
+would also need to prompt g_strAppPath / g_strGameToolsPath independently?
+*/
+// SPoG
+// changed g_strGameToolsPath to g_strAppPath
+const char* WINAPI QERApp_GetQERPath()
+{
+  return g_strAppPath.GetBuffer();
+}
+
+const char* WINAPI QERApp_GetGameFile()
+{
+  // FIXME: Arnout: temp solution, need proper 'which game is this' indicator or a different solution for plugins/modules
+  return g_pGameDescription->mGameFile.GetBuffer();
+}
+
+// patches in/out -----------------------------------
+int WINAPI QERApp_AllocateActivePatchHandles()
+{
+  return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
+}
+
+// Grid Size
+float QERApp_QeglobalsGetGridSize()
+{
+  return g_qeglobals.d_gridsize;
+}
+
+int CPlugInManager::AllocateActivePatchHandles()
+{
+  int n = 0;
+  for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+  {
+    if (pb->patchBrush)
+    {
+      n++;
+      m_PatchesHandles.Add(pb);
+    }
+  }
+  return n;
+}
+
+int WINAPI QERApp_AllocateSelectedPatchHandles()
+{
+  return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
+}
+
+int CPlugInManager::AllocateSelectedPatchHandles()
+{
+  int n = 0;
+  // change mode
+  PatchesMode = ESelectedPatches;
+  for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+  {
+    if (pb->patchBrush)
+    {
+      n++;
+      m_PatchesHandles.Add(pb);
+    }
+  }
+  return n;
+}
+
+void WINAPI QERApp_ReleasePatchHandles()
+{
+  g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
+}
+
+patchMesh_t* WINAPI QERApp_GetPatchData(int index)
+{
+  static patchMesh_t patch;
+  patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
+  if (pPatch)
+  {
+    memcpy( &patch, pPatch, sizeof(patchMesh_t) );
+    return &patch;
+  }
+  return NULL;
+}
+
+patchMesh_t* WINAPI QERApp_GetPatchHandle(int index)
+{
+  return g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
+}
+
+void WINAPI QERApp_DeletePatch(int index)
+{
+  patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
+  if (pPatch)
+  {
+    brush_t *pb = pPatch->pSymbiot;
+    Patch_Delete( pPatch );
+    if (pb)
+      Brush_Free( pb );
+  }
+#ifdef _DEBUG
+  Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
+#endif
+}
+
+int WINAPI QERApp_CreatePatchHandle()
+{
+  return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
+}
+
+int CPlugInManager::CreatePatchHandle()
+{
+  // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
+  patchMesh_t *pPatch = MakeNewPatch();
+  m_PluginPatches.Add( pPatch );
+  // change mode
+  PatchesMode = EAllocatedPatches;
+  return m_PluginPatches.GetSize()-1;
+}
+
+void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
+{
+#ifdef DBG_PAPI
+  Sys_Printf ("QERApp_CommitPatchHandleToMap %i..", index);
+#endif
+  g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
+#ifdef DBG_PAPI
+  Sys_Printf ("Done\n");
+#endif
+}
+
+void WINAPI QERApp_CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void* vpEntity)
+{
+#ifdef DBG_PAPI
+  Sys_Printf ("QERApp_CommitPatchHandleToEntity %i..", index);
+#endif
+  g_pParentWnd->GetPlugInMgr().CommitPatchHandleToEntity(index, pMesh, texName, vpEntity);
+#ifdef DBG_PAPI
+  Sys_Printf ("Done\n");
+#endif
+}
+
+void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
+{
+  if (PatchesMode==EAllocatedPatches)
+  {
+    patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
+    memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
+    // patch texturing, if none given use current texture
+    if (texName)
+      pPatch->pShader = QERApp_Shader_ForName (texName);
+    else
+      pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
+    pPatch->d_texture = pPatch->pShader->getTexture();
+    pPatch->pShader->IncRef();
+    g_bScreenUpdates = false;
+    // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
+    brush_t *pb = AddBrushForPatch( pPatch, true );
+    Select_Brush( pb );
+    g_bScreenUpdates = true;
+    Sys_UpdateWindows(W_ALL);
+  } else
+  {
+    brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
+    patchMesh_t *pPatch = pBrush->pPatch;
+    pPatch->width = pMesh->width;
+    pPatch->height = pMesh->height;
+    pPatch->contents = pMesh->contents;
+    pPatch->flags = pMesh->flags;
+    pPatch->value = pMesh->value;
+    pPatch->type = pMesh->type;
+    memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
+    pPatch->bDirty = true;
+  }
+}
+
+void CPlugInManager::CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity)
+{
+  entity_t* pe = reinterpret_cast<entity_t *>(vpEntity);
+
+  if (PatchesMode==EAllocatedPatches)
+  {
+    patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
+    memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
+    // patch texturing, if none given use current texture
+    if (texName)
+      pPatch->pShader = QERApp_Shader_ForName (texName);
+    else
+      pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
+    pPatch->d_texture = pPatch->pShader->getTexture();
+    pPatch->pShader->IncRef();
+    g_bScreenUpdates = false;
+    brush_t *pb = AddBrushForPatch( pPatch, false );  // false, sp have to do the brush building/entity linking ourself
+    Brush_AddToList (pb, &active_brushes);
+    Entity_LinkBrush (pe, pb);
+    Brush_Build( pb );
+    g_bScreenUpdates = true;
+    Sys_UpdateWindows(W_ALL);
+  } else
+  {
+    brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
+    patchMesh_t *pPatch = pBrush->pPatch;
+    pPatch->width = pMesh->width;
+    pPatch->height = pMesh->height;
+    pPatch->contents = pMesh->contents;
+    pPatch->flags = pMesh->flags;
+    pPatch->value = pMesh->value;
+    pPatch->type = pMesh->type;
+    memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
+    pPatch->bDirty = true;
+  }
+}
+
+#if 0
+
+#if defined (__linux__) || defined (__APPLE__)
+  #include <gdk/gdkx.h>
+
+XVisualInfo* QEX_ChooseVisual (bool zbuffer)
+{
+  int attrlist_z[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0};
+  int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0};
+  XVisualInfo *vi;
+  Display *dpy;
+
+  dpy = GDK_DISPLAY();
+  if (dpy == NULL)
+    Error ("OpenGL fatal error: Cannot get display.\n");
+  vi = qglXChooseVisual(dpy, DefaultScreen(dpy), zbuffer ? attrlist_z : attrlist);
+  if (vi == NULL)
+    Error ("OpenGL fatal error: glXChooseVisual failed.\n");
+
+  return vi;
+}
+#endif
+
+#endif
+
+/*!
+\todo FIXME TTimo broken most likely
+actually .. that's not enough, you have to go down for the game pack specific?
+*/
+const char* WINAPI QERApp_ProfileGetDirectory ()
+{
+  return g_strTempPath;
+}
+
+GtkWidget* WINAPI QERApp_GetQeGlobalsGLWidget ()
+{
+  return g_qeglobals_gui.d_glBase;
+}
+
+qboolean WINAPI BrushPrimitMode ()
+{
+  return g_qeglobals.m_bBrushPrimitMode;
+}
+
+brush_t* WINAPI QERApp_ActiveBrushes()
+{
+  return &active_brushes;
+}
+
+brush_t* WINAPI QERApp_SelectedBrushes()
+{
+  return &selected_brushes;
+}
+
+brush_t* WINAPI QERApp_FilteredBrushes()
+{
+  return &filtered_brushes;
+}
+
+CPtrArray* WINAPI QERApp_LstSkinCache()
+{
+  return &g_lstSkinCache;
+}
+
+qtexture_t** WINAPI QERApp_QTextures()
+{
+  return &g_qeglobals.d_qtextures;
+}
+
+GHashTable* WINAPI QERApp_QTexmap()
+{
+  return g_qeglobals.d_qtexmap;
+}
+
+// a simplified version of Texture_SetTexture
+void WINAPI QERApp_Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef)
+{
+  Texture_SetTexture (texdef, brushprimit_texdef);
+}
+
+void QERApp_LoadImage (const char *name, unsigned char **pic, int *width, int *height)
+{
+  g_ImageManager.LoadImage(name, pic, width, height);
+}
+
+unsigned long QERApp_GetTickCount()
+{
+#ifdef _WIN32
+       return GetTickCount();
+#else
+  struct timeval      tp;
+  struct timezone     tzp;
+  static int          basetime=0;
+
+  gettimeofday(&tp, &tzp);
+  if (!basetime)
+    basetime = tp.tv_sec;
+  return (tp.tv_sec-basetime) + tp.tv_usec/1000;       
+#endif
+}
+
+bool CSynapseClientRadiant::RequestAPI(APIDescriptor_t *pAPI)
+{
+  if (!strcmp(pAPI->major_name, RADIANT_MAJOR))
+  {
+    _QERFuncTable_1* pTable= static_cast<_QERFuncTable_1*>(pAPI->mpTable);
+    pTable->m_pfnCreateBrush = &QERApp_CreateBrush;
+    pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;
+    pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;
+    pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;
+    pTable->m_pfnAddFace = &QERApp_AddFace;
+    pTable->m_pfnAddFaceData = &QERApp_AddFaceData;
+    pTable->m_pfnGetFaceData = &QERApp_GetFaceData;
+    pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;
+    pTable->m_pfnSetFaceData = &QERApp_SetFaceData;
+    pTable->m_pfnDeleteFace = &QERApp_DeleteFace;
+    pTable->m_pfnTextureBrush = &QERApp_TextureBrush;
+    pTable->m_pfnBuildBrush = &QERApp_BuildBrush;           // PGM
+    pTable->m_pfnSelectBrush = &QERApp_SelectBrush;         // PGM
+    pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush;       // PGM
+    pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes;   // PGM
+    pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;
+    pTable->m_pfnGetPoints = &QERApp_GetPoints;
+    pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;
+    pTable->m_pfnAllocateSelectedBrushHandles  = &QERApp_AllocateSelectedBrushHandles;
+    pTable->m_pfnReleaseSelectedBrushHandles  = &QERApp_ReleaseSelectedBrushHandles;
+    pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;
+    pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;
+    pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;
+    pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;
+    pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;
+    pTable->m_pfnTextureCount = &QERApp_TextureCount;
+    pTable->m_pfnGetTexture = &QERApp_GetTexture;
+    pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;
+    pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;
+    pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;
+    pTable->m_pfnGetEClass = &QERApp_GetEClass;
+    pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;
+    pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;
+    pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;
+    pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;
+    pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;
+    pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;
+    pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;
+    pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;
+    pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;
+    pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;
+    pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;
+    pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;
+    pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;
+       pTable->m_pfnGetDispatchParams = &QERApp_GetDispatchParams;
+//    pTable->m_pfnRequestInterface = &QERApp_RequestInterface;
+    pTable->m_pfnError = &Error;
+    pTable->m_pfnLoadFile = &QERApp_LoadFile;
+    pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;
+    pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;
+    pTable->m_pfnHasShader = QERApp_HasShader;
+    pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;
+    pTable->m_pfnGetGamePath = &QERApp_GetGamePath;
+    pTable->m_pfnGetQERPath = &QERApp_GetQERPath;
+    pTable->m_pfnGetGameFile = &QERApp_GetGameFile;
+    pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;
+    pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;
+    pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;
+    pTable->m_pfnGetPatchData = &QERApp_GetPatchData;
+    pTable->m_pfnGetPatchHandle = &QERApp_GetPatchHandle;
+    pTable->m_pfnDeletePatch = &QERApp_DeletePatch;
+    pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;
+    pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;
+    pTable->m_pfnLoadImage = &QERApp_LoadImage;
+    pTable->m_pfnMessageBox = &gtk_MessageBox;
+    pTable->m_pfnFileDialog = &file_dialog;
+    pTable->m_pfnColorDialog = &color_dialog;
+    pTable->m_pfnDirDialog = &dir_dialog;
+    pTable->m_pfnLoadBitmap = &load_plugin_bitmap;
+    pTable->m_pfnProfileGetDirectory = &QERApp_ProfileGetDirectory;
+    pTable->m_pfnProfileSaveInt = &profile_save_int;
+    pTable->m_pfnProfileSaveString = &profile_save_string;
+    pTable->m_pfnProfileLoadInt = &profile_load_int;
+    pTable->m_pfnProfileLoadString = &profile_load_string;
+    pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;
+    pTable->m_pfnSysPrintf = &Sys_Printf;
+    pTable->m_pfnSysFPrintf = &Sys_FPrintf;
+    pTable->m_pfnSysBeginWait = &Sys_BeginWait;
+    pTable->m_pfnSysEndWait = &Sys_EndWait;
+    pTable->m_pfnSys_SetTitle = &Sys_SetTitle;
+    pTable->m_pfnSysBeep = &Sys_Beep;
+    pTable->m_pfnSys_Status = &Sys_Status;
+    pTable->m_pfnMapFree = &Map_Free;
+    pTable->m_pfnMapNew = &Map_New;
+    pTable->m_pfnMapBuildBrushData = &Map_BuildBrushData;
+    pTable->m_pfnMap_IsBrushFiltered = &Map_IsBrushFiltered;
+    pTable->m_pfnMapStartPosition = &Map_StartPosition;
+    pTable->m_pfnMapRegionOff = &Map_RegionOff;
+    pTable->m_pfnSetBuildWindingsNoTexBuild = &Brush_SetBuildWindingsNoTexBuild;
+    pTable->m_pfnPointFileClear = &Pointfile_Clear;
+    pTable->m_pfnCSG_MakeHollow = &CSG_MakeHollow;
+    pTable->m_pfnRegionSpawnPoint = &Region_SpawnPoint;
+    pTable->m_pfnQGetTickCount = &QERApp_GetTickCount;
+    pTable->m_pfnGetModelCache = &GetModelCache;
+    pTable->m_pfnGetFileTypeRegistry = &GetFileTypeRegistry;
+    pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;
+    pTable->m_pfnGetMapName = &QERApp_GetMapName;
+    pTable->m_pfnFilterAdd = &FilterCreate;
+    pTable->m_pfnFiltersActivate = &FiltersActivate;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, SCRIPLIB_MAJOR))
+  {
+    _QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pAPI->mpTable);
+    pScripLibTable->m_pfnGetToken = &GetToken;
+    pScripLibTable->m_pfnGetTokenExtra = &GetTokenExtra;
+    pScripLibTable->m_pfnToken = &QERApp_Token;
+    pScripLibTable->m_pfnUnGetToken = &UngetToken;
+    pScripLibTable->m_pfnStartTokenParsing = &StartTokenParsing;
+    pScripLibTable->m_pfnScriptLine = &QERApp_ScriptLine;
+    pScripLibTable->m_pfnTokenAvailable = &TokenAvailable;
+    pScripLibTable->m_pfnCOM_Parse = &COM_Parse;
+    pScripLibTable->m_pfnGet_COM_Token = &Get_COM_Token;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, BRUSH_MAJOR))
+  {
+    _QERBrushTable *pBrushTable = static_cast<_QERBrushTable *>(pAPI->mpTable);
+    pBrushTable->m_pfnBP_MessageBox = &BP_MessageBox;
+    pBrushTable->m_pfnBrush_AddToList = &Brush_AddToList;
+    pBrushTable->m_pfnBrush_Build = &Brush_Build;
+    pBrushTable->m_pfnBrush_Create = &Brush_Create;
+    pBrushTable->m_pfnBrush_Free = &Brush_Free;
+    pBrushTable->m_pfnBrush_Rotate = &Brush_Rotate;
+    pBrushTable->m_pfnBrushAlloc = &Brush_Alloc;
+    pBrushTable->m_pfnFace_Alloc = &Face_Alloc;
+    pBrushTable->m_pfnHasModel = NULL;// &HasModel;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, APPSHADERS_MAJOR))
+  {
+    _QERAppShadersTable *pShadersTable = static_cast<_QERAppShadersTable*>(pAPI->mpTable);
+    pShadersTable->m_pfnQTextures = QERApp_QTextures;
+    pShadersTable->m_pfnQTexmap = QERApp_QTexmap;
+    pShadersTable->m_pfnQeglobalsTexturewin = QERApp_QeglobalsTexturewin;
+    pShadersTable->m_pfnTexture_SetTexture = QERApp_Texture_SetTexture;
+    pShadersTable->m_pfnTexture_ShowInuse = Texture_ShowInuse;
+    pShadersTable->m_pfnBuildShaderList = &BuildShaderList;
+    pShadersTable->m_pfnPreloadShaders = &PreloadShaders;
+    
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, QGL_MAJOR))
+  {
+    _QERQglTable *pQglTable = static_cast<_QERQglTable *>(pAPI->mpTable);
+    pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;
+    pQglTable->m_pfn_qglBegin = qglBegin;
+    pQglTable->m_pfn_qglBindTexture = qglBindTexture;
+    pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;
+    pQglTable->m_pfn_qglCallList = qglCallList;
+    pQglTable->m_pfn_qglCallLists = qglCallLists;
+    pQglTable->m_pfn_qglClear = qglClear;
+    pQglTable->m_pfn_qglClearColor = qglClearColor;
+    pQglTable->m_pfn_qglClearDepth = qglClearDepth;
+    pQglTable->m_pfn_qglColor3f = qglColor3f;
+    pQglTable->m_pfn_qglColor3fv = qglColor3fv;
+    pQglTable->m_pfn_qglColor4f = qglColor4f;
+    pQglTable->m_pfn_qglColor4fv = qglColor4fv;
+       pQglTable->m_pfn_qglColor4ubv = qglColor4ubv;
+    pQglTable->m_pfn_qglColorPointer = qglColorPointer;
+    pQglTable->m_pfn_qglCullFace = qglCullFace;
+    pQglTable->m_pfn_qglDepthFunc = qglDepthFunc;
+    pQglTable->m_pfn_qglDepthMask = qglDepthMask;
+    pQglTable->m_pfn_qglDisable = qglDisable;
+    pQglTable->m_pfn_qglDisableClientState = qglDisableClientState;
+    pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;
+    pQglTable->m_pfn_qglDeleteTextures = qglDeleteTextures;
+    pQglTable->m_pfn_qglDrawElements = qglDrawElements;
+    pQglTable->m_pfn_qglEnable = qglEnable;
+    pQglTable->m_pfn_qglEnableClientState = qglEnableClientState;      
+    pQglTable->m_pfn_qglEnd = qglEnd;
+    pQglTable->m_pfn_qglEndList = qglEndList;
+    pQglTable->m_pfn_qglFogf = qglFogf;
+    pQglTable->m_pfn_qglFogfv = qglFogfv;
+    pQglTable->m_pfn_qglFogi = qglFogi;
+    pQglTable->m_pfn_qglGenLists = qglGenLists;
+    pQglTable->m_pfn_qglGenTextures = qglGenTextures;
+    pQglTable->m_pfn_qglGetDoublev = qglGetDoublev;
+    pQglTable->m_pfn_qglGetIntegerv = qglGetIntegerv;
+    pQglTable->m_pfn_qglHint = qglHint;
+    pQglTable->m_pfn_qglLightfv = qglLightfv;
+    pQglTable->m_pfn_qglLineStipple = qglLineStipple;
+    pQglTable->m_pfn_qglLineWidth = qglLineWidth;
+    pQglTable->m_pfn_qglListBase = qglListBase;
+    pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;
+    pQglTable->m_pfn_qglMaterialf = qglMaterialf;
+    pQglTable->m_pfn_qglMaterialfv = qglMaterialfv;
+    pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;
+    pQglTable->m_pfn_qglMultMatrixf = qglMultMatrixf;
+    pQglTable->m_pfn_qglNewList = qglNewList;
+    pQglTable->m_pfn_qglNormal3f = qglNormal3f;
+    pQglTable->m_pfn_qglNormal3fv = qglNormal3fv;
+    pQglTable->m_pfn_qglNormalPointer = qglNormalPointer;
+    pQglTable->m_pfn_qglOrtho = qglOrtho;
+    pQglTable->m_pfn_qglPointSize = qglPointSize;
+    pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;
+    pQglTable->m_pfn_qglPopAttrib = qglPopAttrib;
+    pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;
+    pQglTable->m_pfn_qglPushAttrib = qglPushAttrib;
+    pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;
+    pQglTable->m_pfn_qglRasterPos3fv = qglRasterPos3fv;
+    pQglTable->m_pfn_qglRotated = qglRotated;
+    pQglTable->m_pfn_qglRotatef = qglRotatef;
+    pQglTable->m_pfn_qglScalef = qglScalef;
+    pQglTable->m_pfn_qglScissor = qglScissor;
+    pQglTable->m_pfn_qglShadeModel = qglShadeModel;
+    pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;
+    pQglTable->m_pfn_qglTexCoord2fv = qglTexCoord2fv;
+    pQglTable->m_pfn_qglTexCoordPointer = qglTexCoordPointer;
+    pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;
+    pQglTable->m_pfn_qglTexGenf = qglTexGenf;
+    pQglTable->m_pfn_qglTexImage1D = qglTexImage1D;
+    pQglTable->m_pfn_qglTexImage2D = qglTexImage2D;
+    pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;
+    pQglTable->m_pfn_qglTexParameterfv = qglTexParameterfv;
+    pQglTable->m_pfn_qglTexParameteri = qglTexParameteri;
+    pQglTable->m_pfn_qglTexParameteriv = qglTexParameteriv;
+    pQglTable->m_pfn_qglTexSubImage1D = qglTexSubImage1D;
+    pQglTable->m_pfn_qglTexSubImage2D = qglTexSubImage2D;
+    pQglTable->m_pfn_qglTranslated = qglTranslated;
+    pQglTable->m_pfn_qglTranslatef = qglTranslatef;
+    pQglTable->m_pfn_qglVertex2f = qglVertex2f;
+    pQglTable->m_pfn_qglVertex3f = qglVertex3f;
+    pQglTable->m_pfn_qglVertex3fv = qglVertex3fv;
+    pQglTable->m_pfn_qglVertexPointer = qglVertexPointer;
+    pQglTable->m_pfn_qglViewport = qglViewport;
+
+    pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;
+
+    pQglTable->m_pfn_qgluPerspective = qgluPerspective;
+    pQglTable->m_pfn_qgluLookAt = qgluLookAt;
+    pQglTable->m_pfnHookGL2DWindow = QERApp_HookGL2DWindow;
+    pQglTable->m_pfnUnHookGL2DWindow = QERApp_UnHookGL2DWindow;
+    pQglTable->m_pfnHookGL3DWindow = QERApp_HookGL3DWindow;
+    pQglTable->m_pfnUnHookGL3DWindow = QERApp_UnHookGL3DWindow;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, DATA_MAJOR))
+  {
+    _QERAppDataTable *pDataTable = static_cast<_QERAppDataTable *>(pAPI->mpTable);
+    pDataTable->m_pfnActiveBrushes = QERApp_ActiveBrushes;
+    pDataTable->m_pfnSelectedBrushes = QERApp_SelectedBrushes;
+    pDataTable->m_pfnFilteredBrushes = QERApp_FilteredBrushes;
+    pDataTable->m_pfnLstSkinCache = QERApp_LstSkinCache;
+    
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, PATCH_MAJOR))
+  {
+    _QERPatchTable *pPatchTable = static_cast<_QERPatchTable *>(pAPI->mpTable);
+    pPatchTable->m_pfnPatch_Alloc = &Patch_Alloc;
+    pPatchTable->m_pfnAddBrushForPatch = &AddBrushForPatch;
+    pPatchTable->m_pfnMakeNewPatch = &MakeNewPatch;
+  
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, ECLASSMANAGER_MAJOR))
+  {
+    _EClassManagerTable *pEClassManTable = static_cast<_EClassManagerTable *>(pAPI->mpTable);
+    
+    pEClassManTable->m_pfnEclass_InsertAlphabetized = &Eclass_InsertAlphabetized;
+    pEClassManTable->m_pfnGet_Eclass_E = &Get_EClass_E;
+    pEClassManTable->m_pfnSet_Eclass_Found = &Set_Eclass_Found;
+    pEClassManTable->m_pfnGet_Parsing_Single = &Get_Parsing_Single;
+    pEClassManTable->m_pfnEClass_Create = &EClass_Create;
+    pEClassManTable->m_pfnEclass_ForName = &Eclass_ForName;
+  
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, SELECTEDFACE_MAJOR))
+  { 
+    _QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pAPI->mpTable);
+
+    pSelectedFaceTable->m_pfnGetSelectedFaceCount = &QERApp_GetSelectedFaceCount;
+    pSelectedFaceTable->m_pfnGetFaceBrush = &QERApp_GetSelectedFaceBrush;
+    pSelectedFaceTable->m_pfnGetFace = &QERApp_GetSelectedFace;
+    pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;
+    pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;
+    pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;
+    pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;
+    pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, APPSURFACEDIALOG_MAJOR))
+  {
+    _QERAppSurfaceTable *pSurfDialogTable = static_cast<_QERAppSurfaceTable *>(pAPI->mpTable);
+    pSurfDialogTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;
+    pSurfDialogTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;
+    pSurfDialogTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;
+    pSurfDialogTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;
+    pSurfDialogTable->m_pfnTexMatToFakeTexCoords = &TexMatToFakeTexCoords;
+    pSurfDialogTable->m_pfnConvertTexMatWithQTexture = &ConvertTexMatWithQTexture;
+    pSurfDialogTable->m_pfnFakeTexCoordsToTexMat = &FakeTexCoordsToTexMat;
+    pSurfDialogTable->m_pfnPatch_ResetTexturing = &Patch_ResetTexturing;
+    pSurfDialogTable->m_pfnPatch_FitTexturing = &Patch_FitTexturing;
+    pSurfDialogTable->m_pfnPatch_NaturalizeSelected = &Patch_NaturalizeSelected;
+    pSurfDialogTable->m_pfnPatch_GetTextureName = &Patch_GetTextureName;
+    pSurfDialogTable->m_pfnQE_SingleBrush = &QE_SingleBrush;
+    pSurfDialogTable->m_pfnIsBrushPrimitMode = &IsBrushPrimitMode;
+    pSurfDialogTable->m_pfnComputeAxisBase = &ComputeAxisBase;
+    pSurfDialogTable->m_pfnBPMatMul = &BPMatMul;
+    pSurfDialogTable->m_pfnEmitBrushPrimitTextureCoordinates = &EmitBrushPrimitTextureCoordinates;
+    pSurfDialogTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;
+    pSurfDialogTable->m_pfnSelect_FitTexture = &Select_FitTexture;
+    pSurfDialogTable->m_pfnQERApp_QeglobalsSavedinfo_SIInc = &QERApp_QeglobalsSavedinfo_SIInc;
+    pSurfDialogTable->m_pfnQeglobalsGetGridSize = &QERApp_QeglobalsGetGridSize;
+    pSurfDialogTable->m_pfnFaceList_FitTexture = &SI_FaceList_FitTexture;
+    pSurfDialogTable->m_pfnGetMainWindow = &SI_GetMainWindow;
+    pSurfDialogTable->m_pfnSetWinPos_From_Prefs = &SI_SetWinPos_from_Prefs;
+    pSurfDialogTable->m_pfnGetSelectedFaceCountfromBrushes = &SI_GetSelectedFaceCountfromBrushes;
+    pSurfDialogTable->m_pfnGetSelFacesTexdef = &SI_GetSelFacesTexdef;
+    pSurfDialogTable->m_pfnSetTexdef_FaceList = &SI_SetTexdef_FaceList;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, UNDO_MAJOR))
+  { 
+    _QERUndoTable *pUndoTable = static_cast<_QERUndoTable *>(pAPI->mpTable);
+
+    pUndoTable->m_pfnUndo_Start = &Undo_Start;
+    pUndoTable->m_pfnUndo_End = &Undo_End;
+    pUndoTable->m_pfnUndo_AddBrush = &Undo_AddBrush;
+    pUndoTable->m_pfnUndo_EndBrush = &Undo_EndBrush;
+    pUndoTable->m_pfnUndo_AddBrushList = &Undo_AddBrushList;
+    pUndoTable->m_pfnUndo_EndBrushList = &Undo_EndBrushList;
+    pUndoTable->m_pfnUndo_AddEntity = &Undo_AddEntity;
+    pUndoTable->m_pfnUndo_EndEntity = &Undo_EndEntity;
+    pUndoTable->m_pfnUndo_Undo = &Undo_Undo;                     // Nurail
+    pUndoTable->m_pfnUndo_Redo = &Undo_Redo;                     // Nurail
+    pUndoTable->m_pfnUndo_GetUndoId = &Undo_GetUndoId;           // Nurail
+    pUndoTable->m_pfnUndo_UndoAvailable = &Undo_UndoAvailable;   // Nurail
+    pUndoTable->m_pfnUndo_RedoAvailable = &Undo_RedoAvailable;   // Nurail
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, CAMERA_MAJOR))
+  {
+    _QERCameraTable *pCameraTable = static_cast<_QERCameraTable *>(pAPI->mpTable);
+
+    pCameraTable->m_pfnGetCamera = &QERApp_GetCamera;
+    pCameraTable->m_pfnSetCamera = &QERApp_SetCamera;
+    pCameraTable->m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, UI_MAJOR))
+  { 
+    _QERUITable *pUITable = static_cast<_QERUITable *>(pAPI->mpTable);
+
+    pUITable->m_pfnCreateGLWindow = QERApp_CreateGLWindow;
+    pUITable->m_pfnHookWindow = QERApp_HookWindow;
+    pUITable->m_pfnUnHookWindow = QERApp_UnHookWindow;
+    pUITable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;
+    pUITable->m_pfnHookListener = QERApp_HookListener;
+    pUITable->m_pfnUnHookListener = QERApp_UnHookListener;
+
+    return true;
+  }
+  if (!strcmp(pAPI->major_name, UIGTK_MAJOR))
+  { 
+    _QERUIGtkTable *pUIGtkTable = static_cast<_QERUIGtkTable *>(pAPI->mpTable);
+
+    pUIGtkTable->m_pfn_GetQeglobalsGLWidget = &QERApp_GetQeGlobalsGLWidget;
+    pUIGtkTable->m_pfn_glwidget_new = &gtk_glwidget_new;
+    pUIGtkTable-> m_pfn_glwidget_swap_buffers = &gtk_glwidget_swap_buffers;
+    pUIGtkTable->m_pfn_glwidget_make_current = &gtk_glwidget_make_current;
+    pUIGtkTable->m_pfn_glwidget_destroy_context = &gtk_glwidget_destroy_context;
+    pUIGtkTable->m_pfn_glwidget_create_context = &gtk_glwidget_create_context;
+#if 0
+    pUIGtkTable->m_pfn_glwidget_get_context = &gtk_glwidget_get_context;
+#endif
+
+    return true;
+  }
+
+  return false;
+}
+
+const char* CSynapseClientRadiant::GetInfo()
+{
+  return "Radiant - synapse core built " __DATE__ " " RADIANT_VERSION;
+}
+
+const char* CSynapseClientRadiant::GetName()
+{
+  return "core";
+}