]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/texwindow.cpp
* more translateable strings
[xonotic/netradiant.git] / radiant / texwindow.cpp
index 2e5c0fb90ef874c18d04601b3600adea25d2ad63..9e30e2d23d3e3c65b5aa077e2500a9523085e932 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-Copyright (C) 1999-2006 Id Software, Inc. and contributors.
+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.
 For a list of contributors, see the accompanying CONTRIBUTORS file.
 
 This file is part of GtkRadiant.
@@ -25,1062 +25,1261 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 // Leonardo Zide (leo@lokigames.com)
 //
 
 // Leonardo Zide (leo@lokigames.com)
 //
 
-#include "texwindow.h"
+/*!\todo
+Clean up texture menu.
+- Remove all global variables and use some objects instead.
+- Create an interface for a plugin to add texture menu items.
+- Make sure the interface is not dependent on gtk.
+*/
 
 
-#include "debugging/debugging.h"
-#include "warnings.h"
-
-#include "iimage.h"
-#include "ifilesystem.h"
-#include "ishaders.h"
-#include "iscriplib.h"
-#include "iselection.h"
-#include "iscenegraph.h"
-#include "itextures.h"
-#include "irender.h"
-#include "iundo.h"
-#include "igl.h"
-#include "iarchive.h"
-#include "moduleobserver.h"
-
-#include <set>
-
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkrange.h>
-#include <gtk/gtkframe.h>
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkvscrollbar.h>
-#include <gtk/gtkmenu.h>
-
-#include "generic/callback.h"
-#include "math/vector.h"
-#include "texturelib.h"
-#include "string/string.h"
-#include "shaderlib.h"
-#include "os/path.h"
-#include "stream/memstream.h"
-#include "stream/textfilestream.h"
-#include "stream/stringstream.h"
-#include "cmdlib.h"
+#ifdef _WIN32
+//#include <gdk/win32/gdkwin32.h>
+#include <gdk/gdkwin32.h>
+#endif
+#if defined (__linux__) || defined (__APPLE__)
+#include <gdk/gdkx.h>
+#include <dirent.h>
+#endif
+#include <gtk/gtk.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include "stdafx.h"
+#include "texwindow.h"
+#include "str.h"
+#include "missing.h"
 #include "texmanip.h"
 #include "texmanip.h"
-#include "textures.h"
-#include "convert.h"
-
-#include "gtkutil/menu.h"
-#include "gtkutil/nonmodal.h"
-#include "gtkutil/cursor.h"
-#include "gtkutil/widget.h"
-#include "gtkutil/glwidget.h"
-
-#include "error.h"
-#include "map.h"
-#include "qgl.h"
-#include "select.h"
-#include "brush_primit.h"
-#include "brushmanip.h"
-#include "patchmanip.h"
-#include "plugin.h"
-#include "qe3.h"
-#include "gtkdlgs.h"
-#include "gtkmisc.h"
-#include "mainframe.h"
-#include "findtexturedialog.h"
-#include "surfacedialog.h"
-#include "patchdialog.h"
-#include "groupdialog.h"
-#include "preferences.h"
-#include "shaders.h"
-#include "commands.h"
-
-
-
-bool TextureGroupsMenu_showWads()
-{
-  return !string_empty(g_pGameDescription->getKeyValue("show_wads"));
-}
 
 
-// globals for textures
-class TextureMenuName
-{
-  enum { c_menuNameLength = 64 };
-  char m_name[c_menuNameLength];
-public:
-  TextureMenuName(const char* name)
-  {
-    strncpy(m_name, name, c_menuNameLength - 1);
-    m_name[c_menuNameLength - 1] = '\0';
-  }
-  const char* c_str() const
-  {
-    return m_name;
-  }
-};
+#define        TYP_MIPTEX      68
+static unsigned        tex_palette[256];
 
 
-typedef std::vector<TextureMenuName> TextureMenuNames;
-TextureMenuNames texture_menunames;
+#define        FONT_HEIGHT     10
 
 
-const char* TextureGroupsMenu_GetName(std::size_t menunum)
-{
-  return texture_menunames[menunum].c_str();
-}
+//int          texture_mode = GL_NEAREST;
+//int          texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int          texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+//int          texture_mode = GL_LINEAR;
+//int          texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+int            texture_mode = GL_LINEAR_MIPMAP_LINEAR;
 
 
-void TextureGroupsMenu_ListItems(GSList*& items)
-{
-  for(TextureMenuNames::const_iterator i = texture_menunames.begin(); i != texture_menunames.end(); ++i)
-  {
-    items = g_slist_append(items, const_cast<char*>((*i).c_str()));
-  }
-}
+int g_nTextureOffset = 0;
 
 
-void TextureBrowser_queueDraw(TextureBrowser& textureBrower);
+// current active texture directory
+//++timo FIXME: I'm not sure this is used anymore
+char           texture_directory[128];
+// if true, the texture window will only display in-use shaders
+// if false, all the shaders in memory are displayed
+qboolean g_bShowAllShaders;
 
 
-class TextureGroupLoader
-{
-  std::size_t m_id;
-public:
-  TextureGroupLoader(std::size_t id)
-    : m_id(id)
-  {
-  }
-  void loadGroup()
-  {
-    ScopeDisableScreenUpdates disableScreenUpdates(TextureGroupsMenu_GetName(m_id), "Loading Textures");
+bool g_bFilterEnabled = false;
+CString g_strFilter;
 
 
-    TextureBrowser_ShowDirectory(GlobalTextureBrowser(), TextureGroupsMenu_GetName(m_id));
-    TextureBrowser_queueDraw(GlobalTextureBrowser());
-  }
-};
+// texture layout functions
+// TTimo: now based on shaders
+int     nActiveShadersCount;
+int     nCurrentShader;
+IShader*  pCurrentShader;
+qtexture_t  *current_texture = NULL;
+int     current_x, current_y, current_row;
 
 
-std::list<TextureGroupLoader> g_texture_group_loaders;
+// globals for textures
+int     texture_nummenus;
+char    texture_menunames[MAX_TEXTUREDIRS][128];
 
 
-void texturegroup_activated(GtkWidget* widget, gpointer data)
-{
-  reinterpret_cast<TextureGroupLoader*>(data)->loadGroup();
-}
+// the list of scripts/*.shader files we need to work with
+// those are listed in shaderlist file
+// FIXME TTimo I get the feeling that those would need to move to the shaders module
+//   for now it's still more simple to just keep it here
+GSList *l_shaderfiles = NULL;
 
 
-bool string_equal_start(const char* string, const char* start)
-{
-  return string_equal_n(string, start, string_length(start));
-}
+void SelectTexture (int mx, int my, bool bShift, bool bFitScale=false);
 
 
-GtkMenuItem* MenuItem_create(const char* name)
-{
-  StringOutputStream buffer(64);
-  buffer << ConvertLocaleToUTF8(name);
-  return GTK_MENU_ITEM(gtk_menu_item_new_with_label(buffer.c_str()));
-}
+void  Texture_MouseDown (int x, int y, int buttons);
+void  Texture_MouseMoved (int x, int y, int buttons);
 
 
-GtkMenuItem* Menu_addItem(GtkMenu* menu, const char* name)
-{
-  GtkMenuItem* item = MenuItem_create(name);
-  gtk_widget_show(GTK_WIDGET(item));
-  menu_add_item(menu, item);
-  return item;
-}
+CPtrArray g_lstSkinCache;
 
 
-void TextureGroupsMenu_addItem(GtkMenu* menu, const char* dirName)
+// TTimo: modifed to add a qtexture_t, Texture_LoadSkin loads using the shader API / QERApp_TryTexture_ForName
+// m_strName is a copy of qtex->name
+struct SkinInfo
 {
 {
-  GtkMenuItem* item = Menu_addItem(menu, dirName);
+  CString m_strName;
+  int m_nTextureBind;
+  qtexture_t *m_qtex;
+  SkinInfo(const char *pName, int n, qtexture_t *qtex)
+  {
+    m_strName = pName;
+    m_nTextureBind = n;
+    m_qtex = qtex;
+  };
+  SkinInfo(){};
+};
 
 
-  g_texture_group_loaders.push_back(TextureGroupLoader(texture_menunames.size()));
-       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(texturegroup_activated), &g_texture_group_loaders.back());
+// =============================================================================
+// global functions
 
 
-  if(TextureGroupsMenu_showWads())
-  {
-    texture_menunames.push_back(dirName);
-  }
+// gets active texture extension
+//
+// FIXME: fix this to be generic from project file
+//
+int GetTextureExtensionCount()
+{
+  // hardcoded hack for png support
+  if (g_pGameDescription->mGameFile == "sof2.game")
+    return 3;
   else
   else
+    return 2;
+}
+
+const char* GetTextureExtension(int nIndex)
+{
+  switch(nIndex)
   {
   {
-    char buffer[1024];
-    strcpy(buffer, dirName);
-    strcat(buffer, "/");
-    texture_menunames.push_back(buffer);
+    case 0:
+      return "tga";
+      break;
+    case 1:
+      return "jpg";
+      break;
+    case 2:
+      return "png";
+      break;
+    default:
+      return NULL;
   }
 }
 
   }
 }
 
-typedef std::set<CopiedString> TextureGroups;
-
-void TextureGroupsMenu_Construct(GtkMenu* menu, const TextureGroups& groups)
+/*
+==============
+Texture_InitPalette
+==============
+*/
+void Texture_InitPalette (byte *pal)
 {
 {
-  texture_menunames.clear();
+  int   r,g,b;
+  int   i;
+  int   inf;
+  byte  gammatable[256];
+  float gamma;
 
 
-  TextureGroups::const_iterator i = groups.begin();
-  while(i != groups.end())
-  {
-    const char* dirName = (*i).c_str();
-    const char* firstUnderscore = strchr(dirName, '_');
-    CopiedString dirRoot(dirName, (firstUnderscore == 0) ? dirName : firstUnderscore + 1);
+  gamma = g_qeglobals.d_savedinfo.fGamma;
 
 
-    // do we shrink the menus?
-    // we shrink only if we have at least two things to shrink :-)
-    TextureGroups::const_iterator next = i;
-    ++next;
-    if(firstUnderscore != 0
-      && next != groups.end()
-      && string_equal_start((*next).c_str(), dirRoot.c_str()))
+  if (gamma == 1.0)
+  {
+    for (i=0 ; i<256 ; i++)
+      gammatable[i] = i;
+  } else
+  {
+    for (i=0 ; i<256 ; i++)
     {
     {
-      CopiedString itemName(dirName, firstUnderscore);
-           GtkMenuItem* item = Menu_addItem(menu, itemName.c_str());
-
-           GtkMenu *pSubMenu = GTK_MENU(gtk_menu_new());
-      gtk_menu_item_set_submenu(item, GTK_WIDGET(pSubMenu));
+      inf = (int)( 255.0f * pow( ( i + 0.5f ) / 255.5f , gamma ) + 0.5f );
+      if (inf < 0)
+        inf = 0;
+      if (inf > 255)
+        inf = 255;
+      gammatable[i] = inf;
+    }
+  }
 
 
-           // keep going...
-           while(i != groups.end() && string_equal_start((*i).c_str(), dirRoot.c_str()))
-           {
-             TextureGroupsMenu_addItem(pSubMenu, (*i).c_str());
+  for (i=0 ; i<256 ; i++)
+  {
+    r = gammatable[pal[0]];
+    g = gammatable[pal[1]];
+    b = gammatable[pal[2]];
+    pal += 3;
 
 
-             ++i;
-           }
-    }
-    else
-    {
-      TextureGroupsMenu_addItem(menu, dirName);
+    //v = (r<<24) + (g<<16) + (b<<8) + 255;
+    //v = BigLong (v);
 
 
-      ++i;
-    }
+    //tex_palette[i] = v;
+    tex_palette[i*3+0] = r;
+    tex_palette[i*3+1] = g;
+    tex_palette[i*3+2] = b;
   }
 }
 
   }
 }
 
-
-void TextureGroups_addWad(TextureGroups& groups, const char* archive)
+void SetTexParameters (void)
 {
 {
-  if(extension_equal(path_get_extension(archive), "wad"))
+  qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
+
+  switch ( texture_mode )
   {
   {
-#if 1
-    groups.insert(archive);
-#else
-    CopiedString archiveBaseName(path_get_filename_start(archive), path_get_filename_base_end(archive));
-    groups.insert(archiveBaseName);
-#endif
+  case GL_NEAREST:
+  case GL_NEAREST_MIPMAP_NEAREST:
+  case GL_NEAREST_MIPMAP_LINEAR:
+    qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+    break;
+  case GL_LINEAR:
+  case GL_LINEAR_MIPMAP_NEAREST:
+  case GL_LINEAR_MIPMAP_LINEAR:
+    qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+    break;
   }
 }
   }
 }
-typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addWad> TextureGroupsAddWadCaller;
 
 
-void TextureGroups_addShader(TextureGroups& groups, const char* shaderName)
+/*
+============
+Texture_SetMode
+============
+*/
+void Texture_SetMode(int iMenu)
 {
 {
-  const char* texture = path_make_relative(shaderName, "textures/");
-  if(texture != shaderName)
+  int iMode;
+  qboolean texturing = true;
+  gpointer item = NULL;
+
+  switch (iMenu)
   {
   {
-    const char* last = path_remove_directory(texture);
-    if(!string_empty(last))
-    {
-      groups.insert(CopiedString(texture, --last));
-    }
+  case ID_VIEW_NEAREST:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_nearest");
+    iMode = GL_NEAREST;
+    break;
+  case ID_VIEW_NEARESTMIPMAP:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_nearestmipmap");
+    iMode = GL_NEAREST_MIPMAP_NEAREST;
+    break;
+  case ID_VIEW_LINEAR:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_linear");
+    iMode = GL_LINEAR;
+    break;
+  case ID_VIEW_BILINEAR:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_bilinear");
+    iMode = GL_NEAREST_MIPMAP_LINEAR;
+    break;
+  case ID_VIEW_BILINEARMIPMAP:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_bilinearmipmap");
+    iMode = GL_LINEAR_MIPMAP_NEAREST;
+    break;
+  case ID_VIEW_TRILINEAR:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_trilinear");
+    iMode = GL_LINEAR_MIPMAP_LINEAR;
+    break;
+  case ID_TEXTURES_WIREFRAME:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_wireframe");
+    iMode = -1;
+    texturing = false;
+    break;
+  case ID_TEXTURES_FLATSHADE:
+    item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_view_flatshade");
+    iMode = -1;
+    texturing = false;
+    break;
+  default:
+    return;
   }
   }
-}
-typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addShader> TextureGroupsAddShaderCaller;
 
 
-void TextureGroups_addDirectory(TextureGroups& groups, const char* directory)
-{
-  groups.insert(directory);
-}
-typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addDirectory> TextureGroupsAddDirectoryCaller;
+  g_qeglobals.d_savedinfo.iTexMenu = iMenu;
+  // NOTE: texture_mode is a GLenum used directly in glTexParameter
+  if(iMode!=-1) texture_mode = iMode;
 
 
-GtkMenu* g_textures_menu = 0;
-GtkMenuItem* g_textures_menu_separator = 0;
-namespace
-{
-  bool g_TexturesMenu_shaderlistOnly = false;
-}
-void TextureGroupsMenu_Construct()
-{
-  TextureGroups groups;
+  g_bIgnoreCommands++;
+  if (item != NULL)
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
+  g_bIgnoreCommands--;
 
 
-  if(TextureGroupsMenu_showWads())
+  if (texturing)
+    SetTexParameters ();
+
+  if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
   {
   {
-    GlobalFileSystem().forEachArchive(TextureGroupsAddWadCaller(groups));
-  }
-  else
+    g_pParentWnd->GetCamWnd()->Camera()->draw_mode = cd_wire;
+    Map_BuildBrushData();
+    Sys_UpdateWindows (W_ALL);
+    return;
+  } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE)
   {
   {
-    // scan texture dirs and pak files only if not restricting to shaderlist
-    if(g_pGameDescription->mGameType != "doom3" && !g_TexturesMenu_shaderlistOnly)
-    {
-      GlobalFileSystem().forEachDirectory("textures/", TextureGroupsAddDirectoryCaller(groups));
-    }
+    g_pParentWnd->GetCamWnd()->Camera()->draw_mode = cd_solid;
+    Map_BuildBrushData();
+    Sys_UpdateWindows (W_ALL);
+    return;
+  }
 
 
-    GlobalShaderSystem().foreachShaderName(TextureGroupsAddShaderCaller(groups));
+  for (qtexture_t *q = g_qeglobals.d_qtextures; q; q = q->next)
+  {
+    qglBindTexture (GL_TEXTURE_2D, q->texture_number);
+    SetTexParameters ();
   }
 
   }
 
-  TextureGroupsMenu_Construct(g_textures_menu, groups);
-}
+  // select the default texture
+  qglBindTexture( GL_TEXTURE_2D, 0 );
 
 
-void TextureGroupsMenu_Destroy()
-{
-  // delete everything
-  GtkMenu* menu = g_textures_menu;
-  GtkMenuItem* sep = g_textures_menu_separator;
-  GList* lst = g_list_find(gtk_container_children(GTK_CONTAINER(menu)), GTK_WIDGET(sep));
-  while(lst->next)
+  qglFinish();
+
+  if (g_pParentWnd->GetCamWnd()->Camera()->draw_mode != cd_texture)
   {
   {
-    // these delete functions are recursive, it's gonna free all submenus
-    gtk_widget_destroy(GTK_WIDGET (lst->next->data));
-    // lst is no longer relevant, need to get it again
-    lst = g_list_find(gtk_container_children(GTK_CONTAINER(menu)), GTK_WIDGET(sep));
+    g_pParentWnd->GetCamWnd()->Camera()->draw_mode = cd_texture;
+    Map_BuildBrushData();
   }
   }
-}
 
 
+  Sys_UpdateWindows (W_ALL);
+}
 
 
-class TextureGroupsMenu : public ModuleObserver
+/*!
+gamma correction stuff
+took out of QERApp_LoadTextureRGBA for clarity
+*/
+byte g_gammatable[256];
+void ResampleGamma(float fGamma)
 {
 {
-  std::size_t m_unrealised;
-public:
-  TextureGroupsMenu() : m_unrealised(2)
+  int i,inf;
+  if (fGamma == 1.0)
   {
   {
-  }
-  void realise()
-  {
-    if(--m_unrealised == 0)
-    {
-      if(g_textures_menu != 0)
-      {
-        TextureGroupsMenu_Construct();
-      }
-    }
-  }
-  void unrealise()
+    for (i = 0; i < 256; i++)
+      g_gammatable[i] = i;
+  } else
   {
   {
-    if(++m_unrealised == 1)
+    for (i = 0; i < 256; i++)
     {
     {
-      if(g_textures_menu != 0)
-      {
-        TextureGroupsMenu_Destroy();
-      }
+      inf = (int)( 255.0f * pow( (i + 0.5f) / 255.5f , fGamma ) + 0.5f );
+      if (inf < 0)
+        inf = 0;
+      if (inf > 255)
+        inf = 255;
+      g_gammatable[i] = inf;
     }
   }
     }
   }
-};
-
-TextureGroupsMenu g_TextureGroupsMenu;
+}
 
 
-class DeferredAdjustment
+/*!
+this function does the actual processing of raw RGBA data into a GL texture
+it will also generate the mipmaps
+it looks like pPixels nWidth nHeight are the only relevant parameters
+*/
+qtexture_t *QERApp_LoadTextureRGBA(unsigned char* pPixels, int nWidth, int nHeight)
 {
 {
-  gdouble m_value;
-  guint m_handler;
-  typedef void (*ValueChangedFunction)(void* data, gdouble value);
-  ValueChangedFunction m_function;
-  void* m_data;
+  static float fGamma = -1;
+  float total[3];
+  byte  *outpixels = NULL;
+  int   i, j, resampled, width2, height2, width3, height3;
+  int   max_tex_size = 0, mip = 0;
+  int   nCount = nWidth * nHeight;
 
 
-  static gboolean deferred_value_changed(gpointer data)
+  if (fGamma != g_qeglobals.d_savedinfo.fGamma)
   {
   {
-    reinterpret_cast<DeferredAdjustment*>(data)->m_function(
-      reinterpret_cast<DeferredAdjustment*>(data)->m_data,
-      reinterpret_cast<DeferredAdjustment*>(data)->m_value
-    );
-    reinterpret_cast<DeferredAdjustment*>(data)->m_handler = 0;
-    reinterpret_cast<DeferredAdjustment*>(data)->m_value = 0;
-    return FALSE;
+    fGamma = g_qeglobals.d_savedinfo.fGamma;
+    ResampleGamma(fGamma);
   }
   }
-public:
-  DeferredAdjustment(ValueChangedFunction function, void* data) : m_value(0), m_handler(0), m_function(function), m_data(data)
-  {
-  }
-  void flush()
-  {
-    if(m_handler != 0)
-    {
-      g_source_remove(m_handler);
-      deferred_value_changed(this);
-    }
-  }
-  void value_changed(gdouble value)
-  {
-    m_value = value;
-    if(m_handler == 0)
-    {
-      m_handler = g_idle_add(deferred_value_changed, this);
-    }
-  }
-  static void adjustment_value_changed(GtkAdjustment *adjustment, DeferredAdjustment* self)
-  {
-    self->value_changed(adjustment->value);
-  }
-};
-
 
 
+  qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
+  if (!max_tex_size)
+    max_tex_size = 1024;
 
 
-class TextureBrowser;
+  qtexture_t *q = (qtexture_t*)g_malloc(sizeof(*q));
+  q->width = nWidth;
+  q->height = nHeight;
 
 
-typedef ReferenceCaller<TextureBrowser, TextureBrowser_queueDraw> TextureBrowserQueueDrawCaller;
+  total[0] = total[1] = total[2] = 0.0f;
 
 
-void TextureBrowser_scrollChanged(void* data, gdouble value);
-
-
-enum StartupShaders
-{
-  STARTUPSHADERS_NONE = 0,
-  STARTUPSHADERS_COMMON,
-  STARTUPSHADERS_ALL,
-};
-
-class TextureBrowser
-{
-public:
-       int width, height;
-       int originy;
-       int m_nTotalHeight;
-
-  CopiedString shader;
-
-  GtkEntry* m_filter;
-  NonModalEntry m_filterEntry;
-
-  GtkWindow* m_parent;
-  GtkWidget* m_gl_widget;
+  // resample texture gamma according to user settings
+  for (i = 0; i < (nCount * 4); i += 4)
+  {
+    for (j = 0; j < 3; j++)
+    {
+      total[j] += (pPixels + i)[j];
+      byte b = (pPixels + i)[j];
+      (pPixels + i)[j] = g_gammatable[b];
+    }
+  }
 
 
-  guint m_sizeHandler;
-  guint m_exposeHandler;
+  q->color[0] = total[0] / (nCount * 255);
+  q->color[1] = total[1] / (nCount * 255);
+  q->color[2] = total[2] / (nCount * 255);
 
 
-  GtkWidget* m_texture_scroll;
+  qglGenTextures (1, &q->texture_number);
 
 
-  bool m_heightChanged;
-  bool m_originInvalid;
+  qglBindTexture( GL_TEXTURE_2D, q->texture_number );
 
 
-  DeferredAdjustment m_scrollAdjustment;
-  FreezePointer m_freezePointer;
+  SetTexParameters();
 
 
-  Vector3 color_textureback;
-  // the increment step we use against the wheel mouse
-  std::size_t m_mouseWheelScrollIncrement;
-  std::size_t m_textureScale;
-  bool m_showTextureFilter;
-  // make the texture increments match the grid changes
-  bool m_showShaders;
-  bool m_showTextureScrollbar;
-  StartupShaders m_startupShaders;
-  // if true, the texture window will only display in-use shaders
-  // if false, all the shaders in memory are displayed
-  bool m_hideUnused;
+  width2 = 1; while (width2 < nWidth) width2 <<= 1;
+  height2 = 1; while (height2 < nHeight) height2 <<= 1;
 
 
+  width3 = width2;
+  height3 = height2;
+  while (width3 > max_tex_size) width3 >>= 1;
+  while (height3 > max_tex_size) height3 >>= 1;
+  if (width3 < 1) width3 = 1;
+  if (height3 < 1) height3 = 1;
 
 
-  void clearFilter()
-  {
-    gtk_entry_set_text(m_filter, "");
-    TextureBrowser_queueDraw(*this);
-  }
-  typedef MemberCaller<TextureBrowser, &TextureBrowser::clearFilter> ClearFilterCaller;
-
-  TextureBrowser() :
-    m_filter(0),
-    m_filterEntry(TextureBrowserQueueDrawCaller(*this), ClearFilterCaller(*this)),
-    m_texture_scroll(0),
-    m_heightChanged(true),
-    m_originInvalid(true),
-    m_scrollAdjustment(TextureBrowser_scrollChanged, this),
-    color_textureback(0.25f, 0.25f, 0.25f),
-    m_mouseWheelScrollIncrement(64),
-    m_textureScale(50),
-    m_showTextureFilter(false),
-    m_showShaders(true),
-    m_showTextureScrollbar(true),
-    m_startupShaders(STARTUPSHADERS_NONE),
-    m_hideUnused(false)
-  {
+  if (!(width2 == nWidth && height2 == nHeight)) {
+    resampled = 1;
+    outpixels = (byte *)malloc(width2 * height2 * 4);
+    R_ResampleTexture(pPixels, nWidth, nHeight, outpixels, width2, height2, 4);
+  } else {
+    resampled = 0;
+    outpixels = pPixels;
   }
   }
-};
-
-void(*TextureBrowser_textureSelected)(const char* shader);
 
 
-
-void TextureBrowser_updateScroll(TextureBrowser& textureBrowser);
-
-
-const char* TextureBrowser_getComonShadersName()
-{
-  const char* value = g_pGameDescription->getKeyValue("common_shaders_name");
-  if(!string_empty(value))
+  while (width2 > width3 || height2 > height3)
   {
   {
-    return value;
+    GL_MipReduce(outpixels, outpixels, width2, height2, width3, height3);
+
+    if (width2 > width3)
+      width2 >>= 1;
+    if (height2 > height3)
+      height2 >>= 1;
   }
   }
-  return "Common";
-}
 
 
-const char* TextureBrowser_getComonShadersDir()
-{
-  const char* value = g_pGameDescription->getKeyValue("common_shaders_dir");
-  if(!string_empty(value))
+  qglTexImage2D(GL_TEXTURE_2D, mip++, g_qeglobals.texture_components, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);
+  while (width2 > 1 || height2 > 1)
   {
   {
-    return value;
+    GL_MipReduce(outpixels, outpixels, width2, height2, 1, 1);
+
+    if (width2 > 1)
+      width2 >>= 1;
+    if (height2 > 1)
+      height2 >>= 1;
+
+    qglTexImage2D(GL_TEXTURE_2D, mip++, g_qeglobals.texture_components, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);
   }
   }
-  return "common/";
-}
 
 
+  qglBindTexture(GL_TEXTURE_2D, 0);
+  if (resampled)
+    free(outpixels);
 
 
-void TextureBrowser_setShowFilter(TextureBrowser& textureBrowser, bool show)
-{
-  widget_set_visible(GTK_WIDGET(textureBrowser.m_filter), show);
+  return q;
 }
 
 }
 
-const char* TextureBrowser_getFilter(TextureBrowser& textureBrowser)
+/*
+==================
+DumpUnreferencedShaders
+usefull function: dumps the list of .shader files that are not referenced to the console
+==================
+*/
+void DumpUnreferencedShaders()
 {
 {
-  if(textureBrowser.m_showTextureFilter)
+  GSList *lst, *sh, *files;
+  bool bFound = false;
+
+  files = vfsGetFileList ("scripts", "shader");
+  for (lst = files; lst; lst = lst->next)
   {
   {
-    return gtk_entry_get_text(textureBrowser.m_filter);
-  }
-  return 0;
-}
+    bool listed = false;
 
 
-inline int TextureBrowser_fontHeight(TextureBrowser& textureBrowser)
-{
-  return GlobalOpenGL().m_fontHeight;
-}
+    for (sh = l_shaderfiles; sh != NULL; sh = g_slist_next (sh))
+      if (!strcmp ((char*)sh->data, (char*)lst->data))
+      {
+        listed = true;
+        break;
+      }
 
 
-const char* TextureBrowser_GetSelectedShader(TextureBrowser& textureBrowser)
-{
-  return textureBrowser.shader.c_str();
-}
+    if (!listed)
+    {
+      if (!bFound)
+      {
+        bFound = true;
+        Sys_FPrintf (SYS_WRN, "Following shader files are not referenced in shaderlist.txt:\n");
+      }
+      Sys_FPrintf (SYS_WRN, "%s\n", (char*)lst->data);
+    }
+  }
 
 
-void TextureBrowser_SetStatus(TextureBrowser& textureBrowser, const char* name)
-{
-  IShader* shader = QERApp_Shader_ForName( name);
-  qtexture_t* q = shader->getTexture();
-  StringOutputStream strTex(256);
-  strTex << name << " W: " << Unsigned(q->width) << " H: " << Unsigned(q->height);
-  shader->DecRef();
-  g_pParentWnd->SetStatusText(g_pParentWnd->m_texture_status, strTex.c_str());
+  vfsClearFileDirList (&files);
 }
 
 }
 
-void TextureBrowser_Focus(TextureBrowser& textureBrowser, const char* name);
-
-void TextureBrowser_SetSelectedShader(TextureBrowser& textureBrowser, const char* shader)
+/*
+==================
+BuildShaderList
+build a CStringList of shader names
+==================
+*/
+void BuildShaderList()
 {
 {
-  textureBrowser.shader = shader;
-  TextureBrowser_SetStatus(textureBrowser, shader);
-  TextureBrowser_Focus(textureBrowser, shader);
+  int count;
+  char filename[1024];
+  char *pBuff;
+  char dirstring[NAME_MAX];
+  int nLen;
+  if (l_shaderfiles!=NULL)
+  {
+    g_slist_free(l_shaderfiles);
+    l_shaderfiles = NULL;
+  }
 
 
-  if(FindTextureDialog_isOpen())
+  if (g_pGameDescription->mGameFile != "hl.game")
   {
   {
-    FindTextureDialog_selectTexture(shader);
+    strcpy(filename, g_pGameDescription->mShaderlist.GetBuffer());
+    count = vfsGetFileCount(filename, 0 );
+    if (count==0)
+    {
+      Sys_FPrintf(SYS_ERR, "Couldn't find '%s'\n", g_pGameDescription->mShaderlist.GetBuffer());
+      return;
+    }
+    // NOTE TTimo we use vfsGetFullPath solely to get the full path of the shader list we are gonna load
+    //   but we actually send the relative path to vfsLoadFile
+    //   so let's hope there is no disparity between the two functions
+    if (!vfsGetFullPath(filename, 0, 0))
+    {
+      Sys_FPrintf(SYS_ERR, "Couldn't find full path for '%s'\n", g_pGameDescription->mShaderlist.GetBuffer());
+      return;
+    }
+    Sys_Printf("Parsing shader files from %s\n", vfsGetFullPath(filename, 0, 0));
+    nLen = vfsLoadFile (filename, reinterpret_cast<void**>(&pBuff), 0);
+    if (nLen > 0)
+    {
+      StartTokenParsing(pBuff);
+      nLen = 0;
+      while (GetToken(true))
+      {
+        GSList *tmp;
+        bool found = false;
+
+        // each token should be a shader filename
+        sprintf(dirstring, "%s.shader", token);
+
+        for (tmp = l_shaderfiles; tmp != NULL; tmp = tmp->next)
+        {
+          if (!strcmp (dirstring, (char*)tmp->data))
+          {
+            found = true;
+            Sys_FPrintf(SYS_WRN, "duplicate entry \"%s\" in shaderlist.txt\n", (char*)tmp->data);
+            break;
+          }
+        }
+
+        if (!found)
+        {
+          l_shaderfiles = g_slist_append (l_shaderfiles, strdup (dirstring));
+          nLen++;
+        }
+      }
+      g_free(pBuff);
+    }
   }
 }
 
   }
 }
 
-
-CopiedString g_TextureBrowser_currentDirectory;
-
 /*
 /*
-============================================================================
-
-TEXTURE LAYOUT
+==================
+FillTextureMenu
 
 
-TTimo: now based on a rundown through all the shaders
-NOTE: we expect the Active shaders count doesn't change during a Texture_StartPos .. Texture_NextPos cycle
-  otherwise we may need to rely on a list instead of an array storage
-============================================================================
+==================
 */
 */
-
-class TextureLayout
+void ClearGSList (GSList* lst)
 {
 {
-public:
-  // texture layout functions
-  // TTimo: now based on shaders
-  int current_x, current_y, current_row;
-};
-
-void Texture_StartPos(TextureLayout& layout)
-{
-  layout.current_x = 8;
-  layout.current_y = -8;
-  layout.current_row = 0;
+  GSList *p = lst;
+  while (p)
+  {
+    free (p->data);
+    p = g_slist_remove (p, p->data);
+  }
 }
 
 }
 
-void Texture_NextPos(TextureBrowser& textureBrowser, TextureLayout& layout, qtexture_t* current_texture, int *x, int *y)
+void FillTextureMenu (GSList** pArray)
 {
 {
-  qtexture_t* q = current_texture;
+  GtkWidget *menu, *sep, *item; // point to the Textures GtkMenu and to the last separator
+  GList *lst;
+  GSList *texdirs = NULL;
+  GSList *texdirs_tmp = NULL;
+  GSList *p;
+  char dirRoot[NAME_MAX];
 
 
-  int nWidth = (int)(q->width * ((float)textureBrowser.m_textureScale / 100));
-  int nHeight = (int)(q->height * ((float)textureBrowser.m_textureScale / 100));
-  if (layout.current_x + nWidth > textureBrowser.width-8 && layout.current_row)
-  { // go to the next row unless the texture is the first on the row
-    layout.current_x = 8;
-    layout.current_y -= layout.current_row + TextureBrowser_fontHeight(textureBrowser) + 4;
-    layout.current_row = 0;
+  // delete everything
+  menu = GTK_WIDGET (g_object_get_data (G_OBJECT (g_qeglobals_gui.d_main_window), "menu_textures"));
+  sep = GTK_WIDGET (g_object_get_data (G_OBJECT (g_qeglobals_gui.d_main_window), "menu_textures_separator"));
+  lst = g_list_find (gtk_container_children (GTK_CONTAINER (menu)), sep);
+  while (lst->next)
+  {
+    // these delete functions are recursive, it's gonna free all submenus
+    gtk_widget_destroy (GTK_WIDGET (lst->next->data));
+    // lst is no longer relevant, need to get it again
+    lst = g_list_find (gtk_container_children (GTK_CONTAINER (menu)), sep);
   }
 
   }
 
-  *x = layout.current_x;
-  *y = layout.current_y;
-
-  // Is our texture larger than the row? If so, grow the
-  // row height to match it
+  texture_nummenus = 0;
 
 
-  if (layout.current_row < nHeight)
-    layout.current_row = nHeight;
-
-  // never go less than 64, or the names get all crunched up
-  layout.current_x += nWidth < 64 ? 64 : nWidth;
-  layout.current_x += 8;
-}
-
-// if texture_showinuse jump over non in-use textures
-bool Texture_IsShown(IShader* shader, bool show_shaders, bool hideUnused, const char* filter)
-{
-  if(!shader_equal_prefix(shader->getName(), "textures/"))
-    return false;
-
-  if (!show_shaders && !shader->IsDefault())
-    return false;
-
-  if(hideUnused && !shader->IsInUse())
-    return false;
+  // add everything
+  if (!g_qeglobals.d_project_entity)
+    return;
 
 
-  if(!string_empty(g_TextureBrowser_currentDirectory.c_str()))
+  // scan texture dirs and pak files only if not restricting to shaderlist
+  if (!g_PrefsDlg.m_bTexturesShaderlistOnly)
   {
   {
-    if(!shader_equal_prefix(shader_get_textureName(shader->getName()), g_TextureBrowser_currentDirectory.c_str()))
+    texdirs_tmp = vfsGetDirList ("textures/");
+    for (p=texdirs_tmp; p; p=g_slist_next(p))
     {
     {
-      return false;
+      // Hydra: erm, this didn't used to do anything except leak memory...
+      // For Halflife support this is required to work however.
+      // g_slist_append(texdirs, p->data);
+      texdirs = g_slist_append(texdirs, strdup((char *)p->data));
     }
     }
+    vfsClearFileDirList (&texdirs_tmp);
   }
 
   }
 
-  if (filter != 0)
+  // scan the shaders in shaderlist.txt
+  BuildShaderList ();
+  PreloadShaders ();
+  DumpUnreferencedShaders ();
+  while (l_shaderfiles != NULL)
   {
   {
-    // some basic filtering
-    if (strstr( shader_get_textureName(shader->getName()), filter ) == 0)
-      return false;
-  }
+    char shaderfile[PATH_MAX];
+    gboolean found = FALSE;
 
 
-  return true;
-}
+    ExtractFileName ((char*)l_shaderfiles->data, shaderfile);
+    StripExtension (shaderfile);
+    g_strdown (shaderfile);
 
 
-void TextureBrowser_heightChanged(TextureBrowser& textureBrowser)
-{
-  textureBrowser.m_heightChanged = true;
+    for (GSList *tmp = texdirs; tmp; tmp = g_slist_next (tmp))
+      if (!strcasecmp ((char*)tmp->data, shaderfile))
+      {
+             found = TRUE;
+             break;
+      }
 
 
-  TextureBrowser_updateScroll(textureBrowser);
-  TextureBrowser_queueDraw(textureBrowser);
-}
+    if (!found)
+      texdirs = g_slist_prepend (texdirs, strdup (shaderfile));
 
 
-void TextureBrowser_evaluateHeight(TextureBrowser& textureBrowser)
-{
-  if(textureBrowser.m_heightChanged)
-  {
-    textureBrowser.m_heightChanged = false;
+    free (l_shaderfiles->data);
+    l_shaderfiles = g_slist_remove (l_shaderfiles, l_shaderfiles->data);
+  }
 
 
-    textureBrowser.m_nTotalHeight = 0;
+  // sort the list
+  texdirs = g_slist_sort (texdirs, (GCompareFunc)strcmp);
 
 
-    TextureLayout layout;
-    Texture_StartPos(layout);
-    for(QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement())
+  GSList *temp = texdirs;
+  while (temp)
+  {
+    char* ptr = strchr ((char*)temp->data, '_');
+
+    // do we shrink the menus?
+    if (ptr != NULL)
     {
     {
-      IShader* shader = QERApp_ActiveShaders_IteratorCurrent();
+      // extract the root
+      strcpy (dirRoot, (char*)temp->data);
+      dirRoot[ptr - (char*)temp->data + 1] = 0;
 
 
-      if(!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused, TextureBrowser_getFilter(textureBrowser)))
-        continue;
+      // we shrink only if we have at least two things to shrink :-)
+      if (temp->next && (strstr ((char*)temp->next->data, dirRoot) == (char*)temp->next->data))
+      {
+             GtkWidget *pSubMenu = gtk_menu_new ();
+        GtkWidget *pSubMenuRef = pSubMenu;
+             // keep going...
+             do
+             {
+               item = gtk_menu_item_new_with_label ((char*)temp->data);
+               gtk_widget_show (item);
+          CheckMenuSplitting (pSubMenu);
+               gtk_container_add (GTK_CONTAINER (pSubMenu), item);
+               gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
+                                   GINT_TO_POINTER (CMD_TEXTUREWAD+texture_nummenus));
+
+               strcpy (texture_menunames[texture_nummenus], (char*)temp->data);
+               strcat (texture_menunames[texture_nummenus], "/");
+               if (pArray)
+                 *pArray = g_slist_append (*pArray, strdup ((char*)temp->data));
+               if (++texture_nummenus == MAX_TEXTUREDIRS)
+               {
+                 Sys_Printf("WARNING: max texture directories count has been reached!\n");
+                 // push submenu and get out
+                 item = gtk_menu_item_new_with_label (dirRoot);
+                 gtk_widget_show (item);
+                 gtk_container_add (GTK_CONTAINER (menu), item);
+                 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), pSubMenu);
+                 ClearGSList (texdirs);
+                 return;
+               }
+               temp = temp->next;
+             }
+        while (temp && (strstr((char*)temp->data, dirRoot)==temp->data));
+
+        ptr = strchr (dirRoot, '_');
+        *ptr = 0;
+             item = gtk_menu_item_new_with_label (dirRoot);
+             gtk_widget_show (item);
+             CheckMenuSplitting (menu);
+             gtk_container_add (GTK_CONTAINER (menu), item);
+        gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), pSubMenuRef);
+             continue;
+      }
+    }
 
 
-      int   x, y;
-      Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y);
-      textureBrowser.m_nTotalHeight = std::max(textureBrowser.m_nTotalHeight, abs(layout.current_y) + TextureBrowser_fontHeight(textureBrowser) + (int)(shader->getTexture()->height * ((float)textureBrowser.m_textureScale / 100)) + 4);
+    item = gtk_menu_item_new_with_label ((char*)temp->data);
+    gtk_widget_show (item);
+    CheckMenuSplitting (menu);
+    gtk_container_add (GTK_CONTAINER (menu), item);
+    gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
+                        GINT_TO_POINTER (CMD_TEXTUREWAD+texture_nummenus));
+
+    strcpy (texture_menunames[texture_nummenus], (char*)temp->data);
+    strcat (texture_menunames[texture_nummenus], "/");
+    if (pArray)
+      *pArray = g_slist_append (*pArray, strdup ((char*)temp->data));
+    if (++texture_nummenus == MAX_TEXTUREDIRS)
+    {
+      Sys_Printf("WARNING: max texture directories count has been reached!\n");
+      ClearGSList (texdirs);
+      return;
     }
     }
+
+    temp = temp->next;
   }
   }
+  ClearGSList (texdirs);
 }
 
 }
 
-int TextureBrowser_TotalHeight(TextureBrowser& textureBrowser)
-{
-  TextureBrowser_evaluateHeight(textureBrowser);
-  return textureBrowser.m_nTotalHeight;
-}
+/*
+==============
+Texture_ShowDirectory
+relies on texture_directory global for the directory to use
+called by
+  void Texture_ShowDirectory (int menunum, bool bLinked)
+  void Texture_ShowDirectory (char* pPath, bool bLinked)
+1) Load the shaders for the given directory
+2) Scan the remaining texture, load them and assign them a default shader (the "noshader" shader)
+NOTE: when writing a texture plugin, or some texture extensions, this function may need to be overriden, and made
+  available through the IShaders interface
+NOTE: for texture window layout:
+  all shaders are stored with alphabetical order after load
+  previously loaded and displayed stuff is hidden, only in-use and newly loaded is shown
+  ( the GL textures are not flushed though)
+==============
+*/
+void Texture_ShowDirectory ()
+{
+  char  name[1024];
+  char  dirstring[1024];
+  CString strTemp;
+  int shaders_count = 0;
+  int textures_count = 0;
+  GSList *files = NULL, *temp;
+
+  g_bScreenUpdates = false;
+
+  // refresh the in-use textures: that will clear the IsDisplayed flag on unused stuff
+  // and leave it on in-use so they'll still be displayed
+  Texture_ShowInuse();
+  // and textures loaded in the following lines will be displayed as well...
+  // NOTE: shaders that are not in use but have been loaded previously are still in memory. But they don't get displayed.
+
+  g_qeglobals.d_texturewin.originy = 0;
+  // load texture_directory.shader
+  // NOTE: because of above call to Texture_ClearInuse, g_ActiveShaders will have the newly loaded shaders only
+  // we'll use that later to check if textures have a shader associated or not
+  // NOTE: all shaders loaded through QERApp_LoadShadersFromDir will get their InUse flag to True, we'll need a call to Texture_ShowInUse for later cleanup/adjustment
+  // NOTE: QERApp_LoadShadersFromDir has two criterions for loading a shader:
+  //   the shaderfile is texture_directory (like "museum" will load everything in museum.shader)
+  //   the shader name contains texture_directory (like "base_floor" will load museum.shader::base_floor/concfloor_rain)
+  shaders_count = QERApp_LoadShadersFromDir(texture_directory);
+  // load remaining texture files
+  // if a texture is already in use to represent a shader, ignore it
 
 
-inline const int& min_int(const int& left, const int& right)
-{
-  return std::min(left, right);
-}
+  // need this function "GSList *lst SynapseServer::GetMinorList(char *major_name);"
 
 
-void TextureBrowser_clampOriginY(TextureBrowser& textureBrowser)
-{
-  if(textureBrowser.originy > 0)
-  {
-    textureBrowser.originy = 0;
-  }
-  int lower = min_int(textureBrowser.height - TextureBrowser_TotalHeight(textureBrowser), 0);
-  if(textureBrowser.originy < lower)
+  sprintf (dirstring, "textures/%s", texture_directory);
+  g_ImageManager.BeginExtensionsScan();
+  const char* ext;
+  while((ext=g_ImageManager.GetNextExtension()) != NULL)
   {
   {
-    textureBrowser.originy = lower;
+    files = g_slist_concat(files, vfsGetFileList (dirstring, ext));
   }
   }
-}
 
 
-int TextureBrowser_getOriginY(TextureBrowser& textureBrowser)
-{
-  if(textureBrowser.m_originInvalid)
+  for (temp = files; temp; temp = temp->next)
   {
   {
-    textureBrowser.m_originInvalid = false;
-    TextureBrowser_clampOriginY(textureBrowser);
-    TextureBrowser_updateScroll(textureBrowser);
-  }
-  return textureBrowser.originy;
-}
+    sprintf(name, "%s%s", texture_directory, (char*)temp->data);
 
 
-void TextureBrowser_setOriginY(TextureBrowser& textureBrowser, int originy)
-{
-  textureBrowser.originy = originy;
-  TextureBrowser_clampOriginY(textureBrowser);
-  TextureBrowser_updateScroll(textureBrowser);
-  TextureBrowser_queueDraw(textureBrowser);
-}
+      StripExtension (name);
+      strTemp = name;
+      strTemp.MakeLower();
 
 
+    if (strTemp.Find(".specular") >= 0 ||
+         strTemp.Find(".glow") >= 0 ||
+         strTemp.Find(".bump") >= 0 ||
+         strTemp.Find(".diffuse") >= 0 ||
+         strTemp.Find(".blend") >= 0 ||
+              strTemp.Find(".alpha") >= 0)
+         continue;
 
 
-std::set<Callback> g_activeShadersChangedCallbacks;
-
-void TextureBrowser_addActiveShadersChangedCallback(const Callback& callback)
-{
-  g_activeShadersChangedCallbacks.insert(callback);
-}
+    // avoid ever loading a texture name with spaces
+    if (strTemp.Find(" ") >= 0)
+    {
+      Sys_FPrintf(SYS_WRN, "WARNING: Skipping texture name with spaces [%s]\n", strTemp.GetBuffer());
+      continue;
+    }
 
 
-class ShadersObserver : public ModuleObserver
-{
-  std::set<Callback> m_realiseCallbacks;
-public:
-  void realise()
-  {
-    std::for_each(m_realiseCallbacks.begin(), m_realiseCallbacks.end(), CallbackInvoke());
-  }
-  void unrealise()
-  {
-  }
-  void insert(const Callback& callback)
-  {
-    m_realiseCallbacks.insert(callback);
+    // build a texture name that fits the conventions for qtexture_t::name
+    char stdName[1024];
+    sprintf( stdName, "textures/%s", name );
+    // check if this texture doesn't have a shader
+    if (!QERApp_ActiveShader_ForTextureName( stdName ))
+    {
+      QERApp_CreateShader_ForTextureName (stdName);
+      textures_count++;
+    }
   }
   }
-};
 
 
-namespace
-{
-  ShadersObserver g_ShadersObserver;
-}
+  Sys_Printf("Loaded %d shaders and created default shader for %d orphan textures.\n",
+            shaders_count, textures_count );
 
 
-void TextureBrowser_addShadersRealiseCallback(const Callback& callback)
-{
-  g_ShadersObserver.insert(callback);
-}
+  vfsClearFileDirList (&files);
 
 
-void TextureBrowser_activeShadersChanged(TextureBrowser& textureBrowser)
-{
-  TextureBrowser_heightChanged(textureBrowser);
-  textureBrowser.m_originInvalid = true;
+  // sort for displaying
+  QERApp_SortActiveShaders();
 
 
-  std::for_each(g_activeShadersChangedCallbacks.begin(), g_activeShadersChangedCallbacks.end(), CallbackInvoke());
-}
+  sprintf (name, "Textures: %s", texture_directory);
+  gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), name);
 
 
-void TextureBrowser_importShowScrollbar(TextureBrowser& textureBrowser, bool value)
-{
-  textureBrowser.m_showTextureScrollbar = value;
-  if(textureBrowser.m_texture_scroll != 0)
-  {
-    widget_set_visible(textureBrowser.m_texture_scroll, textureBrowser.m_showTextureScrollbar);
-    TextureBrowser_updateScroll(textureBrowser);
-  }
-}
-typedef ReferenceCaller1<TextureBrowser, bool, TextureBrowser_importShowScrollbar> TextureBrowserImportShowScrollbarCaller;
+  // select the first texture in the list
+  if (!g_qeglobals.d_texturewin.texdef.GetName()[0])
+    SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
 
 
-void TextureBrowser_importShowFilter(TextureBrowser& textureBrowser, bool value)
-{
-  textureBrowser.m_showTextureFilter = value;
-  if(textureBrowser.m_filter != 0)
-  {
-    TextureBrowser_setShowFilter(textureBrowser, textureBrowser.m_showTextureFilter);
-  }
+  g_bScreenUpdates = true;
+
+  Sys_UpdateWindows (W_TEXTURE);
 }
 }
-typedef ReferenceCaller1<TextureBrowser, bool, TextureBrowser_importShowFilter> TextureBrowserImportShowFilterCaller;
 
 /*
 ==============
 
 /*
 ==============
-TextureBrowser_ShowDirectory
-relies on texture_directory global for the directory to use
+Texture_ShowDirectory
 1) Load the shaders for the given directory
 2) Scan the remaining texture, load them and assign them a default shader (the "noshader" shader)
 NOTE: when writing a texture plugin, or some texture extensions, this function may need to be overriden, and made
   available through the IShaders interface
 1) Load the shaders for the given directory
 2) Scan the remaining texture, load them and assign them a default shader (the "noshader" shader)
 NOTE: when writing a texture plugin, or some texture extensions, this function may need to be overriden, and made
   available through the IShaders interface
-NOTE: for texture window layout:
-  all shaders are stored with alphabetical order after load
-  previously loaded and displayed stuff is hidden, only in-use and newly loaded is shown
-  ( the GL textures are not flushed though)
 ==============
 */
 ==============
 */
-bool texture_name_ignore(const char* name)
+void Texture_ShowDirectory (int menunum)
 {
 {
-  StringOutputStream strTemp(string_length(name));
-  strTemp << LowerCase(name);
-
-  return strstr(strTemp.c_str(), ".specular") != 0 ||
-    strstr(strTemp.c_str(), ".glow") != 0 ||
-    strstr(strTemp.c_str(), ".bump") != 0 ||
-    strstr(strTemp.c_str(), ".diffuse") != 0 ||
-    strstr(strTemp.c_str(), ".blend") != 0 ||
-         strstr(strTemp.c_str(), ".alpha") != 0;
+  strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
+  Texture_ShowDirectory();
 }
 
 }
 
-class LoadShaderVisitor : public Archive::Visitor
+// scroll origin so the current texture is completely on screen
+// if current texture is not displayed, nothing is changed
+void Texture_ResetPosition()
 {
 {
-public:
-  void visit(const char* name)
-  {
-    CopiedString shaderName(name, path_get_filename_base_end(name));
-    IShader* shader = QERApp_Shader_ForName(shaderName.c_str());
-    shader->DecRef();
+  qtexture_t  *q;
+  int  x,y;
+
+  //this shouldn't ever happen, we startup with notex
+  if (!g_qeglobals.d_texturewin.texdef.GetName()[0]) {
+    return;
   }
   }
-};
 
 
-void TextureBrowser_SetHideUnused(TextureBrowser& textureBrowser, bool hideUnused);
+  // otherwise position with current texture shown
+  // this used to be in Texture_SetTexture
+  Texture_StartPos ();
+  while (1)
+  {
+    // NOTE: return value is == pCurrentShader and pCurrentShader->getTexture == current_texture
+    Texture_NextPos (&x, &y);
+    q = current_texture;
+    // if the current texture never found (because // 'show shaders' is off,
+    // for example), do nothing
+    if (!q)
+      break;
 
 
-GtkWidget* g_page_textures;
+    int nHeight = (int)(q->height * ((float)g_PrefsDlg.m_nTextureScale / 100));
+    // we have found when texdef->name and the shader name match
+    // NOTE: as everywhere else for our comparisons, we are not case sensitive
+    if (!strcmpi( g_qeglobals.d_texturewin.texdef.GetName(), pCurrentShader->getName() ))
+    {
+      // take care of calls before initialized
+      if ( !g_qeglobals.d_texturewin.height) {
+        g_qeglobals.d_texturewin.originy = 0;
+        break;
+      }
+      // if the bottom of our selected texture will fit with origin 0, use that
+      // to prevent scrolling uglyness (stuff scrolled off screen when
+      // everything would fit)
+      if ( -(y -nHeight-2*FONT_HEIGHT) <  g_qeglobals.d_texturewin.height) {
+        g_qeglobals.d_texturewin.originy = 0;
+        break;
+      }
+      // if current is off the top of the window, move it to the top
+      if (y > g_qeglobals.d_texturewin.originy)
+      {
+        g_qeglobals.d_texturewin.originy = y;
+        break;
+      }
 
 
-void TextureBrowser_toggleShown() 
-{
-  GroupDialog_showPage(g_page_textures);
+      // if current is off the bottom, put it on the bottom
+      if (y-nHeight-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
+      {
+        g_qeglobals.d_texturewin.originy = y-nHeight-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
+        break;
+      }
+      // if we made it here, it should already be in view
+      break;
+    }
+  }
+  Sys_UpdateWindows (W_TEXTURE);
 }
 
 }
 
-
-void TextureBrowser_updateTitle()
+/*
+==============
+Texture_ShowAll
+will set the IsDisplayed flag on all the active shaders, so we see everything that's currently in memory
+==============
+*/
+void Texture_ShowAll()
 {
 {
-  GroupDialog_updatePageTitle(g_page_textures);
+  char name[1024];
+
+#ifdef _DEBUG
+  if (g_bShowAllShaders)
+    Sys_Printf("WARNING: already showing all shaders\n");
+#endif
+  QERApp_ActiveShaders_SetDisplayed(true);
+  g_bShowAllShaders = true;
+  // put some information in the texture window title?
+  sprintf (name, "Textures: in use");
+  gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), name);
+  Sys_UpdateWindows (W_TEXTURE);
 }
 
 }
 
+/*
+==============
+Texture_ShowInuse
+clear all IsDisplayed flags
+scan the map, set IsInUse (will set IsDisplayed on the way)
+NOTE: don't sort the textures, don't update the windows (it's used in several contexts, not always necessary to do either)
+==============
+*/
+void WINAPI Texture_ShowInuse (void)
+{
+  face_t  *f;
+  brush_t *b;
+  char  name[1024];
 
 
+  g_qeglobals.d_texturewin.originy = 0;
 
 
-class TextureCategoryLoadShader
-{
-  const char* m_directory;
-  std::size_t& m_count;
-public:
-  typedef const char* first_argument_type;
+  // purge
+  QERApp_ActiveShaders_SetDisplayed(false);
+  // scan and only display in-use stuff
+  Sys_Status("Selecting active textures", 0);
 
 
-  TextureCategoryLoadShader(const char* directory, std::size_t& count)
-    : m_directory(directory), m_count(count)
+  for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
   {
   {
-    m_count = 0;
+    if (b->patchBrush)
+    {
+      b->pPatch->pShader->SetInUse(true);
+    } else
+    {
+      for (f=b->brush_faces ; f ; f=f->next)
+      {
+        f->pShader->SetInUse(true);
+      }
+    }
   }
   }
-  void operator()(const char* name) const
+  for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
   {
   {
-    if(shader_equal_prefix(name, "textures/")
-      && shader_equal_prefix(name + string_length("textures/"), m_directory))
+    if (b->patchBrush)
     {
     {
-      ++m_count;
-      // request the shader, this will load the texture if needed
-      // this Shader_ForName call is a kind of hack
-      IShader *pFoo = QERApp_Shader_ForName(name);
-      pFoo->DecRef();
+      b->pPatch->pShader->SetInUse(true);
+    } else
+    {
+      for (f=b->brush_faces ; f ; f=f->next)
+      {
+        f->pShader->SetInUse(true);
+      }
     }
   }
     }
   }
-};
 
 
-void TextureDirectory_loadTexture(const char* directory, const char* texture)
-{
-  StringOutputStream name(256);
-  name << directory << StringRange(texture, path_get_filename_base_end(texture));
+  // we are no longer showing everything
+  g_bShowAllShaders = false;
+  // put some information in the texture window title?
+  sprintf (name, "Textures: in use");
+  gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), name);
 
 
-  if(texture_name_ignore(name.c_str()))
-  {
-    return;
-  }
 
 
-  if (!texdef_name_valid(name.c_str()))
+  // select the first texture in the list
+  if (!g_qeglobals.d_texturewin.texdef.GetName()[0])
   {
   {
-    globalOutputStream() << "Skipping invalid texture name: [" << name.c_str() << "]\n";
-    return;
+    SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
   }
   }
-
-  // if a texture is already in use to represent a shader, ignore it
-  IShader* shader = QERApp_Shader_ForName(name.c_str());
-  shader->DecRef();
 }
 }
-typedef ConstPointerCaller1<char, const char*, TextureDirectory_loadTexture> TextureDirectoryLoadTextureCaller;
 
 
-class LoadTexturesByTypeVisitor : public ImageModules::Visitor
+void Texture_ShowStartupShaders()
 {
 {
-  const char* m_dirstring;
-public:
-  LoadTexturesByTypeVisitor(const char* dirstring)
-    : m_dirstring(dirstring)
+  if (g_PrefsDlg.m_nShader == PrefsDlg::SHADER_COMMON)
   {
   {
+    // RIANT
+    // HACK FOR JK2 SUPPORT
+    if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game")
+    {
+      strcpy (texture_directory, "system/");
+    }
+    // RIANT
+    // HACK FOR SOF2 SUPPORT
+    else if (g_pGameDescription->mGameFile == "sof2.game")
+    {
+      strcpy (texture_directory, "tools/");
+    }
+    else strcpy (texture_directory, "common/");
+    Texture_ShowDirectory ();
   }
   }
-  void visit(const char* minor, const _QERPlugImageTable& table)
-  {
-    GlobalFileSystem().forEachFile(m_dirstring, minor, TextureDirectoryLoadTextureCaller(m_dirstring));
+
+  if (g_PrefsDlg.m_nShader == PrefsDlg::SHADER_ALL) {
+    int    count;
+    char   filename[1024];
+    char   *pBuff;
+    char   dirstring[NAME_MAX];
+    int    nLen;
+    GSList *shaderfiles = NULL;
+
+    strcpy(filename, g_pGameDescription->mShaderlist.GetBuffer());
+    count = vfsGetFileCount(filename, 0);
+    if (count == 0)
+    {
+      Sys_FPrintf(SYS_ERR, "Couldn't find '%s'\n", g_pGameDescription->mShaderlist.GetBuffer());
+      return;
+    }
+
+    if (!vfsGetFullPath(filename, 0, 0))
+    {
+      Sys_FPrintf(SYS_ERR, "Couldn't find full path for '%s'\n", g_pGameDescription->mShaderlist.GetBuffer());
+      return;
+    }
+
+    Sys_Printf("Parsing shader files from %s\n", vfsGetFullPath(filename, 0, 0));
+    nLen = vfsLoadFile (filename, reinterpret_cast<void**>(&pBuff), 0);
+    if (nLen > 0)
+    {
+      StartTokenParsing(pBuff);
+      nLen = 0;
+      while (GetToken(true))
+      {
+        GSList *tmp;
+        bool found = false;
+
+        // each token should be a shader filename
+        sprintf(dirstring, "%s.shader", token);
+
+        for (tmp = shaderfiles; tmp != NULL; tmp = tmp->next)
+        {
+          if (!strcmp (dirstring, (char*)tmp->data))
+          {
+            found = true;
+            Sys_FPrintf(SYS_WRN, "duplicate entry \"%s\" in shaderlist.txt\n", (char*)tmp->data);
+            break;
+          }
+        }
+
+        if (!found)
+        {
+          shaderfiles = g_slist_append (l_shaderfiles, strdup (dirstring));
+          strcpy (texture_directory, dirstring);
+          Texture_ShowDirectory ();
+          nLen++;
+        }
+      }
+      g_free(pBuff);
+    }
   }
   }
-};
+}
+
+/*
+============================================================================
 
 
-void TextureBrowser_ShowDirectory(TextureBrowser& textureBrowser, const char* directory)
+TEXTURE LAYOUT
+
+TTimo: now based on a rundown through all the shaders
+nActiveShadersCount: number of shader that have a qtexture_t and may be displayed in the tex window
+nCurrentShader: index of active shader that has the current_texture
+pCurrentShader: IShader* for current shader
+NOTE: we expect the Active shaders count doesn't change during a Texture_StartPos .. Texture_NextPos cycle
+  otherwise we may need to rely on a list instead of an array storage
+============================================================================
+*/
+
+void Texture_StartPos (void)
 {
 {
-  if(TextureGroupsMenu_showWads())
-  {
-    Archive* archive = GlobalFileSystem().getArchive(directory);
-    ASSERT_NOTNULL(archive);
-    LoadShaderVisitor visitor;
-    archive->forEachFile(Archive::VisitorFunc(visitor, Archive::eFiles, 0), "textures/");
-  }
-  else
+  //++timo TODO: check use of current_texture and current_row?
+  current_x = 8;
+  current_y = -8;
+  current_row = 0;
+  nActiveShadersCount = QERApp_GetActiveShaderCount();
+  nCurrentShader = -1;
+  current_texture = NULL;
+  pCurrentShader = NULL;
+}
+
+// if texture_showinuse jump over non in-use textures
+// it's not very clear what should be done here and what in Texture_Draw .. maybe merging the two would do good
+IShader* Texture_NextPos (int *x, int *y)
+{
+  qtexture_t* q;
+  while (1)
   {
   {
-    g_TextureBrowser_currentDirectory = directory;
-    TextureBrowser_heightChanged(textureBrowser);
+    if (nCurrentShader >= nActiveShadersCount - 1)
+    {
+      // no more shaders
+      current_texture = NULL;
+      pCurrentShader = NULL;
+      return NULL;
+    }
+    nCurrentShader++;
+    pCurrentShader = QERApp_ActiveShader_ForIndex(nCurrentShader);
+    if (pCurrentShader == NULL)
+    {
+      Sys_Printf("ERROR: unexpected pCurrentShader == NULL in Texture_NextPos\n");
+      return NULL;
+    }
+    current_texture = pCurrentShader->getTexture();
+    q = current_texture;
+
+    if (!q)
+    {
+      Sys_Printf("WARNING: found an IShader without qtexture_t in Texture_NextPos\n");
+      return NULL;
+    }
+
+    /*
+    Never show anything other than "textures/" path,
+    This is for q1/q2/q3 .map format, which expects "textures/" path on everything we apply
+    */
+    if(strncmp(pCurrentShader->getName(), "textures/", 9) != 0)
+      continue;
 
 
-    std::size_t shaders_count;
-    GlobalShaderSystem().foreachShaderName(makeCallback1(TextureCategoryLoadShader(directory, shaders_count)));
-    globalOutputStream() << "Showing " << Unsigned(shaders_count) << " shaders.\n";
+    // don't show shaders?
+    if (!(g_PrefsDlg.m_bShowShaders || pCurrentShader->IsDefault()))
+      continue;
 
 
-    if(g_pGameDescription->mGameType != "doom3")
+    if (g_PrefsDlg.m_bTextureWindow)
     {
     {
-      // load remaining texture files
+      // some basic filtering
+      if (!g_pParentWnd->GetTexWnd()->CheckFilter( pCurrentShader->getName() ))
+        continue;
+    }
 
 
-      StringOutputStream dirstring(64);
-      dirstring << "textures/" << directory;
+    //++timo FIXME: texture_showinuse is useless? with the menu and reload we just refresh the IsDisplayed flag
+    // but the IsInUse is only relevant to draw the green outline
+    if (pCurrentShader->IsDisplayed())
+      break;
 
 
-      {
-        LoadTexturesByTypeVisitor visitor(dirstring.c_str());
-        Radiant_getImageModules().foreachModule(visitor);
-      }
-    }
+    continue;
   }
 
   }
 
-  // we'll display the newly loaded textures + all the ones already in use
-  TextureBrowser_SetHideUnused(textureBrowser, false);
+  int nWidth = (int)(q->width * ((float)g_PrefsDlg.m_nTextureScale / 100));
+  int nHeight = (int)(q->height * ((float)g_PrefsDlg.m_nTextureScale / 100));
+  if (current_x + nWidth > g_qeglobals.d_texturewin.width-8 && current_row)
+  { // go to the next row unless the texture is the first on the row
+    current_x = 8;
+    current_y -= current_row + FONT_HEIGHT + 4;
+    current_row = 0;
+  }
 
 
-  TextureBrowser_updateTitle();
-}
+  *x = current_x;
+  *y = current_y;
 
 
+  // Is our texture larger than the row? If so, grow the
+  // row height to match it
 
 
-bool TextureBrowser_hideUnused();
+  if (current_row < nHeight)
+    current_row = nHeight;
 
 
-void TextureBrowser_hideUnusedExport(const BoolImportCallback& importer)
-{
-  importer(TextureBrowser_hideUnused());
-}
-typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_hideUnusedExport> TextureBrowserHideUnusedExport;
+  // never go less than 64, or the names get all crunched up
+  current_x += nWidth < 64 ? 64 : nWidth;
+  current_x += 8;
 
 
-void TextureBrowser_showShadersExport(const BoolImportCallback& importer)
-{
-  importer(GlobalTextureBrowser().m_showShaders);
+  return pCurrentShader;
 }
 }
-typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShadersExport> TextureBrowserShowShadersExport;
 
 
-void TextureBrowser_showShaderlistOnly(const BoolImportCallback& importer)
-{
-  importer(g_TexturesMenu_shaderlistOnly);
-}
-typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport;
+/*
+============================================================================
 
 
-class TexturesMenu
-{
-public:
-  ToggleItem m_hideunused_item;
-  ToggleItem m_showshaders_item;
-  ToggleItem m_showshaderlistonly_item;
-
-  TexturesMenu() :
-    m_hideunused_item(TextureBrowserHideUnusedExport()),
-    m_showshaders_item(TextureBrowserShowShadersExport()),
-    m_showshaderlistonly_item(TextureBrowserShowShaderlistOnlyExport())
-  {
-  }
-};
+  MOUSE ACTIONS
 
 
-TexturesMenu g_TexturesMenu;
+============================================================================
+*/
 
 
-void TextureBrowser_SetHideUnused(TextureBrowser& textureBrowser, bool hideUnused)
-{
-  if(hideUnused)
-  {
-    textureBrowser.m_hideUnused = true;
-  }
-  else
-  {
-    textureBrowser.m_hideUnused = false;
-  }
+static  int textures_cursorx, textures_cursory;
 
 
-  g_TexturesMenu.m_hideunused_item.update();
+/*
+============
+Texture_SetTexture
 
 
-  TextureBrowser_heightChanged(textureBrowser);
-  textureBrowser.m_originInvalid = true;
-}
+brushprimit_texdef must be understood as a qtexture_t with width=2 height=2 ( the default one )
+============
+*/
 
 
-void TextureBrowser_ShowStartupShaders(TextureBrowser& textureBrowser)
+//++timo NOTE: this is a mix of Shader module stuff and texture explorer
+// it might need to be split in parts or moved out .. dunno
+void WINAPI Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef *pTexdef, bool bSetSelection )
 {
 {
-  if(textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON)
+  if (texdef->GetName()[0] == '(')
   {
   {
-    TextureBrowser_ShowDirectory(textureBrowser, TextureBrowser_getComonShadersDir());
+    Sys_Status("Can't select an entity texture", 0);
+    return;
   }
   }
-  else if(textureBrowser.m_startupShaders == STARTUPSHADERS_ALL)
+  g_qeglobals.d_texturewin.texdef = *texdef;
+  g_qeglobals.d_texturewin.texdef.flags &= ~SURF_KEEP;
+  g_qeglobals.d_texturewin.texdef.contents &= ~CONTENTS_KEEP;
+  // store the shader pointer
+  // NOTE: maybe passing the shader pointer would help?
+  g_qeglobals.d_texturewin.pShader->DecRef();
+  g_qeglobals.d_texturewin.pShader = QERApp_Shader_ForName(texdef->GetName());
+  g_qeglobals.d_texturewin.pShader->IncRef();
+  // set this shader as in use
+  g_qeglobals.d_texturewin.pShader->SetInUse( true );
+  // store the texture coordinates for new brush primitive mode
+  // be sure that all the callers are using the default 2x2 texture
+  if (g_qeglobals.m_bBrushPrimitMode)
   {
   {
-    for(TextureMenuNames::const_iterator i = texture_menunames.begin(); i != texture_menunames.end(); ++i)
-    {
-      TextureBrowser_ShowDirectory(textureBrowser, (*i).c_str());
-    }
+    g_qeglobals.d_texturewin.brushprimit_texdef = *brushprimit_texdef;
   }
   }
-}
 
 
-
-//++timo NOTE: this is a mix of Shader module stuff and texture explorer
-// it might need to be split in parts or moved out .. dunno
-// scroll origin so the specified texture is completely on screen
-// if current texture is not displayed, nothing is changed
-void TextureBrowser_Focus(TextureBrowser& textureBrowser, const char* name)
-{
-  TextureLayout layout;
-  // scroll origin so the texture is completely on screen
-  Texture_StartPos(layout);
-  
-  for(QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement())
+  g_dlgFind.updateTextures(texdef->GetName());
+  if (!g_dlgFind.isOpen() && bSetSelection)
   {
   {
-    IShader* shader = QERApp_ActiveShaders_IteratorCurrent();
-
-    if(!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused, TextureBrowser_getFilter(textureBrowser)))
-      continue;
-
-    int x, y;
-    Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y);
-    qtexture_t* q = shader->getTexture();
-    if (!q)
-      break;
-
-    // we have found when texdef->name and the shader name match
-    // NOTE: as everywhere else for our comparisons, we are not case sensitive
-    if (shader_equal(name, shader->getName()))
-    {
-      int textureHeight = (int)(q->height * ((float)textureBrowser.m_textureScale / 100))
-        + 2 * TextureBrowser_fontHeight(textureBrowser);
-
-      int originy = TextureBrowser_getOriginY(textureBrowser);
-      if (y > originy)
-      {
-        originy = y;
-      }
+    Select_SetTexture(texdef,brushprimit_texdef,bFitScale);
+  }
 
 
-      if (y - textureHeight < originy - textureBrowser.height)
-      {
-        originy = (y - textureHeight) + textureBrowser.height;
-      }
+  //plugins: send a message telling that the selected texture may have changed
+  DispatchRadiantMsg( RADIANT_TEXTURE );
 
 
-      TextureBrowser_setOriginY(textureBrowser, originy);
-      return;
-    }
-  }
+  // scroll origin so the texture is completely on screen
+  // takes texdef from g_qeglobals.d_texturewin.texdef, set above
+  Texture_ResetPosition();
 }
 
 }
 
-IShader* Texture_At(TextureBrowser& textureBrowser, int mx, int my)
+void ViewShader(const char *pFile, const char *pName)
 {
 {
-  my += TextureBrowser_getOriginY(textureBrowser) - textureBrowser.height;
-
-  TextureLayout layout;
-  Texture_StartPos(layout);
-  for(QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement())
+  //  ask the vfs to build the full path to the file
+  // (i.e. the first one found)
+  char *fullName = vfsGetFullPath(pFile,0,0);
+  if (fullName == NULL)
   {
   {
-    IShader* shader = QERApp_ActiveShaders_IteratorCurrent();
-
-    if(!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused, TextureBrowser_getFilter(textureBrowser)))
-      continue;
+    Sys_FPrintf (SYS_ERR, "Couldn't get a full path to the shader file: %s\n", pFile);
+    return;
+  }
 
 
-    int   x, y;
-    Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y);
-    qtexture_t  *q = shader->getTexture();
-    if (!q)
+  char* pBuff = NULL;
+  int nSize = vfsLoadFullPathFile(fullName, reinterpret_cast<void**>(&pBuff));
+  if (nSize <= 0)
+  {
+    Sys_FPrintf (SYS_ERR, "Failed to load shader file %s\n", fullName);
+    return;
+  }
+  // look for the shader declaration
+  int nStart;
+  CString strFind = pName;
+  CString strLook = pBuff;
+  strLook.MakeLower();
+  strFind.MakeLower();
+  // offset used when jumping over commented out definitions
+  int nOffset = 0;
+  while (true)
+  {
+    nStart = strLook.Find(strFind, nOffset);
+    if (nStart == -1)
       break;
       break;
-
-    int nWidth = (int)(q->width * ((float)textureBrowser.m_textureScale / 100));
-    int nHeight = (int)(q->height * ((float)textureBrowser.m_textureScale / 100));
-    if (mx > x && mx - x < nWidth
-      && my < y && y - my < nHeight + TextureBrowser_fontHeight(textureBrowser))
+    // we have found something, maybe it's a commented out shader name?
+    char *strCheck = new char[strLook.GetLength()+1];
+    strcpy( strCheck, strLook.GetBuffer() );
+    strCheck[nStart] = 0;
+    char *pCheck = strrchr( strCheck, '\n' );
+    // if there's a commentary sign in-between we'll continue
+    if (pCheck && strstr( pCheck, "//" ))
     {
     {
-      return shader;
+      delete[] strCheck;
+      nOffset = nStart + 1;
+      continue;
     }
     }
+    delete[] strCheck;
+    nOffset = nStart;
+    break;
   }
   }
+  // now close the file
+  g_free(pBuff);
 
 
-  return 0;
+  DoTextEditor (fullName, nOffset);
 }
 
 /*
 }
 
 /*
@@ -1090,69 +1289,140 @@ SelectTexture
   By mouse click
 ==============
 */
   By mouse click
 ==============
 */
-void SelectTexture(TextureBrowser& textureBrowser, int mx, int my, bool bShift)
+void SelectTexture (int mx, int my, bool bShift, bool bFitScale)
 {
 {
-  IShader* shader = Texture_At(textureBrowser, mx, my);
-  if(shader != 0)
+  int   x, y;
+  qtexture_t  *q;
+  texdef_t  tex;
+  brushprimit_texdef_t brushprimit_tex;
+
+  my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
+
+  Texture_StartPos ();
+  while (1)
   {
   {
-    if (bShift)
+    // NOTE: return value is == pCurrentShader and pCurrentShader->getTexture == current_texture
+    Texture_NextPos (&x, &y);
+    q = current_texture;
+    if (!q)
+      break;
+    int nWidth = (int)(q->width * ((float)g_PrefsDlg.m_nTextureScale / 100));
+    int nHeight = (int)(q->height * ((float)g_PrefsDlg.m_nTextureScale / 100));
+    if (mx > x && mx - x < nWidth
+      && my < y && y - my < nHeight + FONT_HEIGHT)
     {
     {
-      if (shader->IsDefault())
-        globalOutputStream() << "ERROR: " << shader->getName() << " is not a shader, it's a texture.\n";
+      if (bShift)
+      {
+        if (pCurrentShader->IsDefault())
+          Sys_Printf("ERROR: %s is not a shader, it's a texture.\n", pCurrentShader->getName() );
+        else
+          ViewShader( pCurrentShader->getShaderFileName(), pCurrentShader->getName() );
+      }
       else
       else
-        ViewShader( shader->getShaderFileName(), shader->getName() );
-    }
-    else
-    {
-      TextureBrowser_SetSelectedShader(textureBrowser, shader->getName());
-      TextureBrowser_textureSelected(shader->getName());
-
-      if (!FindTextureDialog_isOpen())
       {
       {
-        UndoableCommand undo("textureNameSetSelected");
-        Select_SetShader(shader->getName());
+        memset (&tex, 0, sizeof(tex));
+        memset (&brushprimit_tex, 0, sizeof(brushprimit_tex));
+        if (g_qeglobals.m_bBrushPrimitMode)
+        {
+          // brushprimit fitted to a 2x2 texture
+          brushprimit_tex.coords[0][0] = 1.0f;
+          brushprimit_tex.coords[1][1] = 1.0f;
+        }
+        else
+        {
+          tex.scale[0] = g_pGameDescription->mTextureDefaultScale;
+          tex.scale[1] = g_pGameDescription->mTextureDefaultScale;
+        }
+        tex.flags = pCurrentShader->getFlags();
+        // TTimo - shader code cleanup
+        // texdef.name is the name of the shader, not the name of the actual texture file
+        tex.SetName(pCurrentShader->getName());
+        // NOTE WARNING: Texture_SetTexture uses Texture_NextPos stuff to move the window position on to the texture
+        // if there's some kind of fuckup in Texture_SetTexture you may end up with different pCurrentShader or even pCurrentShader == NULL
+        // so we just consider pCurrentShader and current_texture are not valid after this point
+        IShader *pAuxShader = pCurrentShader;
+        Texture_SetTexture ( &tex, &brushprimit_tex, bFitScale, NULL); // Nurail
+        CString strTex;
+        CString strName;
+        // if shader, print shader name, otherwise texture name
+        //++timo FIXME: maybe CShader needs some properties between color / default / actual shader
+#ifdef _DEBUG
+        // this one is never supposed to be set as current one
+        if (pAuxShader->IsColor())
+          Sys_Printf("ERROR: unexpected pCurrentShader->IsColor() in SelectTexture\n");
+#endif
+        // NOTE: IsColor is false, IsDefault the only remaining property
+        if (pAuxShader->IsDefault())
+        {
+          strName = q->name;
+          // remove the "textures/" if needed
+          if (strName.Find("textures/")!=-1)
+            strName = strName.Mid(9);
+        }
+        else
+        {
+          strName = pAuxShader->getName();
+        }
+        strTex.Format("%s W: %i H: %i", strName.GetBuffer(), q->width, q->height);
+        g_pParentWnd->SetStatusText(3, strTex);
       }
       }
+      return;
     }
   }
     }
   }
+
+  Sys_Status("Did not select a texture", 0);
 }
 
 /*
 }
 
 /*
-============================================================================
-
-  MOUSE ACTIONS
-
-============================================================================
+==============
+Texture_MouseDown
+==============
 */
 */
-
-void TextureBrowser_trackingDelta(int x, int y, unsigned int state, void* data)
+void Texture_MouseDown (int x, int y, int buttons)
 {
 {
-  TextureBrowser& textureBrowser = *reinterpret_cast<TextureBrowser*>(data);
-  if(y != 0)
-  {
-    int scale = 1;
+  Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
 
 
-    if(state & GDK_SHIFT_MASK)
-      scale = 4;
-
-    int originy = TextureBrowser_getOriginY(textureBrowser);
-    originy += y * scale;
-    TextureBrowser_setOriginY(textureBrowser, originy);
+  // lbutton = select texture
+  if (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_SHIFT) || buttons == (MK_LBUTTON | MK_CONTROL))
+  {
+    SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y, buttons & MK_SHIFT, buttons & MK_CONTROL);
+    UpdateSurfaceDialog();
+    UpdatePatchInspector();
   }
 }
 
   }
 }
 
-void TextureBrowser_Tracking_MouseDown(TextureBrowser& textureBrowser)
-{
-  textureBrowser.m_freezePointer.freeze_pointer(textureBrowser.m_parent, TextureBrowser_trackingDelta, &textureBrowser);
-}
+/*
+==============
+Texture_MouseMoved
+==============
+*/
 
 
-void TextureBrowser_Tracking_MouseUp(TextureBrowser& textureBrowser)
+void Texture_MouseMoved (int x, int y, int buttons)
 {
 {
-  textureBrowser.m_freezePointer.unfreeze_pointer(textureBrowser.m_parent);
-}
+  int scale = 1;
 
 
-void TextureBrowser_Selection_MouseDown(TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy)
-{
-  SelectTexture(textureBrowser, pointx, textureBrowser.height - 1 - pointy, (flags & GDK_SHIFT_MASK) != 0);
+  if ( buttons & MK_SHIFT )
+    scale = 4;
+
+  // rbutton = drag texture origin
+  if (buttons & MK_RBUTTON)
+  {
+    Sys_GetCursorPos (&x, &y);
+    if ( y != textures_cursory)
+    {
+      g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
+      if (g_qeglobals.d_texturewin.originy > 0)
+        g_qeglobals.d_texturewin.originy = 0;
+      Sys_SetCursorPos (textures_cursorx, textures_cursory);
+
+      // (g_PrefsDlg.m_bTextureScrollbar && g_qeglobals_gui.d_texture_scroll != NULL)
+      // fixes broken texture scrolling when scrollbar is disabled
+      GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_qeglobals_gui.d_texture_scroll));
+      gtk_adjustment_set_value (vadjustment, abs(g_qeglobals.d_texturewin.originy));
+      //
+    }
+    return;
+  }
 }
 
 /*
 }
 
 /*
@@ -1163,6 +1433,8 @@ DRAWING
 ============================================================================
 */
 
 ============================================================================
 */
 
+int imax(int iFloor, int i) { if (i>iFloor) return iFloor;return i;}
+
 /*
 ============
 Texture_Draw
 /*
 ============
 Texture_Draw
@@ -1171,571 +1443,516 @@ we must query all qtexture_t* to manage and display through the IShaders interfa
 this allows a plugin to completely override the texture system
 ============
 */
 this allows a plugin to completely override the texture system
 ============
 */
-void Texture_Draw(TextureBrowser& textureBrowser)
-{
-  int originy = TextureBrowser_getOriginY(textureBrowser);
-
-  glClearColor(textureBrowser.color_textureback[0],
-    textureBrowser.color_textureback[1],
-    textureBrowser.color_textureback[2],
-    0);
-  glViewport(0, 0, textureBrowser.width, textureBrowser.height);
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-
-  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  glDisable (GL_DEPTH_TEST);
-  glDisable(GL_BLEND);
-  glOrtho (0, textureBrowser.width, originy-textureBrowser.height, originy, -100, 100);
-  glEnable (GL_TEXTURE_2D);
-
-  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-
-  int last_y = 0, last_height = 0;
-
-  TextureLayout layout;
-  Texture_StartPos(layout);
-  for(QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement())
-  {
-    IShader* shader = QERApp_ActiveShaders_IteratorCurrent();
-
-    if(!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused, TextureBrowser_getFilter(textureBrowser)))
-      continue;
-
-    int x, y;
-    Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y);
-    qtexture_t *q = shader->getTexture();
+void Texture_Draw (int width, int height)
+{
+  int x, y, last_y = 0, last_height = 0, nWidth, nHeight;
+  qtexture_t *q;
+  char *name;
+
+  qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
+                 g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
+                 g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2], 0);
+  qglViewport (0,0,width,height);
+  qglMatrixMode(GL_PROJECTION);
+  qglLoadIdentity ();
+
+  qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  qglDisable (GL_DEPTH_TEST);
+  qglDisable(GL_BLEND);
+  qglOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
+  qglEnable (GL_TEXTURE_2D);
+
+  qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+  g_qeglobals.d_texturewin.width = width;
+  g_qeglobals.d_texturewin.height = height;
+
+  Texture_StartPos();
+  for (;;)
+  {
+    // NOTE: return value is == pCurrentShader and pCurrentShader->getTexture == current_texture
+    Texture_NextPos (&x, &y);
+    q = current_texture;
     if (!q)
       break;
 
     if (!q)
       break;
 
-    int nWidth = (int)(q->width * ((float)textureBrowser.m_textureScale / 100));
-    int nHeight = (int)(q->height * ((float)textureBrowser.m_textureScale / 100));
+    nWidth = (int)(q->width * ((float)g_PrefsDlg.m_nTextureScale / 100));
+    nHeight = (int)(q->height * ((float)g_PrefsDlg.m_nTextureScale / 100));
 
     if (y != last_y)
     {
       last_y = y;
       last_height = 0;
     }
 
     if (y != last_y)
     {
       last_y = y;
       last_height = 0;
     }
-    last_height = std::max (nHeight, last_height);
+    last_height = MAX (nHeight, last_height);
 
     // Is this texture visible?
 
     // Is this texture visible?
-    if ((y-nHeight-TextureBrowser_fontHeight(textureBrowser) < originy)
-        && (y > originy - textureBrowser.height))
+    if ((y-nHeight-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
+        && (y > g_qeglobals.d_texturewin.originy - height))
     {
       // borders rules:
       // if it's the current texture, draw a thick red line, else:
       // shaders have a white border, simple textures don't
       // if !texture_showinuse: (some textures displayed may not be in use)
       // draw an additional square around with 0.5 1 0.5 color
     {
       // borders rules:
       // if it's the current texture, draw a thick red line, else:
       // shaders have a white border, simple textures don't
       // if !texture_showinuse: (some textures displayed may not be in use)
       // draw an additional square around with 0.5 1 0.5 color
-      if (shader_equal(TextureBrowser_GetSelectedShader(textureBrowser), shader->getName()))
+      if (!strcmpi(g_qeglobals.d_texturewin.texdef.GetName(), pCurrentShader->getName()))
       {
       {
-             glLineWidth (3);
-             glColor3f (1,0,0);
-             glDisable (GL_TEXTURE_2D);
-
-             glBegin (GL_LINE_LOOP);
-             glVertex2i (x-4,y-TextureBrowser_fontHeight(textureBrowser)+4);
-             glVertex2i (x-4,y-TextureBrowser_fontHeight(textureBrowser)-nHeight-4);
-             glVertex2i (x+4+nWidth,y-TextureBrowser_fontHeight(textureBrowser)-nHeight-4);
-             glVertex2i (x+4+nWidth,y-TextureBrowser_fontHeight(textureBrowser)+4);
-             glEnd();
-
-             glEnable (GL_TEXTURE_2D);
-             glLineWidth (1);
+             qglLineWidth (3);
+             qglColor3f (1,0,0);
+             qglDisable (GL_TEXTURE_2D);
+
+             qglBegin (GL_LINE_LOOP);
+             qglVertex2f (x-4,y-FONT_HEIGHT+4);
+             qglVertex2f (x-4,y-FONT_HEIGHT-nHeight-4);
+             qglVertex2f (x+4+nWidth,y-FONT_HEIGHT-nHeight-4);
+             qglVertex2f (x+4+nWidth,y-FONT_HEIGHT+4);
+             qglEnd ();
+
+             qglEnable (GL_TEXTURE_2D);
+             qglLineWidth (1);
       }
       else
       {
       }
       else
       {
-             glLineWidth (1);
+             qglLineWidth (1);
              // shader border:
              // shader border:
-             if (!shader->IsDefault())
+             if (!pCurrentShader->IsDefault())
              {
              {
-               glColor3f (1,1,1);
-               glDisable (GL_TEXTURE_2D);
-
-               glBegin (GL_LINE_LOOP);
-               glVertex2i (x-1,y+1-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x-1,y-nHeight-1-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x+1+nWidth,y-nHeight-1-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x+1+nWidth,y+1-TextureBrowser_fontHeight(textureBrowser));
-               glEnd();
-               glEnable (GL_TEXTURE_2D);
+               qglColor3f (1,1,1);
+               qglDisable (GL_TEXTURE_2D);
+
+               qglBegin (GL_LINE_LOOP);
+               qglVertex2f (x-1,y+1-FONT_HEIGHT);
+               qglVertex2f (x-1,y-nHeight-1-FONT_HEIGHT);
+               qglVertex2f (x+1+nWidth,y-nHeight-1-FONT_HEIGHT);
+               qglVertex2f (x+1+nWidth,y+1-FONT_HEIGHT);
+               qglEnd ();
+               qglEnable (GL_TEXTURE_2D);
              }
 
              // highlight in-use textures
              }
 
              // highlight in-use textures
-             if (!textureBrowser.m_hideUnused && shader->IsInUse())
+             if (pCurrentShader->IsInUse())
              {
              {
-               glColor3f (0.5,1,0.5);
-               glDisable (GL_TEXTURE_2D);
-               glBegin (GL_LINE_LOOP);
-               glVertex2i (x-3,y+3-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x-3,y-nHeight-3-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x+3+nWidth,y-nHeight-3-TextureBrowser_fontHeight(textureBrowser));
-               glVertex2i (x+3+nWidth,y+3-TextureBrowser_fontHeight(textureBrowser));
-               glEnd();
-               glEnable (GL_TEXTURE_2D);
+               qglColor3f (0.5,1,0.5);
+               qglDisable (GL_TEXTURE_2D);
+               qglBegin (GL_LINE_LOOP);
+               qglVertex2f (x-3,y+3-FONT_HEIGHT);
+               qglVertex2f (x-3,y-nHeight-3-FONT_HEIGHT);
+               qglVertex2f (x+3+nWidth,y-nHeight-3-FONT_HEIGHT);
+               qglVertex2f (x+3+nWidth,y+3-FONT_HEIGHT);
+               qglEnd ();
+               qglEnable (GL_TEXTURE_2D);
              }
       }
 
       // Draw the texture
              }
       }
 
       // Draw the texture
-      glBindTexture (GL_TEXTURE_2D, q->texture_number);
-      GlobalOpenGL_debugAssertNoErrors();
-      glColor3f (1,1,1);
-      glBegin (GL_QUADS);
-      glTexCoord2i (0,0);
-      glVertex2i (x,y-TextureBrowser_fontHeight(textureBrowser));
-      glTexCoord2i (1,0);
-      glVertex2i (x+nWidth,y-TextureBrowser_fontHeight(textureBrowser));
-      glTexCoord2i (1,1);
-      glVertex2i (x+nWidth,y-TextureBrowser_fontHeight(textureBrowser)-nHeight);
-      glTexCoord2i (0,1);
-      glVertex2i (x,y-TextureBrowser_fontHeight(textureBrowser)-nHeight);
-      glEnd();
+      qglBindTexture (GL_TEXTURE_2D, q->texture_number);
+      QE_CheckOpenGLForErrors();
+      qglColor3f (1,1,1);
+      qglBegin (GL_QUADS);
+      qglTexCoord2f (0,0);
+      qglVertex2f (x,y-FONT_HEIGHT);
+      qglTexCoord2f (1,0);
+      qglVertex2f (x+nWidth,y-FONT_HEIGHT);
+      qglTexCoord2f (1,1);
+      qglVertex2f (x+nWidth,y-FONT_HEIGHT-nHeight);
+      qglTexCoord2f (0,1);
+      qglVertex2f (x,y-FONT_HEIGHT-nHeight);
+      qglEnd ();
 
       // draw the texture name
 
       // draw the texture name
-      glDisable (GL_TEXTURE_2D);
-      glColor3f (1,1,1);
+      qglDisable (GL_TEXTURE_2D);
+      qglColor3f (1,1,1);
 
 
-      glRasterPos2i (x, y-TextureBrowser_fontHeight(textureBrowser)+2);
+      qglRasterPos2f (x, y-FONT_HEIGHT+2);
 
       // don't draw the directory name
 
       // don't draw the directory name
-      const char* name = shader->getName();
+      name = (char*)pCurrentShader->getName();
       name += strlen(name);
       name += strlen(name);
-      while(name != shader->getName() && *(name-1) != '/' && *(name-1) != '\\')
+      while(name != (char*)pCurrentShader->getName() && *(name-1) != '/' && *(name-1) != '\\')
         name--;
 
         name--;
 
-      GlobalOpenGL().drawString(name);
-      glEnable (GL_TEXTURE_2D);
+      gtk_glwidget_print_string(name);
+      qglEnable (GL_TEXTURE_2D);
     }
     }
-
-    //int totalHeight = abs(y) + last_height + TextureBrowser_fontHeight(textureBrowser) + 4;
   }
 
   }
 
+  g_qeglobals.d_texturewin.m_nTotalHeight = abs(y) + last_height + FONT_HEIGHT + 4;
 
   // reset the current texture
 
   // reset the current texture
-  glBindTexture(GL_TEXTURE_2D, 0);
-  //qglFinish();
+  qglBindTexture(GL_TEXTURE_2D, 0);
+  qglFinish();
 }
 
 }
 
-void TextureBrowser_queueDraw(TextureBrowser& textureBrowser)
+//++timo seems we only know hard inits now..
+//void Texture_Init (bool bHardInit)
+void Texture_Init()
 {
 {
-  if(textureBrowser.m_gl_widget != 0)
+  g_qeglobals.d_qtextures = NULL;
+  // initialize the qtexture map
+  if (g_qeglobals.d_qtexmap)
   {
   {
-    gtk_widget_queue_draw(textureBrowser.m_gl_widget);
+    Sys_FPrintf(SYS_ERR, "TODO: delete g_qeglobals.d_qtexmap in Texture_Init\n");
   }
   }
+  g_qeglobals.d_qtexmap = g_hash_table_new (g_str_hash, g_str_equal);
+  // initialize .. in some cases if no default texture / project loaded it crashes
+  memset( &g_qeglobals.d_texturewin.texdef, 0, sizeof(g_qeglobals.d_texturewin.texdef) );
+  g_qeglobals.d_texturewin.texdef.SetName(SHADER_NOT_FOUND);
+  g_qeglobals.d_texturewin.pShader = QERApp_Shader_ForName(SHADER_NOT_FOUND);
 }
 
 }
 
-
-void TextureBrowser_setScale(TextureBrowser& textureBrowser, std::size_t scale)
-{
-  textureBrowser.m_textureScale = scale;
-
-  TextureBrowser_queueDraw(textureBrowser);
-}
-
-
-void TextureBrowser_MouseWheel(TextureBrowser& textureBrowser, bool bUp)
+// FIXME TTimo this needs to move to the shader module along with l_shaderlist move
+// preload shader files that have been listed in shaderlist.txt
+void PreloadShaders()
 {
 {
-  int originy = TextureBrowser_getOriginY(textureBrowser);
-
-  if (bUp)
+  GSList *lst = l_shaderfiles;
+  Str shadername;
+  while (lst)
   {
   {
-    originy += int(textureBrowser.m_mouseWheelScrollIncrement);
+    shadername = g_pGameDescription->mShaderPath;
+    shadername += (char*)lst->data;
+    QERApp_LoadShaderFile(shadername.GetBuffer());
+    lst = lst->next;
   }
   }
-  else
-  {
-    originy -= int(textureBrowser.m_mouseWheelScrollIncrement);
-  }
-
-  TextureBrowser_setOriginY(textureBrowser, originy);
 }
 
 }
 
-
-
-gboolean TextureBrowser_button_press(GtkWidget* widget, GdkEventButton* event, TextureBrowser* textureBrowser)
+// TTimo: modified to expect the reletive path to the skin as input
+// will look into pak files if necessary
+// uses the shader code to load the texture Try_Texture_ForName
+// modified SkinInfo accordingly to store the qtexture_t and shader name (reletive version)
+// the .md3 have bundled filetype extension, but they don't fit with the actual data
+//   ex: models/mapobjects/gargoyle.tga doesn't exist, but models/mapobjects/gargoyle.jpg can be used instead
+//   so we remove the extension before load attempt
+int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight)
 {
 {
-  if(event->type == GDK_BUTTON_PRESS)
-  {
-    if(event->button == 3)
-    {
-      TextureBrowser_Tracking_MouseDown(*textureBrowser);
-    }
-    else if(event->button == 1)
-    {
-      TextureBrowser_Selection_MouseDown(*textureBrowser, event->state, static_cast<int>(event->x), static_cast<int>(event->y));
-    }
-  }
-  return FALSE;
-}
+  //  byte *pic = NULL;
+  //  byte *pic32 = NULL;
+  int nTex = -1;
+  qtexture_t *qtex;
+  SkinInfo *pInfo;
+  const char *pCleanName;
 
 
-gboolean TextureBrowser_button_release(GtkWidget* widget, GdkEventButton* event, TextureBrowser* textureBrowser)
-{
-  if(event->type == GDK_BUTTON_RELEASE)
+  int nSize = g_lstSkinCache.GetSize();
+  pCleanName = QERApp_CleanTextureName( pName, false );
+  for (int i = 0; i < nSize; i++)
   {
   {
-    if(event->button == 3)
+    SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
+    if (pInfo)
     {
     {
-      TextureBrowser_Tracking_MouseUp(*textureBrowser);
+      if (stricmp(pCleanName, pInfo->m_strName) == 0)
+      {
+        return pInfo->m_nTextureBind;
+      }
     }
   }
     }
   }
-  return FALSE;
-}
-
-gboolean TextureBrowser_motion(GtkWidget *widget, GdkEventMotion *event, TextureBrowser* textureBrowser)
-{
-  return FALSE;
-}
 
 
-gboolean TextureBrowser_scroll(GtkWidget* widget, GdkEventScroll* event, TextureBrowser* textureBrowser)
-{
-  if(event->direction == GDK_SCROLL_UP)
+  // if the load is successfull, we get back a qtexture_t
+  // we don't need to free it, it's in g_qeglobals.d_qtextures
+  // NOTE: we need to free the SkinInfo though..
+  qtex = QERApp_Try_Texture_ForName( pCleanName );
+  if (qtex)
   {
   {
-    TextureBrowser_MouseWheel(*textureBrowser, true);
-  }
-  else if(event->direction == GDK_SCROLL_DOWN)
+    nTex = qtex->texture_number;
+    pInfo = new SkinInfo(qtex->name, nTex, qtex);
+  } else
   {
   {
-    TextureBrowser_MouseWheel(*textureBrowser, false);
+    pInfo = new SkinInfo(pCleanName, -1, NULL);
   }
   }
-  return FALSE;
+  g_lstSkinCache.Add(pInfo);
+
+  return nTex;
 }
 
 }
 
-void TextureBrowser_scrollChanged(void* data, gdouble value)
+bool TexWnd::CheckFilter( const char* name )
 {
 {
-  //globalOutputStream() << "vertical scroll\n";
-  TextureBrowser_setOriginY(*reinterpret_cast<TextureBrowser*>(data), -(int)value);
+  const char* buf = gtk_entry_get_text (GTK_ENTRY (m_pFilter));
+  if (strstr( name, buf ) != 0)
+    return true;
+  return false;
 }
 
 }
 
-static void TextureBrowser_verticalScroll(GtkAdjustment *adjustment, TextureBrowser* textureBrowser)
+// =============================================================================
+// static functions
+
+static void vertical_scroll (GtkWidget *widget, gpointer data)
 {
 {
-  textureBrowser->m_scrollAdjustment.value_changed(adjustment->value);
+  ((TexWnd*)data)->OnVScroll ();
 }
 
 }
 
-void TextureBrowser_updateScroll(TextureBrowser& textureBrowser)
+static void filter_changed (GtkWidget *widget, gpointer data)
 {
 {
-  if(textureBrowser.m_showTextureScrollbar)
-  {
-    int totalHeight = TextureBrowser_TotalHeight(textureBrowser);
-
-    totalHeight = std::max(totalHeight, textureBrowser.height);
-
-    GtkAdjustment *vadjustment = gtk_range_get_adjustment(GTK_RANGE(textureBrowser.m_texture_scroll));
+  CString str;
+  str = gtk_entry_get_text (GTK_ENTRY (widget));
+  ((TexWnd*)data)->UpdateFilter (str);
+}
 
 
-    vadjustment->value = -TextureBrowser_getOriginY(textureBrowser);
-    vadjustment->page_size = textureBrowser.height;
-    vadjustment->page_increment = textureBrowser.height/2;
-    vadjustment->step_increment = 20;
-    vadjustment->lower = 0;
-    vadjustment->upper = totalHeight;
+// =============================================================================
+// TexWnd class
 
 
-    g_signal_emit_by_name(G_OBJECT (vadjustment), "changed");
-  }
+TexWnd::TexWnd()
+: GLWindow (FALSE)
+{
+  m_pFilter = NULL;
+  m_bNeedRange = true;
 }
 
 }
 
-gboolean TextureBrowser_size_allocate(GtkWidget* widget, GtkAllocation* allocation, TextureBrowser* textureBrowser)
+TexWnd::~TexWnd()
 {
 {
-  textureBrowser->width = allocation->width;
-  textureBrowser->height = allocation->height;
-  TextureBrowser_heightChanged(*textureBrowser);
-  textureBrowser->m_originInvalid = true;
-  TextureBrowser_queueDraw(*textureBrowser);
-  return FALSE;
 }
 
 }
 
-gboolean TextureBrowser_expose(GtkWidget* widget, GdkEventExpose* event, TextureBrowser* textureBrowser)
+void TexWnd::OnCreate ()
 {
 {
-  if(glwidget_make_current(textureBrowser->m_gl_widget) != FALSE)
-  {
-    GlobalOpenGL_debugAssertNoErrors();
-    TextureBrowser_evaluateHeight(*textureBrowser);
-    Texture_Draw(*textureBrowser);
-    GlobalOpenGL_debugAssertNoErrors();
-    glwidget_swap_buffers(textureBrowser->m_gl_widget);
-  }
-  return FALSE;
-}
+  if (!MakeCurrent ())
+    Error ("glMakeCurrent in TexWnd::OnCreate failed");
 
 
+  g_qeglobals_gui.d_texture = m_pWidget;
+  g_nTextureOffset = 0;
 
 
-TextureBrowser g_TextureBrowser;
+  GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_qeglobals_gui.d_texture_scroll));
+  gtk_signal_connect (GTK_OBJECT (vadjustment), "value_changed", GTK_SIGNAL_FUNC (vertical_scroll), this);
 
 
-TextureBrowser& GlobalTextureBrowser()
-{
-  return g_TextureBrowser;
-}
+  if (g_PrefsDlg.m_bTextureScrollbar)
+    gtk_widget_show (g_qeglobals_gui.d_texture_scroll);
+  else
+    gtk_widget_hide (g_qeglobals_gui.d_texture_scroll);
+  m_bNeedRange = true;
 
 
-bool TextureBrowser_hideUnused()
-{
-  return g_TextureBrowser.m_hideUnused;
+  gtk_signal_connect (GTK_OBJECT (m_pFilter), "changed", GTK_SIGNAL_FUNC (filter_changed), this);
+  if (g_PrefsDlg.m_bTextureWindow)
+    gtk_widget_show (m_pFilter);
 }
 
 }
 
-void TextureBrowser_ToggleHideUnused()
+void TexWnd::UpdateFilter(const char* pFilter)
 {
 {
-  if(g_TextureBrowser.m_hideUnused)
-  {
-    TextureBrowser_SetHideUnused(g_TextureBrowser, false);
-  }
-  else
+  g_bFilterEnabled = false;
+  if (pFilter)
   {
   {
-    TextureBrowser_SetHideUnused(g_TextureBrowser, true);
+    g_strFilter = pFilter;
+    if (g_strFilter.GetLength() > 0)
+      g_bFilterEnabled = true;
+    QERApp_SortActiveShaders();
   }
   }
+  Sys_UpdateWindows (W_TEXTURE);
 }
 
 }
 
-GtkWidget* TextureBrowser_constructWindow(GtkWindow* toplevel)
+void TexWnd::OnSize (int cx, int cy)
 {
 {
-  GlobalShaderSystem().setActiveShadersChangedNotify(ReferenceCaller<TextureBrowser, TextureBrowser_activeShadersChanged>(g_TextureBrowser));
-
-  GtkWidget* hbox = gtk_hbox_new (FALSE, 0);
-
-  g_TextureBrowser.m_parent = toplevel;
+  m_bNeedRange = true;
+}
 
 
+void TexWnd::OnExpose ()
+{
+  int nOld = g_qeglobals.d_texturewin.m_nTotalHeight;
+  if (!MakeCurrent ())
   {
   {
-         GtkWidget* w = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0,0,0,1,1,1)));
-         gtk_widget_show (w);
-         gtk_box_pack_end (GTK_BOX (hbox), w, FALSE, TRUE, 0);
-         g_TextureBrowser.m_texture_scroll = w;
-
-    GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_TextureBrowser.m_texture_scroll));
-    g_signal_connect(G_OBJECT(vadjustment), "value_changed", G_CALLBACK(TextureBrowser_verticalScroll), &g_TextureBrowser);
-
-    widget_set_visible(g_TextureBrowser.m_texture_scroll, g_TextureBrowser.m_showTextureScrollbar);
+    Sys_Printf("ERROR: glXMakeCurrent failed..\n ");
+    Sys_Printf("Please restart Radiant if the Texture view is not working\n");
+  } else
+  {
+    QE_CheckOpenGLForErrors();
+    Texture_Draw (m_pWidget->allocation.width, m_pWidget->allocation.height - g_nTextureOffset);
+    QE_CheckOpenGLForErrors();
+    SwapBuffers ();
   }
   }
+  if (g_PrefsDlg.m_bTextureScrollbar && (m_bNeedRange || g_qeglobals.d_texturewin.m_nTotalHeight != nOld))
   {
   {
-         GtkWidget* texbox = gtk_vbox_new (FALSE, 0);
-         gtk_widget_show(texbox);
-         gtk_box_pack_start(GTK_BOX(hbox), texbox, TRUE, TRUE, 0);
-
-         {
-                 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
-                 gtk_box_pack_start(GTK_BOX(texbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
-
-                 g_TextureBrowser.m_filter = entry;
-      if(g_TextureBrowser.m_showTextureFilter)
-      {
-        gtk_widget_show(GTK_WIDGET(g_TextureBrowser.m_filter));
-      }
-
-      g_TextureBrowser.m_filterEntry.connect(entry);
-         }
-
-         {
-      g_TextureBrowser.m_gl_widget = glwidget_new(FALSE);
-      gtk_widget_ref(g_TextureBrowser.m_gl_widget);
-
-      gtk_widget_set_events(g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK);
-      GTK_WIDGET_SET_FLAGS(g_TextureBrowser.m_gl_widget, GTK_CAN_FOCUS);
+    GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_qeglobals_gui.d_texture_scroll));
 
 
-                 gtk_box_pack_start(GTK_BOX(texbox), g_TextureBrowser.m_gl_widget, TRUE, TRUE, 0);
-                 gtk_widget_show(g_TextureBrowser.m_gl_widget);
-
-      g_TextureBrowser.m_sizeHandler = g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "size_allocate", G_CALLBACK(TextureBrowser_size_allocate), &g_TextureBrowser);
-      g_TextureBrowser.m_exposeHandler = g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "expose_event", G_CALLBACK(TextureBrowser_expose), &g_TextureBrowser);
-
-      g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "button_press_event", G_CALLBACK(TextureBrowser_button_press), &g_TextureBrowser);
-      g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "button_release_event", G_CALLBACK(TextureBrowser_button_release), &g_TextureBrowser);
-      g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "motion_notify_event", G_CALLBACK(TextureBrowser_motion), &g_TextureBrowser);
-      g_signal_connect(G_OBJECT(g_TextureBrowser.m_gl_widget), "scroll_event", G_CALLBACK(TextureBrowser_scroll), &g_TextureBrowser);
-         }
-       }
-  TextureBrowser_updateScroll(g_TextureBrowser);
+    vadjustment->value = -g_qeglobals.d_texturewin.originy;
+    vadjustment->page_size = m_pWidget->allocation.height;
+    vadjustment->page_increment = m_pWidget->allocation.height/2;
+    vadjustment->step_increment = 20;
+    vadjustment->lower = 0;
+    vadjustment->upper = g_qeglobals.d_texturewin.m_nTotalHeight;
 
 
-  gtk_container_set_focus_chain(GTK_CONTAINER(hbox), NULL);
+    gtk_signal_emit_by_name (GTK_OBJECT (vadjustment), "changed");
 
 
-  return hbox;
+    m_bNeedRange = false;
+  }
 }
 
 }
 
-void TextureBrowser_destroyWindow()
+void TexWnd::OnLButtonDown (guint32 flags, int pointx, int pointy)
 {
 {
-  GlobalShaderSystem().setActiveShadersChangedNotify(Callback());
-
-  g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_sizeHandler);
-  g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_exposeHandler);
-
-  gtk_widget_unref(g_TextureBrowser.m_gl_widget);
+  SetCapture ();
+  Texture_MouseDown (pointx, pointy - g_nTextureOffset, flags);
 }
 
 }
 
-const Vector3& TextureBrowser_getBackgroundColour(TextureBrowser& textureBrowser)
+void TexWnd::OnRButtonDown (guint32 flags, int pointx, int pointy)
 {
 {
-  return textureBrowser.color_textureback;
+  SetCapture ();
+  Texture_MouseDown (pointx, pointy - g_nTextureOffset, flags);
 }
 
 }
 
-void TextureBrowser_setBackgroundColour(TextureBrowser& textureBrowser, const Vector3& colour)
+void TexWnd::OnMButtonDown (guint32 flags, int pointx, int pointy)
 {
 {
-  textureBrowser.color_textureback = colour;
-  TextureBrowser_queueDraw(textureBrowser);
+  SetCapture ();
+  Texture_MouseDown (pointx, pointy - g_nTextureOffset, flags);
 }
 
 }
 
-
-void TextureBrowser_ToggleShowShaders() 
+void TexWnd::OnLButtonUp (guint32 flags, int pointx, int pointy)
 {
 {
-  g_TextureBrowser.m_showShaders ^= 1;
-  g_TexturesMenu.m_showshaders_item.update();
-  TextureBrowser_queueDraw(g_TextureBrowser);
+  ReleaseCapture ();
+  DragDropTexture (flags, pointx, pointy);
 }
 
 }
 
-void TextureBrowser_ToggleShowShaderListOnly() 
+void TexWnd::OnRButtonUp (guint32 flags, int pointx, int pointy)
 {
 {
-  g_TexturesMenu_shaderlistOnly ^= 1;
-  g_TexturesMenu.m_showshaderlistonly_item.update();
-  TextureGroupsMenu_Destroy();
-  TextureGroupsMenu_Construct();
+  ReleaseCapture ();
 }
 
 }
 
-void TextureBrowser_showAll()
+void TexWnd::OnMButtonUp (guint32 flags, int pointx, int pointy)
 {
 {
-  g_TextureBrowser_currentDirectory = "";
-  TextureBrowser_heightChanged(g_TextureBrowser);
-  TextureBrowser_updateTitle();
+  ReleaseCapture ();
 }
 
 }
 
-void TextureBrowser_exportTitle(const StringImportCallback& importer)
+void TexWnd::OnMouseMove (guint32 flags, int pointx, int pointy)
 {
 {
-  StringOutputStream buffer(64);
-  buffer << "Textures: ";
-  if(!string_empty(g_TextureBrowser_currentDirectory.c_str()))
-  {
-    buffer << g_TextureBrowser_currentDirectory.c_str();
-  }
-  else
-  {
-    buffer << "all";
-  }
-  importer(buffer.c_str());
+  Texture_MouseMoved (pointx, pointy - g_nTextureOffset, flags);
+  // if scrollbar is hidden, we don't seem to get an update
+  if( !g_PrefsDlg.m_bTextureScrollbar )
+    RedrawWindow ();
 }
 
 }
 
+void TexWnd::OnVScroll ()
+{
+  GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_qeglobals_gui.d_texture_scroll));
+
+  g_qeglobals.d_texturewin.originy = - (int)vadjustment->value;
+  RedrawWindow ();
+}
 
 
-void TextureScaleImport(TextureBrowser& textureBrowser, int value)
+void TexWnd::UpdatePrefs()
 {
 {
-  switch(value)
-  {
-  case 0:
-    TextureBrowser_setScale(textureBrowser, 10);
-    break;
-  case 1:
-    TextureBrowser_setScale(textureBrowser, 25);
-    break;
-  case 2:
-    TextureBrowser_setScale(textureBrowser, 50);
-    break;
-  case 3:
-    TextureBrowser_setScale(textureBrowser, 100);
-    break;
-  case 4:
-    TextureBrowser_setScale(textureBrowser, 200);
-    break;
-  }
+  if (g_PrefsDlg.m_bTextureWindow)
+    gtk_widget_show (m_pFilter);
+  else
+    gtk_widget_hide (m_pFilter);
+
+  if (g_PrefsDlg.m_bTextureScrollbar)
+    gtk_widget_show (g_qeglobals_gui.d_texture_scroll);
+  else
+    gtk_widget_hide (g_qeglobals_gui.d_texture_scroll);
+  m_bNeedRange = true;
+  RedrawWindow ();
 }
 }
-typedef ReferenceCaller1<TextureBrowser, int, TextureScaleImport> TextureScaleImportCaller;
 
 
-void TextureScaleExport(TextureBrowser& textureBrowser, const IntImportCallback& importer)
+void TexWnd::FocusEdit()
 {
 {
-  switch(textureBrowser.m_textureScale)
-  {
-  case 10:
-    importer(0);
-    break;
-  case 25:
-    importer(1);
-    break;
-  case 50:
-    importer(2);
-    break;
-  case 100:
-    importer(3);
-    break;
-  case 200:
-    importer(4);
-    break;
-  }
+  if (GTK_WIDGET_VISIBLE (m_pFilter))
+    gtk_window_set_focus (GTK_WINDOW (g_pParentWnd->m_pWidget), m_pFilter);
 }
 }
-typedef ReferenceCaller1<TextureBrowser, const IntImportCallback&, TextureScaleExport> TextureScaleExportCaller;
 
 
-void TextureBrowser_constructPreferences(PreferencesPage& page)
+void TexWnd::OnMouseWheel(bool bUp)
 {
 {
-  page.appendCheckBox(
-    "", "Texture subsets",
-    TextureBrowserImportShowFilterCaller(GlobalTextureBrowser()),
-    BoolExportCaller(GlobalTextureBrowser().m_showTextureFilter)
-  );
-  page.appendCheckBox(
-    "", "Texture scrollbar",
-    TextureBrowserImportShowScrollbarCaller(GlobalTextureBrowser()),
-    BoolExportCaller(GlobalTextureBrowser().m_showTextureScrollbar)
-  );
+  if (bUp)
   {
   {
-    const char* texture_scale[] = { "10%", "25%", "50%", "100%", "200%" };
-    page.appendCombo(
-      "Texture Thumbnail Scale",
-      STRING_ARRAY_RANGE(texture_scale),
-      IntImportCallback(TextureScaleImportCaller(GlobalTextureBrowser())),
-      IntExportCallback(TextureScaleExportCaller(GlobalTextureBrowser()))
-    );
+    if(g_qeglobals.d_texturewin.originy < 0) {
+      g_qeglobals.d_texturewin.originy += g_PrefsDlg.m_nWheelInc;
+      // clamp so we don't get jiggle if moved by less than scrollwheel increment
+      if(g_qeglobals.d_texturewin.originy > 0) {
+        g_qeglobals.d_texturewin.originy = 0;
+      }
+    }
   }
   }
-  page.appendEntry("Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement);
+  else
   {
   {
-    const char* startup_shaders[] = { "None", TextureBrowser_getComonShadersName(), "All" };
-    page.appendCombo("Load Shaders at Startup", reinterpret_cast<int&>(GlobalTextureBrowser().m_startupShaders), STRING_ARRAY_RANGE(startup_shaders));
+    if(g_qeglobals.d_texturewin.originy > (-g_qeglobals.d_texturewin.m_nTotalHeight + g_qeglobals.d_texturewin.height))
+      g_qeglobals.d_texturewin.originy -= g_PrefsDlg.m_nWheelInc;
   }
   }
+  GtkAdjustment *vadjustment = gtk_range_get_adjustment (GTK_RANGE (g_qeglobals_gui.d_texture_scroll));
+  gtk_adjustment_set_value (vadjustment, abs(g_qeglobals.d_texturewin.originy));
+
+  RedrawWindow();
 }
 }
-void TextureBrowser_constructPage(PreferenceGroup& group)
-{
-  PreferencesPage page(group.createPage("Texture Browser", "Texture Browser Preferences"));
-  TextureBrowser_constructPreferences(page);
-}
-void TextureBrowser_registerPreferencesPage()
+
+void TexWnd::DragDropTexture (guint32 flags, int pointx, int pointy)
 {
 {
-  PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, TextureBrowser_constructPage>());
-}
+  // This gets called from leftmouse up event. We see if the mouseup is above
+  // the camwindow. If this is the case do a trace for a surface. If we hit a
+  // surface, texture it with the current texture.
+
+  int     m_ptXcheck, m_ptYcheck;
+  int     m_ptX, m_ptY;
+  GtkWidget *widget;
+  gint x, y;
+  vec3_t  dir;
+  float          f, r, u;
+  int     i;
+
+  // we only want to catch a plain mouseevent
+  if (flags)
+    return;
+
+  // see if we are above the camwindow
+  Sys_GetCursorPos (&m_ptX, &m_ptY);
 
 
+  if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
+    widget = g_pParentWnd->GetCamWnd()->m_pParent;
+  else
+    widget = g_pParentWnd->GetCamWnd()->GetWidget();
 
 
-#include "preferencesystem.h"
-#include "stringio.h"
+  get_window_pos (widget, &x, &y);
 
 
-typedef ReferenceCaller1<TextureBrowser, std::size_t, TextureBrowser_setScale> TextureBrowserSetScaleCaller;
+  if (m_ptX < x || m_ptY < y ||
+      m_ptX > x + widget->allocation.width ||
+      m_ptY > y + widget->allocation.height)
+    return;
 
 
+  // check if the camwindow isn't being partially hidden by another window at this point
+  m_ptXcheck = m_ptX;
+  m_ptYcheck = m_ptY;
 
 
+  if( g_pParentWnd->GetCamWnd()->GetWidget()->window != gdk_window_at_pointer( &m_ptXcheck, &m_ptYcheck ) )
+    return;
 
 
-void TextureClipboard_textureSelected(const char* shader);
+  // calc ray direction
+  x = m_ptX - x;
+  y = g_pParentWnd->GetCamWnd()->Camera()->height - 1 - (m_ptY - y);
+  u = (float)( y - ( g_pParentWnd->GetCamWnd()->Camera()->height * .5f ) ) / ( g_pParentWnd->GetCamWnd()->Camera()->height * .5f );
+  r = (float)( x - ( g_pParentWnd->GetCamWnd()->Camera()->width * .5f ) ) / ( g_pParentWnd->GetCamWnd()->Camera()->width * .5f );
+  f = 1;
 
 
-void TextureBrowser_Construct()
-{
-  GlobalToggles_insert("ShowInUse", FreeCaller<TextureBrowser_ToggleHideUnused>(), ToggleItem::AddCallbackCaller(g_TexturesMenu.m_hideunused_item), Accelerator('U'));
-  GlobalCommands_insert("ShowAllTextures", FreeCaller<TextureBrowser_showAll>(), Accelerator('A', (GdkModifierType)GDK_CONTROL_MASK));
-  GlobalCommands_insert("ViewTextures", FreeCaller<TextureBrowser_toggleShown>(), Accelerator('T'));
-  GlobalToggles_insert("ToggleShowShaders", FreeCaller<TextureBrowser_ToggleShowShaders>(), ToggleItem::AddCallbackCaller(g_TexturesMenu.m_showshaders_item));
-  GlobalToggles_insert("ToggleShowShaderlistOnly", FreeCaller<TextureBrowser_ToggleShowShaderListOnly>(), ToggleItem::AddCallbackCaller(g_TexturesMenu.m_showshaderlistonly_item));
-
-  GlobalPreferenceSystem().registerPreference("TextureScale",
-    makeSizeStringImportCallback(TextureBrowserSetScaleCaller(g_TextureBrowser)),
-    SizeExportStringCaller(g_TextureBrowser.m_textureScale)
-  );
-  GlobalPreferenceSystem().registerPreference("NewTextureWindowStuff",
-    makeBoolStringImportCallback(TextureBrowserImportShowFilterCaller(g_TextureBrowser)),
-    BoolExportStringCaller(GlobalTextureBrowser().m_showTextureFilter)
-  );
-  GlobalPreferenceSystem().registerPreference("TextureScrollbar",
-    makeBoolStringImportCallback(TextureBrowserImportShowScrollbarCaller(g_TextureBrowser)),
-    BoolExportStringCaller(GlobalTextureBrowser().m_showTextureScrollbar)
-  );
-  GlobalPreferenceSystem().registerPreference("ShowShaders", BoolImportStringCaller(GlobalTextureBrowser().m_showShaders), BoolExportStringCaller(GlobalTextureBrowser().m_showShaders));
-  GlobalPreferenceSystem().registerPreference("ShowShaderlistOnly", BoolImportStringCaller(g_TexturesMenu_shaderlistOnly), BoolExportStringCaller(g_TexturesMenu_shaderlistOnly));
-  GlobalPreferenceSystem().registerPreference("LoadShaders", IntImportStringCaller(reinterpret_cast<int&>(GlobalTextureBrowser().m_startupShaders)), IntExportStringCaller(reinterpret_cast<int&>(GlobalTextureBrowser().m_startupShaders)));
-  GlobalPreferenceSystem().registerPreference("WheelMouseInc", SizeImportStringCaller(GlobalTextureBrowser().m_mouseWheelScrollIncrement), SizeExportStringCaller(GlobalTextureBrowser().m_mouseWheelScrollIncrement));
-  GlobalPreferenceSystem().registerPreference("SI_Colors0", Vector3ImportStringCaller(GlobalTextureBrowser().color_textureback), Vector3ExportStringCaller(GlobalTextureBrowser().color_textureback));
-
-  g_TextureBrowser.shader = texdef_name_default();
-
-  Textures_setModeChangedNotify(ReferenceCaller<TextureBrowser, TextureBrowser_queueDraw>(g_TextureBrowser));
-
-  TextureBrowser_registerPreferencesPage();
-
-  GlobalShaderSystem().attach(g_ShadersObserver);
-  GlobalShaderSystem().attach(g_TextureGroupsMenu);
-  GlobalFileSystem().attach(g_TextureGroupsMenu);
-
-  TextureBrowser_textureSelected = TextureClipboard_textureSelected;
-}
-void TextureBrowser_Destroy()
-{
-  GlobalFileSystem().detach(g_TextureGroupsMenu);
-  GlobalShaderSystem().detach(g_TextureGroupsMenu);
-  GlobalShaderSystem().detach(g_ShadersObserver);
+  for (i=0 ; i<3 ; i++)
+    dir[i] = g_pParentWnd->GetCamWnd()->Camera()->vpn[i] * f +
+        g_pParentWnd->GetCamWnd()->Camera()->vright[i] * r +
+        g_pParentWnd->GetCamWnd()->Camera()->vup[i] * u;
+  VectorNormalize (dir, dir);
 
 
-  Textures_setModeChangedNotify(Callback());
+  // do a trace for a surface
+       trace_t t;
+
+       t = Test_Ray (g_pParentWnd->GetCamWnd()->Camera()->origin, dir, SF_SINGLEFACE);
+
+  if (t.brush)
+  {
+    texdef_t  tex;
+    brushprimit_texdef_t brushprimit_tex;
+
+    memset (&tex, 0, sizeof(tex));
+    memset (&brushprimit_tex, 0, sizeof(brushprimit_tex));
+    if (g_qeglobals.m_bBrushPrimitMode)
+    {
+      // brushprimit fitted to a 2x2 texture
+      brushprimit_tex.coords[0][0] = 1.0f;
+      brushprimit_tex.coords[1][1] = 1.0f;
+    } else
+    {
+      tex.scale[0] = g_pGameDescription->mTextureDefaultScale;
+      tex.scale[1] = g_pGameDescription->mTextureDefaultScale;
+    }
+    tex.flags = g_qeglobals.d_texturewin.texdef.flags;
+    tex.value = g_qeglobals.d_texturewin.texdef.value;
+    tex.contents = g_qeglobals.d_texturewin.texdef.contents;
+    // TTimo - shader code cleanup
+    // texdef.name is the name of the shader, not the name of the actual texture file
+    tex.SetName(g_qeglobals.d_texturewin.texdef.GetName());
+
+    Undo_Start("set face textures");
+         Undo_AddBrush(t.brush);
+         SetFaceTexdef (t.face, &tex, &brushprimit_tex, false, NULL );
+         Brush_Build(t.brush, false);
+         Undo_EndBrush(t.brush);
+         Undo_End();
+
+    Sys_UpdateWindows (W_CAMERA);
+    g_pParentWnd->OnTimer ();
+  }
 }
 }