Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

TexWnd.cpp (76521B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // TexWnd.cpp : implementation file
     23 //
     24 
     25 #include "stdafx.h"
     26 #include <assert.h>
     27 #include "Radiant.h"
     28 #include "TexWnd.h"
     29 #include "qe3.h"
     30 #include "io.h"
     31 #include "PrefsDlg.h"
     32 #include "shaderinfo.h"
     33 #include "pakstuff.h"
     34 #include "str.h"
     35 #include "PrefsDlg.h"
     36 
     37 Str m_gStr;
     38 
     39 #ifdef _DEBUG
     40 #define new DEBUG_NEW
     41 #undef THIS_FILE
     42 static char THIS_FILE[] = __FILE__;
     43 #endif
     44 
     45 qtexture_t *Texture_ForNamePath(char* name, char* pFullPath);
     46 #define	TYP_MIPTEX	68
     47 static unsigned	tex_palette[256];
     48 
     49 qtexture_t	*notexture = NULL;
     50 qtexture_t	*g_pluginTexture = NULL;
     51 
     52 static qboolean	nomips = false;
     53 
     54 #define	FONT_HEIGHT	10
     55 
     56 HGLRC s_hglrcTexture = NULL;
     57 HDC	 s_hdcTexture = NULL;
     58 
     59 //int		texture_mode = GL_NEAREST;
     60 //int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
     61 //int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
     62 //int		texture_mode = GL_LINEAR;
     63 //int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
     64 int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
     65 
     66 // this is the global counter for GL bind numbers
     67 int		texture_extension_number = 1;
     68 int g_nCurrentTextureMenuName;
     69 
     70 int g_nTextureOffset = 0;
     71 
     72 // current active texture directory.  if empty, show textures in use
     73 char		texture_directory[128];	// use if texture_showinuse is false
     74 qboolean	texture_showinuse;
     75 
     76 bool g_bFilterEnabled = false;
     77 CString g_strFilter;
     78 
     79 // texture layout functions
     80 qtexture_t	*current_texture = NULL;
     81 int			current_x, current_y, current_row;
     82 
     83 int			texture_nummenus;
     84 #define		MAX_TEXTUREDIRS	128
     85 char		texture_menunames[MAX_TEXTUREDIRS][128];
     86 
     87 qboolean	g_dontuse = true;		// set to true to load the texture but not flag as used
     88 
     89 // void SelectTexture (int mx, int my, bool bShift = false);
     90 void SelectTexture (int mx, int my, bool bShift, bool bFitScale=false);
     91 
     92 void	Texture_MouseDown (int x, int y, int buttons);
     93 void	Texture_MouseUp (int x, int y, int buttons);
     94 void	Texture_MouseMoved (int x, int y, int buttons);
     95 
     96 CPtrArray g_lstShaders;
     97 CPtrArray g_lstSkinCache;
     98 
     99 struct SkinInfo
    100 {
    101   CString m_strName;
    102   int m_nTextureBind;
    103   SkinInfo(const char *pName, int n)
    104   {
    105     m_strName = pName;
    106     m_nTextureBind = n;
    107   };
    108   SkinInfo(){};
    109 };
    110 
    111 // checks wether a qtexture_t exists for a given name
    112 //++timo FIXME: is this really any use? redundant.
    113 bool ShaderQTextureExists(const char *pName)
    114 {
    115   for (qtexture_t *q=g_qeglobals.d_qtextures ; q ; q=q->next)
    116   {
    117     if (!strcmp(q->name,  pName))
    118     {
    119       return true;
    120     }
    121   }
    122   return false;
    123 
    124 }
    125 
    126 CShaderInfo* hasShader(const char *pName)
    127 {
    128   int nSize = g_lstShaders.GetSize();
    129   for (int i = 0; i < nSize; i++)
    130   {
    131     CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
    132     if (pInfo != NULL)
    133     {
    134       if (pInfo->m_strName.CompareNoCase(pName) == 0)
    135       {
    136         return pInfo;
    137       }
    138     }
    139   }
    140   return NULL;
    141 }
    142 
    143 // gets active texture extension
    144 // 
    145 // FIXME: fix this to be generic from project file
    146 //
    147 int GetTextureExtensionCount()
    148 {
    149   return 2;
    150 }
    151 
    152 const char* GetTextureExtension(int nIndex)
    153 {
    154   if ( nIndex == 0)
    155   {
    156     _QERTextureInfo *pInfo = g_pParentWnd->GetPlugInMgr().GetTextureInfo();
    157     const char *pTex = (pInfo != NULL) ? pInfo->m_TextureExtension : NULL;
    158     return (pTex == NULL) ? (g_PrefsDlg.m_bHiColorTextures == FALSE) ? "wal" : "tga" : pTex;
    159   }
    160   // return jpg for 2nd extension
    161   return "jpg";
    162 }
    163 
    164 void SortTextures(void)
    165 {	
    166 	qtexture_t	*q, *qtemp, *qhead, *qcur, *qprev;
    167 
    168 	// standard insertion sort
    169 	// Take the first texture from the list and
    170 	// add it to our new list
    171 	if ( g_qeglobals.d_qtextures == NULL)
    172 		return;	
    173 
    174 	qhead = g_qeglobals.d_qtextures;
    175 	q = g_qeglobals.d_qtextures->next;
    176 	qhead->next = NULL;
    177 	
    178 	// while there are still things on the old
    179 	// list, keep adding them to the new list
    180 	while (q)
    181 	{
    182 		qtemp = q;
    183 		q = q->next;
    184 		
    185 		qprev = NULL;
    186 		qcur = qhead;
    187 
    188 		while (qcur)
    189 		{
    190 			// Insert it here?
    191 			if (strcmp(qtemp->name, qcur->name) < 0)
    192 			{
    193 				qtemp->next = qcur;
    194 				if (qprev)
    195 					qprev->next = qtemp;
    196 				else
    197 					qhead = qtemp;
    198 				break;
    199 			}
    200 			
    201 			// Move on
    202 
    203 			qprev = qcur;
    204 			qcur = qcur->next;
    205 
    206 
    207 			// is this one at the end?
    208 
    209 			if (qcur == NULL)
    210 			{
    211 				qprev->next = qtemp;
    212 				qtemp->next = NULL;
    213 			}
    214 		}
    215 
    216 
    217 	}
    218 
    219 	g_qeglobals.d_qtextures = qhead;
    220 }
    221 
    222 /*
    223 ==============
    224 Texture_InitPalette
    225 ==============
    226 */
    227 void Texture_InitPalette (byte *pal)
    228 {
    229     int		r,g,b,v;
    230     int		i;
    231 	int		inf;
    232 	byte	gammatable[256];
    233 	float	gamma;
    234 
    235 	gamma = g_qeglobals.d_savedinfo.fGamma;
    236 
    237 	if (gamma == 1.0)
    238 	{
    239 		for (i=0 ; i<256 ; i++)
    240 			gammatable[i] = i;
    241 	}
    242 	else
    243 	{
    244 		for (i=0 ; i<256 ; i++)
    245 		{
    246 			inf = 255 * pow ( (float)( (i+0.5)/255.5 ), gamma ) + 0.5;
    247 			if (inf < 0)
    248 				inf = 0;
    249 			if (inf > 255)
    250 				inf = 255;
    251 			gammatable[i] = inf;
    252 		}
    253 	}
    254 
    255     for (i=0 ; i<256 ; i++)
    256     {
    257 		  r = gammatable[pal[0]];
    258 		  g = gammatable[pal[1]];
    259 		  b = gammatable[pal[2]];
    260 		  pal += 3;
    261 		
    262 		  v = (r<<24) + (g<<16) + (b<<8) + 255;
    263 		  v = BigLong (v);
    264 		
    265 		  tex_palette[i] = v;
    266     }
    267 }
    268 
    269 void SetTexParameters (void)
    270 {
    271 	qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
    272 	
    273 	switch ( texture_mode )
    274 	{
    275 	case GL_NEAREST:
    276 	case GL_NEAREST_MIPMAP_NEAREST:
    277 	case GL_NEAREST_MIPMAP_LINEAR:
    278 		qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    279 		break;
    280 	case GL_LINEAR:
    281 	case GL_LINEAR_MIPMAP_NEAREST:
    282 	case GL_LINEAR_MIPMAP_LINEAR:
    283 		qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    284 		break;
    285 	}
    286 }
    287 
    288 /*
    289 ============
    290 Texture_SetMode
    291 ============
    292 */
    293 void Texture_SetMode(int iMenu)
    294 {
    295 	int	i, iMode;
    296 	HMENU hMenu;
    297 	qboolean texturing = true;
    298 
    299 	hMenu = GetMenu(g_qeglobals.d_hwndMain);
    300 
    301 	switch(iMenu) {
    302 	case ID_VIEW_NEAREST:					
    303 		iMode = GL_NEAREST;
    304 		break;
    305 	case ID_VIEW_NEARESTMIPMAP:
    306 		iMode = GL_NEAREST_MIPMAP_NEAREST;
    307 		break;
    308 	case ID_VIEW_LINEAR:
    309 		iMode = GL_NEAREST_MIPMAP_LINEAR;
    310 		break;
    311 	case ID_VIEW_BILINEAR:
    312 		iMode = GL_LINEAR;
    313 		break;
    314 	case ID_VIEW_BILINEARMIPMAP:
    315 		iMode = GL_LINEAR_MIPMAP_NEAREST;
    316 		break;
    317 	case ID_VIEW_TRILINEAR:
    318 		iMode = GL_LINEAR_MIPMAP_LINEAR;
    319 		break;
    320 
    321 	case ID_TEXTURES_WIREFRAME:
    322 		iMode = 0;
    323 		texturing = false;
    324 		break;
    325 
    326 	case ID_TEXTURES_FLATSHADE:
    327 		iMode = 0;
    328 		texturing = false;
    329 		break;
    330 
    331 	}
    332 
    333 	CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
    334 	CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
    335 	CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
    336 	CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
    337 	CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
    338 	CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
    339 	CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
    340 	CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);
    341 
    342 	CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);
    343 
    344 	g_qeglobals.d_savedinfo.iTexMenu = iMenu;
    345 	texture_mode = iMode;
    346 
    347   if (g_PrefsDlg.m_bSGIOpenGL)
    348   {
    349     if (s_hdcTexture && s_hglrcTexture)
    350     {
    351       //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
    352       if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
    353 		    Error ("wglMakeCurrent in LoadTexture failed");
    354     }
    355     else
    356       return;
    357   }
    358 
    359 	if ( texturing )
    360 		SetTexParameters ();
    361 
    362 	if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
    363 	{
    364 		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_wire;
    365 		Map_BuildBrushData();
    366 		Sys_UpdateWindows (W_ALL);
    367 		return;
    368 
    369 	} else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {
    370 
    371 		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_solid;
    372 		Map_BuildBrushData();
    373 		Sys_UpdateWindows (W_ALL);
    374 		return;
    375 	}
    376 
    377 	for (i=1 ; i<texture_extension_number ; i++)
    378 	{
    379 		qglBindTexture( GL_TEXTURE_2D, i );
    380 		SetTexParameters ();
    381 	}
    382 
    383 	// select the default texture
    384 	qglBindTexture( GL_TEXTURE_2D, 0 );
    385 
    386 	qglFinish();
    387 
    388 	if (g_pParentWnd->GetCamera()->Camera().draw_mode != cd_texture)
    389 	{
    390 		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_texture;
    391 		Map_BuildBrushData();
    392 	}
    393 
    394 	Sys_UpdateWindows (W_ALL);
    395 }
    396 
    397 /*
    398 ================
    399 R_MipMap
    400 
    401 Operates in place, quartering the size of the texture
    402 ================
    403 */
    404 void R_MipMap (byte *in, int &width, int &height)
    405 {
    406 	int		i, j;
    407 	byte	*out;
    408 	int		row;
    409 	
    410 	row = width * 4;
    411 	width >>= 1;
    412 	height >>= 1;
    413 	out = in;
    414 	for (i=0 ; i<height ; i++, in+=row)
    415 	{
    416 		for (j=0 ; j<width ; j++, out+=4, in+=8)
    417 		{
    418 			out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
    419 			out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
    420 			out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
    421 			out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
    422 		}
    423 	}
    424 }
    425 
    426 /*
    427 =================
    428 Texture_LoadTexture
    429 =================
    430 */
    431 //++timo NOTE: miptex_t is used only for .WAL format .. a bit outdated
    432 qtexture_t *Texture_LoadTexture (miptex_t *qtex)
    433 {
    434   byte		*source;
    435   unsigned	char *dest;
    436   int			width, height, i, count;
    437 	int			total[3];
    438   qtexture_t	*q;
    439       
    440   width = LittleLong(qtex->width);
    441   height = LittleLong(qtex->height);
    442 
    443   q = (qtexture_t*)qmalloc(sizeof(*q));
    444 
    445   q->width = width;
    446   q->height = height;
    447 
    448 	q->flags = qtex->flags;
    449 	q->value = qtex->value;
    450 	q->contents = qtex->contents;
    451 
    452 	dest = (unsigned char*)qmalloc (width*height*4);
    453 
    454   count = width*height;
    455   source = (byte *)qtex + LittleLong(qtex->offsets[0]);
    456 
    457 	// The dib is upside down so we want to copy it into 
    458 	// the buffer bottom up.
    459 
    460 	total[0] = total[1] = total[2] = 0;
    461   for (i=0 ; i<count ; i++)
    462 	{
    463 		dest[i] = tex_palette[source[i]];
    464 
    465 		total[0] += ((byte *)(dest+i))[0];
    466 		total[1] += ((byte *)(dest+i))[1];
    467 		total[2] += ((byte *)(dest+i))[2];
    468 	}
    469 
    470 	q->color[0] = (float)total[0]/(count*255);
    471 	q->color[1] = (float)total[1]/(count*255);
    472 	q->color[2] = (float)total[2]/(count*255);
    473 
    474   q->texture_number = texture_extension_number++;
    475 
    476   if (g_qeglobals.bSurfacePropertiesPlugin)
    477   {
    478 	  // Timo
    479 	  // Surface properties plugins can store their own data in an IPluginQTexture
    480 	  q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
    481 	  GETPLUGINTEXDEF(q)->InitForMiptex( qtex );
    482   }
    483 
    484   //++timo is the m_bSGIOpenGL parameter still taken into account?
    485   if (g_PrefsDlg.m_bSGIOpenGL)
    486   {
    487     //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
    488     if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
    489 		  Error ("wglMakeCurrent in LoadTexture failed");
    490   }
    491 
    492   qglBindTexture( GL_TEXTURE_2D, q->texture_number );
    493 
    494   //Handle3DfxTexturing(q, width, height, dest);
    495 
    496   SetTexParameters ();
    497 
    498   int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
    499   while (nCount-- > 0)
    500   {
    501     if (width > 16 && height > 16)
    502     {
    503       R_MipMap(dest, width, height);
    504     }
    505     else
    506     {
    507       break;
    508     }
    509   }
    510 
    511   if (g_PrefsDlg.m_bSGIOpenGL)
    512   {
    513 	  if (nomips)
    514     {
    515 		  qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
    516     }
    517 	  else
    518 		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
    519   }
    520   else
    521   {
    522 	  if (nomips)
    523 		  qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
    524 	  else
    525 		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
    526   }
    527 
    528 	free (dest);
    529 
    530 	qglBindTexture( GL_TEXTURE_2D, 0 );
    531 
    532   return q;
    533 }
    534 
    535 
    536 
    537 
    538 /*
    539 =================
    540 Texture_LoadTexture
    541 =================
    542 */
    543 qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char* pPath, int nFlags, int nContents, int nValue )
    544 {
    545   int i, j, inf;
    546 	byte	gammatable[256];
    547 	float fGamma = g_qeglobals.d_savedinfo.fGamma;
    548 
    549 
    550   qtexture_t* q = (qtexture_t*)qmalloc(sizeof(*q));
    551   q->width = nWidth;
    552   q->height = nHeight;
    553 	q->flags = nFlags;
    554 	q->value = nValue;
    555 	q->contents = nContents;
    556 
    557   int nCount = nWidth * nHeight;
    558   float total[3];
    559   total[0] = total[1] = total[2] = 0.0f;
    560 
    561   //++timo FIXME: move gamma table initialization somewhere else!
    562 	if (fGamma == 1.0)
    563 	{
    564 		for (i=0 ; i<256 ; i++)
    565 			gammatable[i] = i;
    566 	}
    567 	else
    568 	{
    569 		for (i=0 ; i<256 ; i++)
    570 		{
    571 			inf = 255 * pow ( (float)( (i+0.5)/255.5 ), fGamma ) + 0.5;
    572 			if (inf < 0)
    573 				inf = 0;
    574 			if (inf > 255)
    575 				inf = 255;
    576 			gammatable[i] = inf;
    577 		}
    578 	}
    579 
    580 
    581   // all targas are stored internally as 32bit so rgba = 4 bytes
    582   for (i = 0 ; i < (nCount * 4) ; i += 4)
    583 	{
    584     for (j = 0; j < 3; j++)
    585     {
    586 	    total[j] += (pPixels+i)[j];
    587       byte b = (pPixels+i)[j];
    588       (pPixels+i)[j] = gammatable[b];
    589               
    590     }
    591 	}
    592 
    593 	q->color[0] = total[0] / (nCount * 255);
    594 	q->color[1] = total[1] / (nCount * 255);
    595 	q->color[2] = total[2] / (nCount * 255);
    596 
    597 
    598   q->texture_number = texture_extension_number++;
    599 
    600   if (g_qeglobals.bSurfacePropertiesPlugin)
    601   {
    602 	  // Timo
    603 	  // Surface properties plugins can store their own data in an IPluginQTexture
    604 	  q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
    605 	  GETPLUGINTEXDEF(q)->SetDefaultTexdef();
    606   }
    607 
    608   if (g_PrefsDlg.m_bSGIOpenGL)
    609   {
    610     //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
    611     if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
    612 		  Error ("wglMakeCurrent in LoadTexture failed");
    613   }
    614 
    615   qglBindTexture( GL_TEXTURE_2D, q->texture_number );
    616 
    617   //Handle3DfxTexturing(q, width, height, dest);
    618 
    619   SetTexParameters();
    620 
    621   nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
    622   while (nCount-- > 0)
    623   {
    624     if (nWidth > 16 && nHeight > 16)
    625     {
    626       R_MipMap(pPixels, nWidth, nHeight);
    627     }
    628     else
    629     {
    630       break;
    631     }
    632   }
    633 
    634   if (g_PrefsDlg.m_bSGIOpenGL)
    635   {
    636 	  if (nomips)
    637     {
    638 		  qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
    639     }
    640 	  else
    641 		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
    642   }
    643   else
    644   {
    645 	  if (nomips)
    646 		  qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
    647 	  else
    648 		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
    649   }
    650 
    651 	qglBindTexture( GL_TEXTURE_2D, 0 );
    652 
    653   return q;
    654 }
    655 
    656 
    657 qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char *pPath)
    658 {
    659   CString strName;
    660   CString strPath;
    661   ExtractPath_and_Filename(pPath, strPath, strName);
    662   AddSlash(strPath);
    663   strPath += "textureinfo.ini";
    664   strName.MakeLower();
    665   StripExtension (strName.GetBuffer(0));
    666   strName.ReleaseBuffer();
    667   
    668   int nFlags = GetPrivateProfileInt(strName, "Flags", 0, strPath);
    669   int nValue = GetPrivateProfileInt(strName, "Value", 0, strPath);
    670   int nContents = GetPrivateProfileInt(strName, "Contents", 0, strPath);
    671   return Texture_LoadTGATexture(pPixels, nWidth, nHeight, pPath, nFlags, nValue, nContents);
    672 }
    673 
    674 
    675 void Texture_LoadFromPlugIn(LPVOID vp)
    676 {
    677   g_pluginTexture = notexture;
    678   _QERTextureLoad *pLoad = reinterpret_cast<_QERTextureLoad*>(vp);
    679   if (pLoad != NULL)
    680   {
    681 	  qtexture_t	*q;
    682     q = Texture_LoadTGATexture(pLoad->m_pRGBA, pLoad->m_nWidth, pLoad->m_nHeight, NULL, pLoad->m_nFlags, pLoad->m_nContents, pLoad->m_nValue);
    683     if (q != NULL)
    684     {
    685 		// to save duplicate code (since one always ends up getting forgotten and out of sync) this is now done later by caller
    686 //		  strcpy (q->name, pLoad->m_pName);
    687 //		  StripExtension (q->name);
    688 //		  if (!g_dontuse)
    689 //			q->inuse = true;
    690 //	    q->next = g_qeglobals.d_qtextures;
    691 //	    g_qeglobals.d_qtextures = q;
    692       g_pluginTexture = q;
    693     }
    694   }
    695 }
    696 
    697 
    698 /*
    699 ===============
    700 Texture_CreateSolid
    701 
    702 Create a single pixel texture of the apropriate color
    703 ===============
    704 */
    705 qtexture_t *Texture_CreateSolid (const char *name)
    706 {
    707 	byte	data[4];
    708 	qtexture_t	*q;
    709 
    710   q = (qtexture_t*)qmalloc(sizeof(*q));
    711 
    712   if (g_qeglobals.bSurfacePropertiesPlugin)
    713   {
    714 	  // Timo
    715 	  // Surface properties plugins can store their own data in an IPluginQTexture
    716 	  q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
    717 	  GETPLUGINTEXDEF(q)->SetDefaultTexdef();
    718   }
    719 	
    720 	sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
    721 
    722 	data[0] = q->color[0]*255;
    723 	data[1] = q->color[1]*255;
    724 	data[2] = q->color[2]*255;
    725 	data[3] = 255;
    726 
    727 	q->width = q->height = 1;
    728 	//q->width = q->height = 2;
    729   q->texture_number = texture_extension_number++;
    730 	qglBindTexture( GL_TEXTURE_2D, q->texture_number );
    731 	SetTexParameters ();
    732 
    733   if (g_PrefsDlg.m_bSGIOpenGL)
    734   {
    735 		qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    736   }
    737   else
    738   {
    739 	  if (nomips)
    740 		  qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    741 	  else
    742 		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
    743   }
    744 	qglBindTexture( GL_TEXTURE_2D, 0 );
    745 
    746 	return q;
    747 }
    748 
    749 
    750 /*
    751 =================
    752 Texture_MakeDefault
    753 =================
    754 */
    755 qtexture_t* Texture_MakeDefault (void)
    756 {
    757   qtexture_t	*q;
    758   byte		data[4][4];
    759 
    760   if (g_PrefsDlg.m_bSGIOpenGL)
    761   {
    762     if (s_hdcTexture && s_hglrcTexture)
    763     { 
    764        //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
    765        if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
    766 		     Error ("wglMakeCurrent in LoadTexture failed");
    767     }
    768     else
    769       return NULL;
    770   }
    771 
    772   q = (qtexture_t*)qmalloc(sizeof(*q));
    773   
    774   strcpy (q->name, "notexture");
    775   q->width = q->height = 64;
    776   
    777   memset (data, 0, sizeof(data));
    778   data[0][2] = data[3][2] = 255;
    779   
    780   q->color[0] = 0;
    781   q->color[1] = 0;
    782   q->color[2] = 0.5;
    783 
    784   q->texture_number = texture_extension_number++;
    785   qglBindTexture( GL_TEXTURE_2D, q->texture_number );
    786   SetTexParameters ();
    787 
    788 	if (nomips)
    789 		qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    790 	else
    791 		VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
    792 
    793   qglBindTexture( GL_TEXTURE_2D, 0 );
    794   return q;
    795 }
    796 
    797 
    798 /*
    799 =================
    800 Texture_MakeNotexture
    801 =================
    802 */
    803 void Texture_MakeNotexture (void)
    804 {
    805   notexture = Texture_MakeDefault();
    806   // Timo
    807   // Surface properties plugins can store their own data in an IPluginQTexture
    808   if (g_qeglobals.bSurfacePropertiesPlugin)
    809   {
    810 	  notexture->pData = g_SurfaceTable.m_pfnQTextureAlloc( notexture );
    811 	  GETPLUGINTEXDEF(notexture)->SetDefaultTexdef();
    812   }
    813 }
    814 
    815 
    816 void DemandLoadShaderTexture(qtexture_t *q, CShaderInfo *pShader)
    817 {
    818   char cWork[1024];
    819   char cWork2[1024];
    820   strcpy(cWork, (pShader->m_strTextureName.GetLength() > 0) ? pShader->m_strTextureName  : pShader->m_strName);
    821   StripExtension(cWork);
    822   // TTimo: if the shader has a m_fTransValue != 1.0f, ignore the alpha channel when loading the texture
    823   // in some cases (common/weapclip) the 32bit .tga has an empty alpha channel,
    824   // causing a display bug in the camera view (brush does not seemed drawn since alpha==0 for the texture)
    825   // NOTE: the workaround is not perfect, the same texture may have been loaded earlier with it's alpha channel
    826   q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, false);
    827 
    828   if (q == NULL || q == notexture) {
    829     sprintf(cWork2, "%s/%s",ValueForKey(g_qeglobals.d_project_entity, "basepath"), cWork);
    830     q = Texture_ForNamePath( cWork, cWork2);
    831 
    832     if (q == NULL || q == notexture) {
    833       q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, true);
    834     }
    835   }
    836 
    837   if (q != NULL && q != notexture)
    838   {
    839     pShader->m_pQTexture = q;
    840     strcpy(q->shadername, pShader->m_strShaderName);
    841     q->bFromShader = true;
    842     q->fTrans = pShader->m_fTransValue;
    843     q->nShaderFlags = pShader->m_nFlags;
    844     strcpy(q->name, pShader->m_strName );
    845   }
    846   else
    847   {
    848     Sys_Printf("Could not load shader editor image %s\n", cWork);
    849   }
    850 }
    851 
    852 
    853 void LoadShader(char* pFilename, qtexture_t *q)
    854 {
    855   char* pBuff = NULL;
    856   CString strTexture;
    857   int nSize = LoadFile(pFilename, reinterpret_cast<void**>(&pBuff));
    858   if (nSize == -1)
    859   {
    860     nSize = PakLoadAnyFile(pFilename, reinterpret_cast<void**>(&pBuff));
    861   }
    862   if (nSize > 0)
    863   {
    864     StartTokenParsing(pBuff);
    865     while (GetToken(true))
    866     {
    867       // first token should be the path + name.. (from base)
    868       CShaderInfo *pShader = new CShaderInfo();
    869       pShader->setName(token);
    870       pShader->m_strShaderName = pFilename;
    871       strTexture = token;
    872       bool bGood = true;
    873       float fTrans = 1.0;
    874       GetToken(true);
    875       if (strcmp(token, "{"))
    876       {
    877         bGood = false;
    878         break;
    879       }
    880       else
    881       {
    882         // we need to read until we hit a balanced }
    883         int nMatch = 1;
    884         while (nMatch > 0 && GetToken(true))
    885         {
    886           if (strcmp(token, "{") == 0)
    887           {
    888             nMatch++;
    889           }
    890           else if (strcmp(token, "}") == 0)
    891           {
    892             nMatch--;
    893           }
    894           else if (strcmpi(token, "qer_nocarve") == 0)
    895           {
    896             pShader->m_nFlags |= QER_NOCARVE;
    897           }
    898           else if (strcmpi(token, "qer_trans") == 0)
    899           {
    900             if (GetToken(true))
    901             {
    902               fTrans = atof(token);
    903             }
    904             pShader->m_nFlags |= QER_TRANS;
    905           }
    906           else if (strcmpi(token, "qer_editorimage") == 0)
    907           {
    908             if (GetToken(true))
    909             {
    910               char* pTex = copystring(token);
    911           		QE_ConvertDOSToUnixName( pTex, pTex );
    912               CString str = pTex;
    913               free (pTex);
    914               FindReplace(str, "textures/", "");
    915               FindReplace(str, ".tga", "");
    916               int nPos = str.Find('/');
    917               if (nPos == -1)
    918               {
    919                 nPos = str.Find('\\');
    920               }
    921               if (nPos >= 0)
    922               {
    923                 pShader->m_strTextureName = str;
    924 		 					  pShader->m_strTextureName.MakeLower();	//avoid problems with case
    925 /*
    926                 else
    927                 {
    928                   CString strPath = str.Left(nPos+1);
    929                   DeferredShaderLoad *deferred = new DeferredShaderLoad(str, pShader->m_strName, strPath); 
    930                   g_lstDeferred.Add(deferred);
    931                 }
    932 */
    933               }
    934             }
    935           }
    936           else if (strcmpi(token, "surfaceparm") == 0)
    937           {
    938             //--while (GetToken(false))
    939             //--{
    940             //--
    941             //--}
    942             if (GetToken(true))
    943             {
    944               // next token should be a surface parm
    945               //--if (strcmpi(token, "trans") == 0)
    946               //--{
    947               //--  fTrans = 0.33;
    948               //--}
    949               if (strcmpi(token, "fog") == 0)
    950               {
    951                 if (fTrans == 1.0) // has not been explicitly set by qer_trans
    952                 {
    953                   fTrans = 0.35;
    954                 }
    955               }
    956             }
    957           }
    958         }
    959         if (nMatch != 0)
    960         {
    961           bGood = false;
    962           break;
    963         }
    964       }
    965       //--if (bGood && q)
    966       if (bGood)
    967       {
    968         pShader->m_fTransValue = fTrans;
    969         g_lstShaders.Add(pShader);
    970 
    971         int n = g_PrefsDlg.m_nShader;
    972         if (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_ALL || (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_COMMON && strstr(pShader->m_strName, "common" )))
    973         {
    974 // new 
    975           if (pShader->m_strTextureName.GetLength() > 0)
    976           {
    977             if (!ShaderQTextureExists(pShader->m_strName))
    978             {
    979               DemandLoadShaderTexture(q, pShader);
    980             }
    981           }
    982         }
    983 // end new 
    984         //--q->bFromShader = true;
    985         //--q->fTrans = fTrans;
    986 
    987         //--// good texture here
    988         //--//Sys_Printf("Test load texture %s\n", strTexture);
    989         //--// FIXME.. this is a load of crap
    990         //--strcpy(dirstring, strTexture);
    991         //--QE_ConvertDOSToUnixName(dirstring, dirstring);
    992         //--strTexture = dirstring;
    993         //--FindReplace(strTexture, "textures/", "");
    994 		    //--qtexture_t *q = Texture_ForName (strTexture.GetBuffer(0));
    995         //--if (q != NULL)
    996         //--{
    997         //--  q->bFromShader = true;
    998         //--  q->fTrans = fTrans;
    999         //--}
   1000       }
   1001       else
   1002       {
   1003         Sys_Printf("Error parsing shader at texture %s\n", strTexture);
   1004       }
   1005 
   1006     }
   1007     free (pBuff);
   1008   }
   1009   else
   1010   {
   1011     Sys_Printf("Unabled to read shader %s\n", pFilename);
   1012   }
   1013 }
   1014 
   1015 
   1016 extern bool DoesFileExist(const char* pBuff, long& lSize);
   1017 CShaderInfo* SetNameShaderInfo(qtexture_t* q, const char* pPath, const char* pName)
   1018 {
   1019   CShaderInfo *pInfo = hasShader(pName);
   1020   if (pInfo)
   1021   {
   1022     strcpy(q->shadername, pInfo->m_strShaderName);
   1023     q->bFromShader = true;
   1024     q->fTrans = pInfo->m_fTransValue;
   1025     q->nShaderFlags = pInfo->m_nFlags;
   1026   }
   1027   else
   1028   {
   1029     q->shadername[0] = 0;
   1030   }
   1031   strncpy (q->name, pName, sizeof(q->name) - 1);
   1032 	StripExtension (q->name);
   1033   return pInfo;
   1034 }
   1035 
   1036 void ReplaceQTexture(qtexture_t *pOld, qtexture_t *pNew, brush_t *pList)
   1037 { 
   1038 	for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
   1039 	{
   1040 		if (pBrush->patchBrush)
   1041 		{
   1042 			Patch_ReplaceQTexture(pBrush, pOld, pNew);
   1043 		}
   1044 		if (pBrush->terrainBrush)
   1045 		{
   1046 			Terrain_ReplaceQTexture(pBrush->pTerrain, pOld, pNew);
   1047 		}
   1048 
   1049 		for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
   1050 		{
   1051 			if (pFace->d_texture == pOld)
   1052 			{
   1053 			pFace->d_texture = pNew;
   1054 			}
   1055 		}
   1056 		
   1057 		//Brush_Build(pBrush);
   1058 	}
   1059 }
   1060 
   1061 
   1062 void Texture_Remove(qtexture_t *q)
   1063 {
   1064   qtexture_t* pTex = g_qeglobals.d_qtextures->next;
   1065   if (q == g_qeglobals.d_qtextures)   // it is the head
   1066   {
   1067     g_qeglobals.d_qtextures->next = q->next->next;
   1068     g_qeglobals.d_qtextures = q->next;
   1069   }
   1070   else
   1071   {
   1072     qtexture_t* pLast = g_qeglobals.d_qtextures;
   1073     while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
   1074     {
   1075       if (pTex == q)
   1076       {
   1077         pLast->next = q->next;
   1078         break;
   1079       }
   1080       pLast = pTex;
   1081       pTex = pTex->next;
   1082     }
   1083   }
   1084   qglDeleteTextures(1, reinterpret_cast<const unsigned int*>(&q->texture_number));
   1085 
   1086   if (g_qeglobals.bSurfacePropertiesPlugin)
   1087   {
   1088 	  // Timo
   1089 	  // Surface properties plugin
   1090 #ifdef _DEBUG
   1091 	  if ( !q->pData )
   1092 		  Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
   1093 #endif
   1094 	  if ( q->pData )
   1095 		  GETPLUGINTEXDEF(q)->DecRef();
   1096   }
   1097 
   1098   free(q);
   1099 
   1100 }
   1101 
   1102 /*
   1103 =================
   1104 Texture_MakeNoShadertexture
   1105 
   1106 Make a default black/red check pattern texture
   1107 =================
   1108 */
   1109 qtexture_t * Texture_MakeNoshadertexture( const char *name )
   1110 {
   1111 	qtexture_t	*q;
   1112 	byte		data[4][4];
   1113 
   1114 	notexture = q = (qtexture_t*)qmalloc(sizeof(*q));
   1115 	q->width = q->height = 64;
   1116 	q->fTrans = 1;
   1117 
   1118 	q = (qtexture_t*)qmalloc(sizeof(*q));
   1119   strcpy (q->name, name);
   1120 
   1121 	q->width = q->height = 64;
   1122 	q->fTrans = 1;
   1123 
   1124 	memset (data, 0, sizeof(data));
   1125 	data[0][0] = data[3][0] = 255;
   1126 
   1127 	q->color[0] = 0;
   1128 	q->color[1] = 0;
   1129 	q->color[2] = 0.5;
   1130 
   1131 	q->texture_number = texture_extension_number++;
   1132 	qglBindTexture( GL_TEXTURE_2D, q->texture_number );
   1133 	SetTexParameters ();
   1134 
   1135 	if (nomips)
   1136 		qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
   1137 	else
   1138 		VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
   1139 
   1140 	qglBindTexture( GL_TEXTURE_2D, 0 );
   1141 
   1142 	return q;
   1143 }
   1144 
   1145 
   1146 
   1147 /*
   1148 ===============
   1149 Texture_ForName
   1150 ===============
   1151 */
   1152 //bReload is set to true when called from DemandLoadShaderTexture because it should never re-use
   1153 //an already loaded texture
   1154 qtexture_t *Texture_ForName (const char *name, bool bReplace, bool bShader, bool bNoAlpha, bool bReload, bool makeShader)
   1155 {
   1156   byte    *lump;
   1157 	qtexture_t	*q = NULL;
   1158 	char	filename[1024];
   1159 	
   1160   if (name == NULL || strlen(name) == 0)
   1161 		return notexture;
   1162 	
   1163 	qtexture_t *pRemove = NULL;
   1164 	
   1165 	if (!bReload)
   1166 	{
   1167 		for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
   1168 		{
   1169 			if (!strcmp(name,  q->name))
   1170 			{
   1171 				if (bReplace)
   1172 				{
   1173 					pRemove = q;
   1174 					//Texture_Remove(q);
   1175 					break;
   1176 				}
   1177 				else
   1178 				{
   1179 #ifdef _DEBUG
   1180 					// if the texture is already in memory, then the bNoAlpha flag doesn't have any influence
   1181 					if (bNoAlpha)
   1182 						Sys_Printf("WARNING: bNoAlpha flag on an already loaded texture\n");
   1183 #endif
   1184 					if (!g_dontuse)
   1185 					{
   1186 						q->inuse = true;
   1187 					}
   1188 					return q;
   1189 				}
   1190 			}
   1191 		}
   1192 	}
   1193 
   1194   // did not find it in the standard list
   1195   // skip entity names (
   1196   if (!bShader && name[0] != '(')
   1197   {
   1198     CShaderInfo* pShader = hasShader(name);
   1199     if (pShader)
   1200     {
   1201       if (pShader->m_pQTexture == NULL)
   1202       {
   1203         DemandLoadShaderTexture(q, pShader);
   1204       }
   1205       q = pShader->m_pQTexture;
   1206       //Sys_Printf ("used Shader %s.\n", pShader->m_strName);
   1207     }
   1208     if ( q != NULL)
   1209     {
   1210       return q;
   1211     }
   1212   }
   1213 
   1214 	
   1215 	if (name[0] == '(')
   1216 	{
   1217 		q = Texture_CreateSolid (name);
   1218 		strncpy (q->name, name, sizeof(q->name)-1);
   1219 	}
   1220 	else
   1221 	{
   1222 		// FIXME: this is a mess.. need to move consolidate stuff
   1223 		// down to a single routine.. 
   1224 		// 
   1225 		// if plugins have a texture loader
   1226 		// {
   1227 		//   
   1228 		// }
   1229 		// else
   1230 		// 
   1231 		if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
   1232 		{
   1233 			// rad: 12/19/98
   1234 			// if the plugin is not a wad style then we need to treat it normally
   1235 			// otherwise return without trying to explicitly load the texture
   1236 			// as it should have been loaded by the wad style plugin at init time
   1237 			CString strTex = GetTextureExtension(0);
   1238 			sprintf (filename, "%s\\%s.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name, strTex);
   1239 			if (!g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
   1240       {   
   1241 				g_pParentWnd->GetPlugInMgr().LoadTexture(filename);        
   1242 				if (g_pluginTexture)
   1243 					q = g_pluginTexture;
   1244 			}
   1245 			else
   1246 			{
   1247 				return notexture;
   1248 				// wadstyle.. if we get here then we do not have it
   1249 			}
   1250 		}
   1251 		else
   1252       // we need to try several formats here, or would it be better if we are given a complete name
   1253 			if (g_PrefsDlg.m_bHiColorTextures == TRUE)
   1254 			{
   1255 		    char cWork[1024];
   1256 		  	sprintf (filename, "%s/%s.tga", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
   1257     		QE_ConvertDOSToUnixName( cWork, filename );
   1258 		    strcpy(filename, cWork);
   1259 				Sys_Printf ("Loading %s...", name);
   1260 				unsigned char* pPixels = NULL;
   1261 				int nWidth;
   1262 				int nHeight;
   1263 				LoadImage(filename, &pPixels, &nWidth, &nHeight);
   1264         if (pPixels == NULL)
   1265         {
   1266           // try jpg
   1267           // blatant assumption of .tga should be fine since we sprintf'd it above
   1268           int nLen = strlen(filename);
   1269           filename[nLen-3] = 'j';
   1270           filename[nLen-2] = 'p';
   1271           filename[nLen-1] = 'g';
   1272 				  LoadImage(filename, &pPixels, &nWidth, &nHeight);
   1273         }
   1274 				if (pPixels)
   1275 				{
   1276 					// if we were asked to ignore alpha channel, do it now (.TGA is the only supported file type with alpha channel)
   1277 					//if (bNoAlpha)
   1278 					if (TRUE)
   1279 					{
   1280 						unsigned char* iPix = pPixels;
   1281 						int nCount = nWidth * nHeight;
   1282 						for(iPix=pPixels+3; iPix-pPixels < nCount*4; iPix+=4)
   1283 							*iPix = 255;
   1284 					}
   1285           // we'll be binding the GL texture now
   1286           // need to check we are using a right GL context
   1287           // with GL plugins that have their own window, the GL context may be the plugin's, in which case loading textures will bug
   1288 	        HDC currentHDC = qwglGetCurrentDC();
   1289 	        HGLRC currentHGLRC = qwglGetCurrentContext();
   1290           //++timo FIXME: this may duplicate with qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
   1291           //++timo FIXME: we need a list of lawfull GL contexts or something?
   1292           // I'd rather always use the same GL context for binding...
   1293           if (currentHDC != g_qeglobals.d_hdcBase || currentHGLRC != g_qeglobals.d_hglrcBase)
   1294 	          qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
   1295 					q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
   1296           //++timo I don't set back the GL context .. I don't know how safe it is
   1297           //qwglMakeCurrent( currentHDC, currentHGLRC );
   1298     	//++timo storing the filename .. will be removed by shader code cleanup
   1299 		// this is dirty, and we sure miss some places were we should fill the filename info
   1300 		strcpy( q->filename, name );
   1301 					SetNameShaderInfo(q, filename, name);
   1302 					Sys_Printf ("done.\n", name);
   1303 					free(pPixels);
   1304 				}
   1305 			}
   1306 			else
   1307 			{
   1308 				// load the file
   1309 				sprintf (filename, "%s/%s.wal", ValueForKey (g_qeglobals.d_project_entity, "texturepath"),	name);
   1310 				Sys_Printf ("Loading %s...", name);
   1311 				if (LoadFile (filename, (void**)&lump) == -1)
   1312 				{
   1313 					sprintf (filename, "%s.wal", name);
   1314 					Sys_Printf("failed.. trying pak0.pak..");
   1315 					if(!PakLoadFile(filename, (void**)&lump))
   1316 					{
   1317 						Sys_Printf (" load failed!\n");
   1318 						return notexture;
   1319 					}
   1320 				}
   1321 				Sys_Printf("successful.\n");
   1322 				q = Texture_LoadTexture ((miptex_t *)lump);
   1323 				free (lump);
   1324 				strncpy (q->name, name, sizeof(q->name)-1);
   1325 				StripExtension (q->name);
   1326 			}
   1327 			
   1328  			if (g_PrefsDlg.m_bSGIOpenGL)
   1329 			{
   1330 				if(!q)
   1331 					return notexture;
   1332 			}
   1333 			
   1334 	}// name[0] != '('
   1335 	
   1336 	if(!q)	// safety
   1337   {
   1338     if (bShader && !makeShader) {
   1339       return q;
   1340     }
   1341   
   1342     if (bShader)
   1343     {
   1344       q = Texture_MakeNoshadertexture( name );
   1345 	    Sys_Printf("failed, using default shader\n");
   1346     }
   1347     else
   1348     {
   1349       q = Texture_MakeDefault();
   1350 	    Sys_Printf("failed, using default\n");
   1351     }
   1352   }
   1353 	
   1354   strncpy (q->name, name, sizeof(q->name)-1);
   1355   if (name[0] != '(')
   1356   {
   1357     StripExtension (q->name);
   1358   }
   1359 
   1360 	if (!g_dontuse)
   1361 		q->inuse = true;
   1362 	q->next = g_qeglobals.d_qtextures;
   1363 	g_qeglobals.d_qtextures = q;
   1364 	
   1365 	if (pRemove != NULL)
   1366 	{
   1367 		ReplaceQTexture(pRemove, q, &active_brushes);
   1368 		ReplaceQTexture(pRemove, q, &filtered_brushes);
   1369 		Texture_Remove(pRemove);
   1370 	}
   1371 	
   1372 	return q;
   1373 }
   1374 
   1375 /*
   1376 ===============
   1377 Texture_ForNamePath
   1378 ===============
   1379 */
   1380 qtexture_t *Texture_ForNamePath(char* name, char* pFullPath)
   1381 {
   1382   byte    *lump;
   1383 	qtexture_t	*q;
   1384 	char	filename[1024];
   1385 
   1386   if (strlen(name) == 0)
   1387     return notexture;
   1388 
   1389 	for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
   1390   {
   1391 	  if (!strcmp(name,  q->name))
   1392 		{
   1393 			if (!g_dontuse)
   1394 				q->inuse = true;
   1395 		    return q;
   1396 		}
   1397   }
   1398 
   1399 	if (name[0] == '(')
   1400 	{
   1401 		q = Texture_CreateSolid (name);
   1402 		strncpy (q->name, name, sizeof(q->name)-1);
   1403 	}
   1404 	else
   1405 	{
   1406 		// load the file
   1407     if (g_PrefsDlg.m_bHiColorTextures == TRUE)
   1408     {
   1409       char cWork[1024];
   1410       if (strstr(pFullPath, ".tga") == NULL) {
   1411         sprintf(filename, "%s%s", pFullPath, ".tga");
   1412       } else {
   1413         strcpy(filename, pFullPath);
   1414       }
   1415   		QE_ConvertDOSToUnixName( cWork, filename );
   1416 	    strcpy(filename, cWork);
   1417 		  Sys_Printf ("Loading %s...", name);
   1418       unsigned char* pPixels = NULL;
   1419       int nWidth;
   1420       int nHeight;
   1421       LoadImage(filename, &pPixels, &nWidth, &nHeight);
   1422       if (!pPixels)
   1423       {
   1424         // try jpg
   1425         // blatant assumption of .tga should be fine since we sprintf'd it above
   1426         int nLen = strlen(filename);
   1427         filename[nLen-3] = 'j';
   1428         filename[nLen-2] = 'p';
   1429         filename[nLen-1] = 'g';
   1430 				LoadImage(filename, &pPixels, &nWidth, &nHeight);
   1431       }
   1432       if (pPixels)
   1433       {
   1434         q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
   1435     	//++timo storing the filename .. will be removed by shader code cleanup
   1436 		// this is dirty, and we sure miss some places were we should fill the filename info
   1437 		// NOTE: we store relative path, need to extract it
   1438 		strcpy( q->filename, name );
   1439 
   1440       }
   1441       else
   1442       {
   1443         return notexture;
   1444       }
   1445       free(pPixels);
   1446     }
   1447     else
   1448     {
   1449       sprintf(filename, "%s%s", pFullPath, ".wal");
   1450 		  Sys_Printf ("Loading %s...", name);
   1451 		  if (LoadFile (filename, (void**)&lump) == -1)
   1452       {
   1453 			  Sys_Printf (" load failed!\n");
   1454 			  return notexture;
   1455       }
   1456       Sys_Printf("successful.\n");
   1457 		  q = Texture_LoadTexture ((miptex_t *)lump);
   1458 		  free (lump);
   1459     }
   1460     if (g_PrefsDlg.m_bSGIOpenGL)
   1461     {
   1462 		  if(!q)
   1463 			  return notexture;
   1464     }
   1465 		strncpy (q->name, name, sizeof(q->name)-1);
   1466 		StripExtension (q->name);
   1467 	}
   1468 
   1469 	if (!g_dontuse)
   1470 		q->inuse = true;
   1471 	q->next = g_qeglobals.d_qtextures;
   1472 	g_qeglobals.d_qtextures = q;
   1473 
   1474   return q;
   1475 }
   1476 
   1477 
   1478 
   1479 /*
   1480 ==================
   1481 FillTextureMenu
   1482 
   1483 ==================
   1484 */
   1485 void FillTextureMenu (CStringArray* pArray)
   1486 {
   1487 	HMENU	hmenu;
   1488 	int		i;
   1489 	struct _finddata_t fileinfo;
   1490 	int		handle;
   1491 	char	dirstring[1024];
   1492 	char	*path;
   1493 	DIRLIST	*list = NULL, *temp;
   1494 
   1495   if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
   1496   {
   1497     if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
   1498       return;
   1499   }
   1500 
   1501 	hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE);
   1502 
   1503 	// delete everything
   1504 	for (i=0 ; i<texture_nummenus ; i++)
   1505 		DeleteMenu (hmenu, CMD_TEXTUREWAD+i, MF_BYCOMMAND);
   1506 
   1507   texture_nummenus = 0;
   1508 
   1509 	// add everything
   1510   if (g_qeglobals.d_project_entity)
   1511   {
   1512     //--if (g_PrefsDlg.m_bUseShaders)
   1513     //--{
   1514 	  //--  path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
   1515 	  //--  sprintf (dirstring, "%s/scripts/*.shader", path);
   1516     //--
   1517     //--}
   1518     //--else
   1519     //--{
   1520 	    path = ValueForKey (g_qeglobals.d_project_entity, "texturepath");
   1521 	    sprintf (dirstring, "%s/*.*", path);
   1522     //--}
   1523 
   1524 	  handle = _findfirst (dirstring, &fileinfo);
   1525 	  if (handle != -1)
   1526     {
   1527 	    do
   1528 	    {
   1529         //--if (g_PrefsDlg.m_bUseShaders)
   1530         //--{
   1531 		    //--  if ((fileinfo.attrib & _A_SUBDIR))
   1532         //--    continue;
   1533         //--}
   1534         //--else
   1535         //--{
   1536 		      if (!(fileinfo.attrib & _A_SUBDIR))
   1537 		        continue;
   1538 		      if (fileinfo.name[0] == '.')
   1539 		        continue;
   1540         //--}
   1541         // add this directory to the menu
   1542 	      AddToDirListAlphabetized(&list, fileinfo.name, FROMDISK);
   1543 	    } while (_findnext( handle, &fileinfo ) != -1);
   1544 
   1545 	    _findclose (handle);
   1546     }
   1547 
   1548     //--if (!g_PrefsDlg.m_bUseShaders)
   1549     //--{
   1550       GetPackTextureDirs(&list);
   1551     //--}
   1552 
   1553 	  for(temp = list; temp; temp = temp->next)
   1554 	  {
   1555 		  AppendMenu (hmenu, MF_ENABLED|MF_STRING, CMD_TEXTUREWAD+texture_nummenus, (LPCTSTR)temp->dirname);
   1556 		  strcpy (texture_menunames[texture_nummenus], temp->dirname);
   1557       //--if (!g_PrefsDlg.m_bUseShaders)
   1558       //--{
   1559 		    strcat (texture_menunames[texture_nummenus], "/");
   1560       //--}
   1561       if (pArray)
   1562         pArray->Add(temp->dirname);
   1563 		  if (++texture_nummenus == MAX_TEXTUREDIRS)
   1564 		   break;
   1565 	  }
   1566 
   1567 	  ClearDirList(&list);
   1568   }
   1569 
   1570 
   1571 }
   1572 
   1573 
   1574 /*
   1575 ==================
   1576 Texture_ClearInuse
   1577 
   1578 A new map is being loaded, so clear inuse markers
   1579 ==================
   1580 */
   1581 void Texture_ClearInuse (void)
   1582 {
   1583 	qtexture_t	*q;
   1584 
   1585 	for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
   1586     {
   1587 		q->inuse = false;
   1588 	}
   1589 }
   1590 
   1591 
   1592 
   1593 
   1594 void LoadShadersFromDir(const char *pPath)
   1595 {
   1596   int nSize = g_lstShaders.GetSize();
   1597   for (int i = 0; i < nSize; i++)
   1598   {
   1599     CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
   1600     if (pInfo != NULL)
   1601     {
   1602       if (strstr(pInfo->m_strName, pPath) && pInfo->m_pQTexture == NULL && strstr(pInfo->m_strName, "models/player") == NULL)
   1603       {
   1604         qtexture_t *q = NULL;
   1605         DemandLoadShaderTexture(q, pInfo);
   1606       }
   1607     }
   1608   }
   1609 }
   1610 
   1611 
   1612 /*
   1613 ==============
   1614 Texture_ShowDirectory
   1615 ==============
   1616 */
   1617 void	Texture_ShowDirectory (int menunum, bool bLinked)
   1618 {
   1619 	struct _finddata_t fileinfo;
   1620 	int		handle;
   1621 	char	name[1024];
   1622 	char	dirstring[1024];
   1623 	char	linkstring[1024];
   1624 	FILELIST			*list = NULL, *temp;
   1625   CString strTemp;
   1626 
   1627   //Texture_Flush(false);
   1628 	//Select_Deselect();
   1629 	Texture_ClearInuse();
   1630 	texture_showinuse = false;
   1631 	strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
   1632 
   1633   if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
   1634   {
   1635     if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
   1636       return;
   1637   }
   1638 
   1639   // new
   1640 /*
   1641   if (!g_PrefsDlg.m_bShaderTest)
   1642   {
   1643 	g_dontuse = true;	// needed because this next piece of code calls Texture_ForName() internally! -slc
   1644     LoadDeferred(texture_directory);
   1645     g_dontuse = false;
   1646   }
   1647 */
   1648   if (g_PrefsDlg.m_bHiColorTextures == FALSE)
   1649   {
   1650   }
   1651 
   1652 	g_qeglobals.d_texturewin.originy = 0;
   1653 
   1654   //--if (g_PrefsDlg.m_bUseShaders)
   1655   //--{
   1656   //--  sprintf (dirstring, "%s/scripts/%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_directory);
   1657 	//--  Sys_Printf("loading textures from shader %s\n", dirstring);
   1658   //--  LoadShader(dirstring);
   1659   //--}
   1660   //--else
   1661   //--{
   1662 	  Sys_Status("Loading textures\n", 0);
   1663 
   1664 	  // load all image files
   1665                                           
   1666     sprintf (linkstring, "%s/textures/%stextureinfo.ini", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD]);
   1667 
   1668     for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
   1669     {
   1670       sprintf (dirstring, "%s/textures/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
   1671       Sys_Printf ("Scanning %s\n", dirstring);
   1672 	    handle = _findfirst (dirstring, &fileinfo);
   1673 
   1674       if (handle == -1)
   1675       {
   1676         sprintf(dirstring, "%s/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
   1677         handle = _findfirst (dirstring, &fileinfo);
   1678       }
   1679       if (handle != -1)
   1680 	    {
   1681 		    do
   1682   		  {
   1683 	  		  sprintf (name, "%s%s", texture_directory, fileinfo.name);
   1684 		  	  AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
   1685   		  } while (_findnext( handle, &fileinfo ) != -1);
   1686 	  	  _findclose (handle);
   1687   	  }
   1688 	    else
   1689 	    {
   1690 	      sprintf (dirstring, "%s*.%s", texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
   1691   		  GetPackFileList(&list, dirstring);
   1692 	    }
   1693     }
   1694 
   1695 	  g_dontuse = true;
   1696 	  for(temp = list; temp; temp = temp->next)
   1697 	  {
   1698 		  if(temp->offset == -1)
   1699 			  sprintf(name, "%s", temp->filename);
   1700 		  else
   1701 			  sprintf(name, "%s%s", texture_menunames[menunum-CMD_TEXTUREWAD], temp->filename);
   1702 		  StripExtension (name);
   1703       strTemp = name;
   1704       strTemp.MakeLower();
   1705       if ( strTemp.Find(".specular") >= 0 ||
   1706            strTemp.Find(".glow") >= 0 ||
   1707            strTemp.Find(".bump") >= 0 ||
   1708            strTemp.Find(".diffuse") >= 0 ||
   1709            strTemp.Find(".blend") >= 0 ||
   1710            strTemp.Find(".alpha") >= 0
   1711          )
   1712         continue;
   1713       else
   1714       {
   1715 		    Texture_ForName (name, true);
   1716       }
   1717 	  }
   1718 
   1719 	  ClearFileList(&list);
   1720   //--}
   1721 
   1722 
   1723 	g_dontuse = false;
   1724 
   1725   if (!bLinked)
   1726   {
   1727 
   1728     for (int k = 0; k < 10; k++)
   1729     {
   1730       sprintf(name, "Path%d", k);
   1731       if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
   1732       {
   1733         Texture_ShowDirectory(dirstring, true);
   1734       }
   1735     }
   1736 
   1737     LoadShadersFromDir(texture_directory);
   1738 
   1739     SortTextures();
   1740 	  
   1741     sprintf (name, "Textures: %s", texture_directory);
   1742 	  SetWindowText(g_qeglobals.d_hwndEntity, name);
   1743 
   1744 	  // select the first texture in the list
   1745 	  if (!g_qeglobals.d_texturewin.texdef.name[0])
   1746 		  SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
   1747   }
   1748 }
   1749 
   1750 
   1751 // this can be combined with the above, but per usual i am in a hurry
   1752 //
   1753 void	Texture_ShowDirectory (char* pPath, bool bLinked)
   1754 {
   1755 	struct _finddata_t fileinfo;
   1756 	int		handle;
   1757 	char	name[1024];
   1758 	char	dirstring[1024];
   1759 	char	linkstring[1024];
   1760 	FILELIST			*list = NULL, *temp;
   1761 
   1762   //Texture_Flush(false);
   1763 
   1764 	texture_showinuse = false;
   1765 	Texture_ClearInuse();
   1766 	strcpy (texture_directory, pPath);
   1767 
   1768   if (g_PrefsDlg.m_bHiColorTextures == FALSE)
   1769   {
   1770   }
   1771 
   1772 	g_qeglobals.d_texturewin.originy = 0;
   1773 	Sys_Status("loading all textures\n", 0);
   1774 
   1775 	// load all .wal files
   1776   for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
   1777   {
   1778     sprintf(dirstring, "%s*.%s", pPath,GetTextureExtension(nExt));
   1779                                           
   1780 	  Sys_Printf ("Scanning %s\n", dirstring);
   1781 
   1782 	  handle = _findfirst (dirstring, &fileinfo);
   1783 
   1784     if (handle != -1)
   1785 	  {
   1786 		  do
   1787 		  {
   1788 			  sprintf (name, "%s%s", texture_directory, fileinfo.name);
   1789 			  AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
   1790 		  } while (_findnext( handle, &fileinfo ) != -1);
   1791 		  _findclose (handle);
   1792 	  }
   1793 	  else
   1794 	  {
   1795 		  //sprintf (dirstring, "%s*.wal", texture_menunames[menunum-CMD_TEXTUREWAD]);
   1796 		  //if(!GetPackFileList(&list, dirstring))
   1797 			  return;
   1798 	  }
   1799   }
   1800 
   1801 	g_dontuse = true;
   1802 	for(temp = list; temp; temp = temp->next)
   1803 	{
   1804 		if(temp->offset == -1)
   1805 			sprintf(name, "%s", temp->filename);
   1806 		else
   1807 		  sprintf(name, "%s%s", pPath, temp->filename);
   1808 		StripExtension (name);
   1809 
   1810     int nLen = strlen(name)-1;
   1811     ASSERT(nLen > 0);
   1812     while (name[nLen] != '\\')
   1813       nLen--;
   1814     // found first one
   1815     nLen--;
   1816     ASSERT(nLen > 0);
   1817     while (name[nLen] != '\\')
   1818       nLen--;
   1819     ASSERT(nLen >= 0);
   1820     QE_ConvertDOSToUnixName(name, name);
   1821     Texture_ForName(&name[nLen+1]);
   1822 
   1823 	}
   1824 
   1825 	ClearFileList(&list);
   1826 
   1827 	g_dontuse = false;
   1828 
   1829   SortTextures();
   1830 
   1831   if (!bLinked)
   1832   {
   1833 
   1834     for (int k = 0; k < 10; k++)
   1835     {
   1836       sprintf(name, "Path%d", k);
   1837       if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
   1838       {
   1839         Texture_ShowDirectory(dirstring, true);
   1840       }
   1841     }
   1842 
   1843 
   1844 	  sprintf (name, "Textures: %s", texture_directory);
   1845 	  SetWindowText(g_qeglobals.d_hwndEntity, name);
   1846 
   1847 	  // select the first texture in the list
   1848 	  if (!g_qeglobals.d_texturewin.texdef.name[0])
   1849 		  SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
   1850   }
   1851 }
   1852 
   1853 
   1854 
   1855 void Texture_ResetPosition()
   1856 {
   1857   SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
   1858   g_qeglobals.d_texturewin.originy = 0;
   1859 }
   1860 
   1861 
   1862 
   1863 /*
   1864 ==================
   1865 Texture_SetInuse
   1866 
   1867 ==================
   1868 */
   1869 void Texture_SetInuse (void)
   1870 {
   1871 	qtexture_t	*q;
   1872 
   1873 	for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
   1874   {
   1875 		q->inuse = true;
   1876 	}
   1877 }
   1878 
   1879 
   1880 /*
   1881 ==============
   1882 Texture_ShowAll
   1883 ==============
   1884 */
   1885 void	Texture_ShowAll()
   1886 {
   1887   Texture_SetInuse();
   1888 	Sys_Printf("Showing all textures...\n");
   1889 	Sys_UpdateWindows (W_TEXTURE);
   1890 }
   1891 
   1892 /*
   1893 ==============
   1894 Texture_ShowInuse
   1895 ==============
   1896 */
   1897 void	Texture_ShowInuse (void)
   1898 {
   1899 	face_t	*f;
   1900 	brush_t	*b;
   1901 	char	name[1024];
   1902 
   1903 	texture_showinuse = true;
   1904 	g_dontuse = false;
   1905 
   1906 	g_qeglobals.d_texturewin.originy = 0;	
   1907 
   1908 	Texture_ClearInuse();
   1909 	Sys_Status("Selecting active textures\n", 0);
   1910 
   1911 	for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
   1912   {
   1913     if (b->patchBrush)
   1914     {
   1915       Texture_ForName(b->pPatch->d_texture->name);
   1916     }
   1917     else
   1918     {
   1919 		  for (f=b->brush_faces ; f ; f=f->next)
   1920       {
   1921 			  Texture_ForName (f->texdef.name);
   1922       }
   1923     }
   1924   }
   1925 
   1926 	for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
   1927   {
   1928     if (b->patchBrush)
   1929     {
   1930       Texture_ForName(b->pPatch->d_texture->name);
   1931     }
   1932     else
   1933     {
   1934 		  for (f=b->brush_faces ; f ; f=f->next)
   1935       {
   1936 			  Texture_ForName (f->texdef.name);
   1937       }
   1938     }
   1939   }
   1940 
   1941 	SortTextures();
   1942 	//SetInspectorMode(W_TEXTURE);
   1943 	Sys_UpdateWindows (W_TEXTURE);
   1944 
   1945 	sprintf (name, "Textures: in use");
   1946 	SetWindowText(g_qeglobals.d_hwndEntity, name);
   1947 
   1948 	// select the first texture in the list
   1949 	if (!g_qeglobals.d_texturewin.texdef.name[0])
   1950   {
   1951 		SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
   1952   }
   1953 }
   1954 
   1955 /*
   1956 ============================================================================
   1957 
   1958 TEXTURE LAYOUT
   1959 
   1960 ============================================================================
   1961 */
   1962 
   1963 void Texture_StartPos (void)
   1964 {
   1965 	current_texture = g_qeglobals.d_qtextures;
   1966 	current_x = 8;
   1967 	current_y = -8;
   1968 	current_row = 0;
   1969 }
   1970 
   1971 qtexture_t *Texture_NextPos (int *x, int *y)
   1972 {
   1973 	qtexture_t	*q;
   1974 
   1975 	while (1)
   1976 	{
   1977 		q = current_texture;
   1978 		if (!q)
   1979 			return q;
   1980 		current_texture = current_texture->next;
   1981 		if (q->name[0] == '(')	// fake color texture
   1982 			continue;
   1983 
   1984     if (g_bFilterEnabled)
   1985     {
   1986       CString strName = q->name;
   1987       int nPos = strName.Find('\\');
   1988       if (nPos == -1)
   1989         nPos = strName.Find('/');
   1990       if (nPos >= 0)
   1991         strName = strName.Right(strName.GetLength() - nPos - 1);
   1992       if (strnicmp(g_strFilter.GetBuffer(0), strName, g_strFilter.GetLength()) == 0)
   1993         break;
   1994       else
   1995         continue;
   1996     }
   1997 
   1998     if (q->bFromShader && g_PrefsDlg.m_bShowShaders == FALSE)
   1999     {
   2000       continue;
   2001     }
   2002 
   2003 		if (q->inuse)
   2004 			break;			// always show in use
   2005     
   2006     if (!texture_showinuse && !strnicmp (q->name, texture_directory, strlen(texture_directory)))
   2007 			break;
   2008 		continue;
   2009 	}
   2010 
   2011   int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
   2012   int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
   2013 	if (current_x + nWidth > g_qeglobals.d_texturewin.width-8 && current_row)
   2014 	{	// go to the next row unless the texture is the first on the row
   2015 		current_x = 8;
   2016 		current_y -= current_row + FONT_HEIGHT + 4;
   2017 		current_row = 0;
   2018 	}
   2019 
   2020 	*x = current_x;
   2021 	*y = current_y;
   2022 
   2023 	// Is our texture larger than the row? If so, grow the 
   2024 	// row height to match it
   2025 
   2026     if (current_row < nHeight)
   2027 		  current_row = nHeight;
   2028 
   2029 	// never go less than 64, or the names get all crunched up
   2030 	current_x += nWidth < 64 ? 64 : nWidth;
   2031 	current_x += 8;
   2032 
   2033 	return q;
   2034 }
   2035 
   2036 /*
   2037 ============================================================================
   2038 
   2039   MOUSE ACTIONS
   2040 
   2041 ============================================================================
   2042 */
   2043 
   2044 static	int	textures_cursorx, textures_cursory;
   2045 
   2046 
   2047 /*
   2048 ============
   2049 Texture_SetTexture
   2050 
   2051 brushprimit_texdef must be understood as a qtexture_t with width=2 height=2 ( the default one )
   2052 ============
   2053 */
   2054 void Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef *pTexdef, bool bSetSelection )
   2055 {
   2056 	qtexture_t	*q;
   2057 	int			x,y;
   2058 
   2059 	if (texdef->name[0] == '(')
   2060 	{
   2061 		Sys_Status("Can't select an entity texture\n", 0);
   2062 		return;
   2063 	}
   2064 	g_qeglobals.d_texturewin.texdef = *texdef;
   2065 	g_qeglobals.d_texturewin.texdef.flags &= ~SURF_KEEP;
   2066 	g_qeglobals.d_texturewin.texdef.contents &= ~CONTENTS_KEEP;
   2067 	// store the texture coordinates for new brush primitive mode
   2068 	// be sure that all the callers are using the default 2x2 texture
   2069 	if (g_qeglobals.m_bBrushPrimitMode)
   2070 	{
   2071 		g_qeglobals.d_texturewin.brushprimit_texdef = *brushprimit_texdef;
   2072 	}
   2073 	// surface properties plugin
   2074 	if (g_qeglobals.bSurfacePropertiesPlugin)
   2075 	{
   2076 		if (g_qeglobals.d_texturewin.pTexdef)
   2077 		{
   2078 			// decrement reference count
   2079 			static_cast<IPluginTexdef *>(g_qeglobals.d_texturewin.pTexdef)->DecRef();
   2080 			g_qeglobals.d_texturewin.pTexdef = NULL;
   2081 		}
   2082 		if (pTexdef)
   2083 		{
   2084 			g_qeglobals.d_texturewin.pTexdef = pTexdef->Copy();
   2085 		}
   2086 	}
   2087 
   2088 	Sys_UpdateWindows (W_TEXTURE);
   2089 
   2090   g_dlgFind.updateTextures(texdef->name);
   2091 
   2092   if (!g_dlgFind.isOpen() && bSetSelection)
   2093   {
   2094     Select_SetTexture(texdef,brushprimit_texdef,bFitScale);
   2095   }
   2096 
   2097 
   2098 	//plugins: send a message telling that the selected texture may have changed
   2099 	DispatchRadiantMsg( RADIANT_TEXTURE );
   2100 
   2101 	// scroll origin so the texture is completely on screen
   2102 	Texture_StartPos ();
   2103 	while (1)
   2104 	{
   2105 		q = Texture_NextPos (&x, &y);
   2106 		if (!q)
   2107 			break;
   2108 
   2109     int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
   2110     int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
   2111 		if (!strcmpi(texdef->name, q->name))
   2112 		{
   2113 			if (y > g_qeglobals.d_texturewin.originy)
   2114 			{
   2115 				g_qeglobals.d_texturewin.originy = y;
   2116 				Sys_UpdateWindows (W_TEXTURE);
   2117 				return;
   2118 			}
   2119 
   2120 			if (y-nHeight-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
   2121 			{
   2122 				g_qeglobals.d_texturewin.originy = y-nHeight-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
   2123 				Sys_UpdateWindows (W_TEXTURE);
   2124 				return;
   2125 			}
   2126 
   2127 			return;
   2128 		}
   2129 	}
   2130 }
   2131 
   2132 
   2133 HWND FindEditWindow()
   2134 {
   2135   HWND hwnd = FindWindow("TEditPadForm", NULL);
   2136   HWND hwndEdit = NULL;
   2137   if (hwnd != NULL)
   2138   {
   2139     HWND hwndTab = FindWindowEx(hwnd, NULL, "TTabControl", NULL);
   2140     if (hwndTab != NULL)
   2141     {
   2142       hwndEdit = FindWindowEx(hwndTab, NULL, "TRicherEdit", NULL);
   2143     }
   2144   }
   2145   return hwndEdit;
   2146 }
   2147 
   2148 void Delay(float fSeconds)
   2149 {
   2150   DWORD dw = ::GetTickCount();
   2151   DWORD dwTil = dw + (fSeconds * 1000);
   2152   while (::GetTickCount() < dwTil)
   2153   {
   2154     MSG msg;
   2155     if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
   2156     { 
   2157       TranslateMessage(&msg);
   2158       DispatchMessage(&msg);
   2159     }
   2160   }
   2161 }
   2162 
   2163 
   2164 void ViewShader(const char *pFile, const char *pName)
   2165 {
   2166   CString str;
   2167   char* pBuff = NULL;
   2168   int nSize = LoadFile(pFile, reinterpret_cast<void**>(&pBuff));
   2169   if (nSize == -1)
   2170   {
   2171     nSize = PakLoadAnyFile(pFile, reinterpret_cast<void**>(&pBuff));
   2172   }
   2173   if (nSize > 0)
   2174   {
   2175     str = pBuff;
   2176   }
   2177   int nStart = 0; 
   2178   if (str.GetLength() > 0)
   2179   {
   2180     CString strFind = pName;
   2181     CString strLook = str;
   2182     strLook.MakeLower();
   2183     strFind.MakeLower();
   2184     int n = strLook.Find(strFind);
   2185     if (n >= 0)
   2186     {
   2187       nStart = n;
   2188     }
   2189   }
   2190 
   2191   CString s= "editpad ";
   2192   s += pFile;
   2193   WinExec(s, SW_SHOWNORMAL);
   2194 
   2195   Delay(1.5);
   2196 
   2197   HWND hwndEdit = FindEditWindow();
   2198 
   2199   if (hwndEdit != NULL)
   2200   {
   2201     PostMessage(hwndEdit, EM_SETSEL, nStart, nStart);
   2202   }
   2203   else
   2204   {
   2205     Sys_Printf("Unable to load shader editor.\n");
   2206   }
   2207 
   2208 
   2209 }
   2210 
   2211 /*
   2212 ==============
   2213 SelectTexture
   2214 
   2215   By mouse click
   2216 ==============
   2217 */
   2218 void SelectTexture (int mx, int my, bool bShift, bool bFitScale)
   2219 {
   2220 	int		x, y;
   2221 	qtexture_t	*q;
   2222 	texdef_t	tex;
   2223 	brushprimit_texdef_t brushprimit_tex;
   2224 
   2225 	my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
   2226 	
   2227 	Texture_StartPos ();
   2228 	while (1)
   2229 	{
   2230 		q = Texture_NextPos (&x, &y);
   2231 		if (!q)
   2232 			break;
   2233 		int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
   2234 		int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
   2235 		if (mx > x && mx - x < nWidth
   2236 			&& my < y && y - my < nHeight + FONT_HEIGHT)
   2237 		{
   2238 			if (bShift)
   2239 			{
   2240 				if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
   2241 				{
   2242 					//CString s = "notepad ";
   2243 					//s += q->shadername;
   2244 					//WinExec(s, SW_SHOWNORMAL);	
   2245 	
   2246 					ViewShader(q->shadername, q->name);				
   2247 
   2248 				}
   2249 			}
   2250 			memset (&tex, 0, sizeof(tex));
   2251 			memset (&brushprimit_tex, 0, sizeof(brushprimit_tex));
   2252 			if (g_qeglobals.m_bBrushPrimitMode)
   2253 			{
   2254 				// brushprimit fitted to a 2x2 texture
   2255 				brushprimit_tex.coords[0][0] = 1.0f;
   2256 				brushprimit_tex.coords[1][1] = 1.0f;
   2257 			}
   2258 			else
   2259 			{
   2260 				tex.scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
   2261 				tex.scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
   2262 			}
   2263 			tex.flags = q->flags;
   2264 			tex.value = q->value;
   2265 			tex.contents = q->contents;
   2266 			//strcpy (tex.name, q->name);
   2267 			tex.SetName(q->name);
   2268 			Texture_SetTexture ( &tex, &brushprimit_tex, bFitScale, GETPLUGINTEXDEF(q));
   2269 			CString strTex;
   2270 			CString strName = q->name;
   2271 			//int nPos = strName.Find('\\');
   2272 			//if (nPos == -1)
   2273 			//  nPos = strName.Find('/');
   2274 			//if (nPos >= 0)
   2275 			//  strName = strName.Right(strName.GetLength() - nPos - 1);
   2276 			strTex.Format("%s W: %i H: %i", strName.GetBuffer(0), q->width, q->height);
   2277 			g_pParentWnd->SetStatusText(3, strTex);
   2278 			return;
   2279 		}
   2280 	}
   2281 
   2282 	Sys_Status("Did not select a texture\n", 0);
   2283 }
   2284 
   2285 /*
   2286 ==============
   2287 Texture_MouseDown
   2288 ==============
   2289 */
   2290 void Texture_MouseDown (int x, int y, int buttons)
   2291 {
   2292 	Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
   2293 
   2294 	// lbutton = select texture
   2295 	if (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_SHIFT) || buttons == (MK_LBUTTON | MK_CONTROL))
   2296 	{
   2297     SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y, buttons & MK_SHIFT, buttons & MK_CONTROL);
   2298     UpdateSurfaceDialog();
   2299     UpdatePatchInspector();
   2300 	}
   2301 }
   2302 
   2303 /*
   2304 ==============
   2305 Texture_MouseUp
   2306 ==============
   2307 */
   2308 void Texture_MouseUp (int x, int y, int buttons)
   2309 {
   2310 }
   2311 
   2312 /*
   2313 ==============
   2314 Texture_MouseMoved
   2315 ==============
   2316 */
   2317 void Texture_MouseMoved (int x, int y, int buttons)
   2318 {
   2319 	int scale = 1;
   2320 
   2321 	if ( buttons & MK_SHIFT )
   2322 		scale = 4;
   2323 
   2324 	// rbutton = drag texture origin
   2325 	if (buttons & MK_RBUTTON)
   2326 	{
   2327 		Sys_GetCursorPos (&x, &y);
   2328 		if ( y != textures_cursory)
   2329 		{
   2330 			g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
   2331 			if (g_qeglobals.d_texturewin.originy > 0)
   2332 				g_qeglobals.d_texturewin.originy = 0;
   2333 			Sys_SetCursorPos (textures_cursorx, textures_cursory);
   2334       CWnd *pWnd = CWnd::FromHandle(g_qeglobals.d_hwndTexture);
   2335       if (g_PrefsDlg.m_bTextureScrollbar && pWnd != NULL)
   2336       {
   2337         pWnd->SetScrollPos(SB_VERT, abs(g_qeglobals.d_texturewin.originy));
   2338       }
   2339 		  InvalidateRect(g_qeglobals.d_hwndTexture, NULL, false);
   2340 		  UpdateWindow (g_qeglobals.d_hwndTexture);
   2341 		}
   2342 		return;
   2343 	}
   2344 }
   2345 
   2346 
   2347 /*
   2348 ============================================================================
   2349 
   2350 DRAWING
   2351 
   2352 ============================================================================
   2353 */
   2354 
   2355 int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; }
   2356 HFONT ghFont = NULL;
   2357 
   2358 /*
   2359 ============
   2360 Texture_Draw2
   2361 ============
   2362 */
   2363 void Texture_Draw2 (int width, int height)
   2364 {
   2365 	qtexture_t	*q;
   2366 	int			x, y;
   2367 	char		*name;
   2368 
   2369 	qglClearColor (
   2370 		g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
   2371 		g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
   2372 		g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2],
   2373 		0);
   2374 	qglViewport (0,0,width,height);
   2375 	qglMatrixMode(GL_PROJECTION);
   2376 	qglLoadIdentity ();
   2377 
   2378 	qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   2379 	qglDisable (GL_DEPTH_TEST);
   2380 	qglDisable(GL_BLEND);
   2381 	qglOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
   2382 	qglEnable (GL_TEXTURE_2D);
   2383 
   2384 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   2385 	g_qeglobals.d_texturewin.width = width;
   2386 	g_qeglobals.d_texturewin.height = height;
   2387 	Texture_StartPos ();
   2388 
   2389 	while (1)
   2390 	{
   2391 		q = Texture_NextPos (&x, &y);
   2392 		if (!q)
   2393 			break;
   2394 
   2395     int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
   2396     int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
   2397 		// Is this texture visible?
   2398 		if ( (y-nHeight-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
   2399 			&& (y > g_qeglobals.d_texturewin.originy - height) )
   2400 		{
   2401 
   2402 			// if in use, draw a background
   2403 			if ((q->inuse && !texture_showinuse) || q->bFromShader)
   2404 			{
   2405 				qglLineWidth (1);
   2406 
   2407         if (q->bFromShader)
   2408         {
   2409 				  qglColor3f (1,1,1);
   2410         }
   2411         else
   2412         {
   2413 				  qglColor3f (0.5,1,0.5);
   2414         }
   2415 				qglDisable (GL_TEXTURE_2D);
   2416 
   2417 				qglBegin (GL_LINE_LOOP);
   2418 				qglVertex2f (x-1,y+1-FONT_HEIGHT);
   2419 				qglVertex2f (x-1,y-nHeight-1-FONT_HEIGHT);
   2420 				qglVertex2f (x+1+nWidth,y-nHeight-1-FONT_HEIGHT);
   2421 				qglVertex2f (x+1+nWidth,y+1-FONT_HEIGHT);
   2422 				qglEnd ();
   2423 
   2424 				qglEnable (GL_TEXTURE_2D);
   2425 			}
   2426 
   2427 			// Draw the texture
   2428       float fScale = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? ((float)g_PrefsDlg.m_nTextureScale / 100) : 1.0;
   2429 
   2430 			qglBindTexture( GL_TEXTURE_2D, q->texture_number );
   2431       QE_CheckOpenGLForErrors();
   2432 			qglColor3f (1,1,1);
   2433 			qglBegin (GL_QUADS);
   2434 			qglTexCoord2f (0,0);
   2435 			qglVertex2f (x,y-FONT_HEIGHT);
   2436 			qglTexCoord2f (1,0);
   2437 			qglVertex2f (x+nWidth,y-FONT_HEIGHT);
   2438 			qglTexCoord2f (1,1);
   2439 			qglVertex2f (x+nWidth,y-FONT_HEIGHT-nHeight);
   2440 			qglTexCoord2f (0,1);
   2441 			qglVertex2f (x,y-FONT_HEIGHT-nHeight);
   2442 			qglEnd ();
   2443 
   2444 			// draw the selection border
   2445 			if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name))
   2446 			{
   2447 				qglLineWidth (3);
   2448 				qglColor3f (1,0,0);
   2449 				qglDisable (GL_TEXTURE_2D);
   2450 
   2451 				qglBegin (GL_LINE_LOOP);
   2452 				qglVertex2f (x-4,y-FONT_HEIGHT+4);
   2453 				qglVertex2f (x-4,y-FONT_HEIGHT-nHeight-4);
   2454 				qglVertex2f (x+4+nWidth,y-FONT_HEIGHT-nHeight-4);
   2455 				qglVertex2f (x+4+nWidth,y-FONT_HEIGHT+4);
   2456 				qglEnd ();
   2457 
   2458 				qglEnable (GL_TEXTURE_2D);
   2459 				qglLineWidth (1);
   2460 			}
   2461 
   2462 			// draw the texture name
   2463   	  qglColor3f (0,0,0);
   2464 			
   2465       qglRasterPos2f (x, y-FONT_HEIGHT+2);
   2466 
   2467 			// don't draw the directory name
   2468 			for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++)
   2469 				;
   2470 			if (!*name)
   2471 				name = q->name;
   2472 			else
   2473 				name++;
   2474 
   2475       if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
   2476       {
   2477         // slow as shit
   2478         CString s = "[";
   2479         s += name;
   2480         s += "]";
   2481 			  qglCallLists (s.GetLength(), GL_UNSIGNED_BYTE, s.GetBuffer(0));
   2482       }
   2483       else
   2484       {
   2485 			  qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
   2486       }
   2487 		}
   2488 	}
   2489 
   2490 	g_qeglobals.d_texturewin.m_nTotalHeight = abs(y) + 100;
   2491 	// reset the current texture
   2492 	qglBindTexture( GL_TEXTURE_2D, 0 );
   2493 	qglFinish();
   2494 }
   2495 
   2496 
   2497 void Texture_Init (bool bHardInit)
   2498 {
   2499 	char	name[1024];
   2500 	byte	*pal = NULL;
   2501 
   2502   if (g_PrefsDlg.m_bHiColorTextures == FALSE)
   2503   {
   2504 	  // load the palette
   2505 	  sprintf (name, "%s/pics/colormap.pcx", ValueForKey (g_qeglobals.d_project_entity, "basepath"));
   2506 
   2507 	  Load256Image (name, NULL, &pal, NULL, NULL);
   2508 	  if (!pal)
   2509     {
   2510       // before dropping out, try to load it from the QERadiant directory
   2511       CString strFile = g_strAppPath;
   2512       AddSlash(strFile);
   2513       strFile += "colormap.pcx";
   2514 	    Load256Image (strFile.GetBuffer(0), NULL, &pal, NULL, NULL);
   2515 	    if (!pal)
   2516 		    Sys_Printf ("Couldn't load %s or %s", name, strFile);
   2517     }
   2518     else
   2519     {
   2520 	    Texture_InitPalette (pal);
   2521 	    free (pal);
   2522     }
   2523   }
   2524 
   2525 	// create the fallback texture
   2526 
   2527   if (bHardInit)
   2528   {
   2529 	  Texture_MakeNotexture();
   2530 	  g_qeglobals.d_qtextures = NULL;
   2531   }
   2532   LoadShaders();
   2533 
   2534 }
   2535 
   2536 void Texture_FlushUnused()
   2537 {
   2538   CWaitCursor cursor;
   2539   Texture_ShowInuse();
   2540   if (g_qeglobals.d_qtextures)
   2541   {
   2542 	  qtexture_t* pTex = g_qeglobals.d_qtextures->next;
   2543     qtexture_t *pPrev = g_qeglobals.d_qtextures;
   2544     while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
   2545     {
   2546       qtexture_t* pNextTex = pTex->next;
   2547   	  if (g_qeglobals.bSurfacePropertiesPlugin)
   2548 	    {
   2549 		    // Timo
   2550 		    // Surface properties plugin
   2551 #ifdef _DEBUG
   2552   		  if ( !pTex->pData )
   2553 	  		  Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
   2554 #endif
   2555   		  if ( pTex->pData && pTex->inuse )
   2556 	  		  GETPLUGINTEXDEF(pTex)->DecRef();
   2557   	  }
   2558 
   2559       if (!pTex->inuse)
   2560       {
   2561         unsigned int nTexture = pTex->texture_number;
   2562         qglDeleteTextures(1, &nTexture);
   2563         pPrev->next = pNextTex;
   2564 	      free(pTex);
   2565       }
   2566       else
   2567       {
   2568         pPrev = pTex;
   2569       }
   2570       pTex = pNextTex;
   2571     }
   2572   }
   2573 }
   2574 
   2575 void Texture_Cleanup(CStringList *pList)
   2576 {
   2577   if (g_qeglobals.d_qtextures)
   2578   {
   2579 	  qtexture_t* pTex = g_qeglobals.d_qtextures->next;
   2580     while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
   2581     {
   2582       qtexture_t* pNextTex = pTex->next;
   2583       if (pList)
   2584       {
   2585         if (pTex->name[0] != '(')
   2586         {
   2587           pList->AddTail(pTex->name);
   2588         }
   2589       }
   2590 
   2591   	  if (g_qeglobals.bSurfacePropertiesPlugin)
   2592 	    {
   2593 		    // Timo
   2594 		    // Surface properties plugin
   2595 #ifdef _DEBUG
   2596   		  if ( !pTex->pData )
   2597 	  		  Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
   2598 #endif
   2599   		  if ( pTex->pData )
   2600 	  		  GETPLUGINTEXDEF(pTex)->DecRef();
   2601   	  }
   2602 	    free(pTex);
   2603       pTex = pNextTex;
   2604     }
   2605   }
   2606 
   2607   int nSize = g_lstSkinCache.GetSize();
   2608   for (int i = 0; i < nSize; i++)
   2609   {
   2610     SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
   2611     delete pInfo;
   2612   }
   2613 
   2614 }
   2615 
   2616 /*
   2617 ==================
   2618 Texture_Flush
   2619 ==================
   2620 */
   2621 void Texture_Flush (bool bReload)
   2622 {
   2623   if (!ConfirmModified())
   2624     return;
   2625 
   2626   Map_New ();
   2627 
   2628   CWaitCursor cursor;
   2629   CStringList strList;
   2630   Texture_Init(false);
   2631   Texture_Cleanup(&strList);
   2632 
   2633   GLuint* pGln = new GLuint[texture_extension_number-1];
   2634   qglGenTextures(texture_extension_number-1, pGln);
   2635   QE_CheckOpenGLForErrors();
   2636   qglDeleteTextures(texture_extension_number-1, pGln);
   2637   QE_CheckOpenGLForErrors();
   2638   delete []pGln;
   2639   texture_extension_number = 1;
   2640 	g_qeglobals.d_qtextures = NULL;
   2641 
   2642   if (bReload)
   2643   {
   2644     POSITION pos = strList.GetHeadPosition();
   2645     while (pos)
   2646     {
   2647       CString strTex = strList.GetNext(pos);
   2648 		  Texture_ForName (strTex.GetBuffer(0));
   2649     }
   2650   }
   2651 
   2652 }
   2653 
   2654 
   2655 
   2656 /////////////////////////////////////////////////////////////////////////////
   2657 // CTexWnd
   2658 IMPLEMENT_DYNCREATE(CTexWnd, CWnd);
   2659 
   2660 CTexWnd::CTexWnd()
   2661 {
   2662   m_bNeedRange = true;
   2663 }
   2664 
   2665 CTexWnd::~CTexWnd()
   2666 {
   2667 }
   2668 
   2669 
   2670 BEGIN_MESSAGE_MAP(CTexWnd, CWnd)
   2671 	//{{AFX_MSG_MAP(CTexWnd)
   2672 	ON_WM_CREATE()
   2673 	ON_WM_SIZE()
   2674 	ON_WM_PARENTNOTIFY()
   2675 	ON_WM_TIMER()
   2676 	ON_WM_KEYDOWN()
   2677 	ON_WM_KEYUP()
   2678 	ON_WM_PAINT()
   2679 	ON_WM_VSCROLL()
   2680 	ON_COMMAND(ID_TEXTURES_FLUSH, OnTexturesFlush)
   2681   ON_BN_CLICKED(1200, OnShaderClick)
   2682 	//}}AFX_MSG_MAP
   2683 END_MESSAGE_MAP()
   2684 
   2685 
   2686 /////////////////////////////////////////////////////////////////////////////
   2687 // CTexWnd message handlers
   2688 
   2689 /*
   2690 ============
   2691 WTexWndProc
   2692 ============
   2693 */
   2694 LONG WINAPI TexWndProc (
   2695     HWND    hWnd,
   2696     UINT    uMsg,
   2697     WPARAM  wParam,
   2698     LPARAM  lParam)
   2699 {
   2700 	int		xPos, yPos;
   2701     RECT	rect;
   2702 
   2703     GetClientRect(hWnd, &rect);
   2704 
   2705     switch (uMsg)
   2706     {
   2707 	case WM_CREATE:
   2708     s_hdcTexture = GetDC(hWnd);
   2709 		QEW_SetupPixelFormat(s_hdcTexture, false);
   2710 
   2711 		if ( ( s_hglrcTexture = qwglCreateContext( s_hdcTexture ) ) == 0 )
   2712 			Error( "wglCreateContext in WTex_WndProc failed" );
   2713 
   2714 		if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) )
   2715 			Error( "wglShareLists in WTex_WndProc failed" );
   2716 
   2717     if (!qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ))
   2718 		  Error ("wglMakeCurrent in WTex_WndProc failed");
   2719 
   2720 	  g_qeglobals.d_hwndTexture = hWnd;
   2721 		return 0;
   2722 
   2723 	case WM_DESTROY:
   2724 		//wglMakeCurrent( NULL, NULL );
   2725 		//wglDeleteContext( s_hglrcTexture );
   2726 		 ReleaseDC( hWnd, s_hdcTexture );
   2727 		return 0;
   2728 #if 0
   2729 	case WM_PAINT:
   2730         { 
   2731 		    PAINTSTRUCT	ps;
   2732 
   2733 		    BeginPaint(hWnd, &ps);
   2734 
   2735         if ( !qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ) )
   2736         //if ( !wglMakeCurrent( ps.hdc, s_hglrcTexture ) )
   2737         {
   2738           Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
   2739           Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
   2740         }
   2741         else
   2742         {
   2743 			    Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top - g_nTextureOffset);
   2744 			    qwglSwapBuffers(s_hdcTexture);
   2745           TRACE("Texture Paint\n");
   2746         }
   2747 		    EndPaint(hWnd, &ps);
   2748         }
   2749 		return 0;
   2750 #endif
   2751 	case WM_MBUTTONDOWN:
   2752 	case WM_RBUTTONDOWN:
   2753 	case WM_LBUTTONDOWN:
   2754 		SetCapture( g_qeglobals.d_hwndTexture );
   2755 		xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
   2756 		yPos = (short)HIWORD(lParam);  // vertical position of cursor 
   2757 		
   2758 		Texture_MouseDown (xPos, yPos - g_nTextureOffset, wParam);
   2759 		return 0;
   2760 
   2761 	case WM_MBUTTONUP:
   2762 	case WM_RBUTTONUP:
   2763 	case WM_LBUTTONUP:
   2764 		xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
   2765 		yPos = (short)HIWORD(lParam);  // vertical position of cursor 
   2766 		
   2767 		Texture_MouseUp (xPos, yPos - g_nTextureOffset, wParam);
   2768 		if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
   2769 			ReleaseCapture ();
   2770 		return 0;
   2771 
   2772 	case WM_MOUSEMOVE:
   2773 		xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
   2774 		yPos = (short)HIWORD(lParam);  // vertical position of cursor 
   2775 		
   2776 		Texture_MouseMoved (xPos, yPos - g_nTextureOffset, wParam);
   2777 		return 0;
   2778     }
   2779 
   2780     return DefWindowProc (hWnd, uMsg, wParam, lParam);
   2781 }
   2782 
   2783 
   2784 
   2785 BOOL CTexWnd::PreCreateWindow(CREATESTRUCT& cs) 
   2786 {
   2787   WNDCLASS wc;
   2788   HINSTANCE hInstance = AfxGetInstanceHandle();
   2789   if (::GetClassInfo(hInstance, TEXTURE_WINDOW_CLASS, &wc) == FALSE)
   2790   {
   2791     // Register a new class
   2792   	memset (&wc, 0, sizeof(wc));
   2793     wc.style         = CS_NOCLOSE | CS_OWNDC;
   2794     wc.lpszClassName = TEXTURE_WINDOW_CLASS;
   2795     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
   2796     wc.lpfnWndProc = TexWndProc;
   2797     if (AfxRegisterClass(&wc) == FALSE)
   2798       Error ("CZWnd RegisterClass: failed");
   2799   }
   2800 
   2801   cs.lpszClass = TEXTURE_WINDOW_CLASS;
   2802   cs.lpszName = "TEX";
   2803   if (cs.style != QE3_CHILDSTYLE && cs.style != QE3_STYLE)
   2804     cs.style = QE3_SPLITTER_STYLE;
   2805 
   2806 	return CWnd::PreCreateWindow(cs);
   2807 }
   2808 
   2809 int CTexWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
   2810 {
   2811 	if (CWnd::OnCreate(lpCreateStruct) == -1)
   2812 		return -1;
   2813 
   2814   CRect rctEdit(8, 5, 20, 20);
   2815   g_nTextureOffset = 0;
   2816 
   2817 /*
   2818   if (g_PrefsDlg.m_bShaderTest)
   2819   {
   2820     m_wndShaders.Create("Show Shaders", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, rctEdit, this, 1200);
   2821     m_wndShaders.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
   2822     m_wndShaders.SetCheck(g_PrefsDlg.m_bShowShaders);
   2823     g_nTextureOffset = 25;
   2824   }
   2825 */
   2826   rctEdit.SetRect(8, g_nTextureOffset, 20, 20);
   2827   m_wndFilter.Create(WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_LEFT, rctEdit, this, 1201);
   2828   m_wndFilter.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
   2829   m_wndFilter.SetTexWnd(this);
   2830 
   2831   g_nTextureOffset += 25;
   2832   if (!g_PrefsDlg.m_bTextureWindow)
   2833   {
   2834     m_wndFilter.ShowWindow(SW_HIDE);
   2835     g_nTextureOffset -= 25;
   2836   }
   2837 
   2838   ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
   2839   m_bNeedRange = true;
   2840 
   2841 	return 0;
   2842 }
   2843 
   2844 void CTexWnd::OnSize(UINT nType, int cx, int cy) 
   2845 {
   2846 	CWnd::OnSize(nType, cx, cy);
   2847   CRect rctClient;
   2848   GetClientRect(rctClient);
   2849 /*
   2850   if (g_PrefsDlg.m_bShaderTest && m_wndShaders.GetSafeHwnd())
   2851   {
   2852     m_wndShaders.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 5, rctClient.right - 16, 20, 0);
   2853   }
   2854 */
   2855   m_wndFilter.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 25, rctClient.right - 16, 20, 0);
   2856   m_bNeedRange = true;
   2857 }
   2858 
   2859 void CTexWnd::OnShaderClick()
   2860 {
   2861   g_PrefsDlg.m_bShowShaders = (m_wndShaders.GetCheck() != 0);
   2862   g_PrefsDlg.SavePrefs();
   2863 	RedrawWindow();
   2864 }
   2865 
   2866 void CTexWnd::OnParentNotify(UINT message, LPARAM lParam) 
   2867 {
   2868 	CWnd::OnParentNotify(message, lParam);
   2869 }
   2870 
   2871 int g_nLastLen = 0;
   2872 int g_nTimerHandle = -1;
   2873 char g_cLastChar;
   2874 
   2875 void CTexWnd::UpdateFilter(const char* pFilter)
   2876 {
   2877   if (g_nTimerHandle > 0)
   2878     KillTimer(1);
   2879   g_bFilterEnabled = false;
   2880   if (pFilter)
   2881   {
   2882     g_strFilter = pFilter;
   2883     if (g_strFilter.GetLength() > 0)
   2884     {
   2885       g_bFilterEnabled = true;
   2886       if (g_pParentWnd->CurrentStyle() == QR_QE4 || g_pParentWnd->CurrentStyle() == QR_4WAY)
   2887       {
   2888         if (g_strFilter.GetLength() > g_nLastLen)
   2889         {
   2890           g_cLastChar = toupper(g_strFilter.GetAt(g_strFilter.GetLength()-1));
   2891           if (g_cLastChar == 'N' || g_cLastChar == 'O') // one of the other popups
   2892           {
   2893             g_nTimerHandle = SetTimer(1, 800, NULL);   // half second timer
   2894           }
   2895         }
   2896       }
   2897     }
   2898     g_nLastLen = g_strFilter.GetLength();
   2899 	  SortTextures();
   2900   }
   2901   Sys_UpdateWindows (W_TEXTURE);
   2902 }
   2903 
   2904 void CTexWnd::UpdatePrefs()
   2905 {
   2906   if (!g_PrefsDlg.m_bTextureWindow)
   2907   {
   2908     m_wndFilter.ShowWindow(SW_HIDE);
   2909     g_nTextureOffset = 0;
   2910   }
   2911   else
   2912   {
   2913     m_wndFilter.ShowWindow(SW_SHOW);
   2914     g_nTextureOffset = 25;
   2915   }
   2916   ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
   2917   m_bNeedRange = true;
   2918   Invalidate();
   2919   UpdateWindow();
   2920 }
   2921 
   2922 void CTexWnd::FocusEdit()
   2923 {
   2924   if (m_wndFilter.IsWindowVisible())
   2925     m_wndFilter.SetFocus();
   2926 }
   2927 
   2928 void CTexWnd::OnTimer(UINT nIDEvent) 
   2929 {
   2930   KillTimer(1);
   2931   g_nLastLen = 0;
   2932   g_nTimerHandle = -1;
   2933   ::SetFocus(g_qeglobals.d_hwndEntity);
   2934   ::PostMessage(g_qeglobals.d_hwndEntity, WM_CHAR, g_cLastChar, 0);
   2935 }
   2936 
   2937 void CTexWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
   2938 {
   2939   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
   2940 	//CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
   2941 }
   2942 
   2943 void CTexWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
   2944 {
   2945   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
   2946 }
   2947 
   2948 void CTexWnd::OnPaint() 
   2949 {
   2950 	CPaintDC dc(this); // device context for painting
   2951   CRect rctClient;
   2952   GetClientRect(rctClient);
   2953   int nOld = g_qeglobals.d_texturewin.m_nTotalHeight;
   2954   if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
   2955   //if ( !qwglMakeCurrent(dc.m_hDC, s_hglrcTexture ) )
   2956   {
   2957     Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
   2958     Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
   2959   }
   2960   else
   2961   {
   2962     Texture_Draw2 (rctClient.right-rctClient.left, rctClient.bottom-rctClient.top - g_nTextureOffset);
   2963 		qwglSwapBuffers(s_hdcTexture);
   2964     TRACE("Texture Paint\n");
   2965   }
   2966   if (g_PrefsDlg.m_bTextureScrollbar && (m_bNeedRange || g_qeglobals.d_texturewin.m_nTotalHeight != nOld))
   2967   {
   2968     m_bNeedRange = false;
   2969     SetScrollRange(SB_VERT, 0, g_qeglobals.d_texturewin.m_nTotalHeight, TRUE);
   2970   }
   2971 }
   2972 
   2973 void CTexWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
   2974 {
   2975 	CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
   2976 
   2977   int n = GetScrollPos(SB_VERT);;
   2978   switch (nSBCode)
   2979   {
   2980     case SB_LINEUP :
   2981     {
   2982       n = (n - 15 >  0) ? n - 15 : 0; 
   2983       break;
   2984     }
   2985     case SB_LINEDOWN :
   2986     {
   2987       n = (n + 15 < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + 15 : n; 
   2988       break;
   2989     }
   2990     case SB_PAGEUP :
   2991     {
   2992       n = (n - g_qeglobals.d_texturewin.height >  0) ? n - g_qeglobals.d_texturewin.height : 0; 
   2993       break;
   2994     }
   2995     case SB_PAGEDOWN :
   2996     {
   2997       n = (n + g_qeglobals.d_texturewin.height < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + g_qeglobals.d_texturewin.height : n; 
   2998       break;
   2999     }
   3000     case SB_THUMBPOSITION :
   3001     {
   3002       n = nPos;
   3003       break;
   3004     }
   3005     case SB_THUMBTRACK :
   3006     {
   3007       n = nPos;
   3008       break;
   3009     }
   3010   }
   3011   SetScrollPos(SB_VERT, n);
   3012 	g_qeglobals.d_texturewin.originy = -((int)n);
   3013   Invalidate();
   3014   UpdateWindow();
   3015   //Sys_UpdateWindows(W_TEXTURE);
   3016 }
   3017 
   3018 /*
   3019 and are the caps new caps?  anything done with older stuff will be fubar'd.. which brings up the point if you ever naturalize a cap, you cannot force it back to cap texturing.. i will add that too
   3020 */
   3021 
   3022 void CTexWnd::OnTexturesFlush() 
   3023 {
   3024 	// TODO: Add your command handler code here
   3025 	
   3026 }
   3027 
   3028 void LoadShaders()
   3029 {
   3030 	char	dirstring[1024];
   3031 	char	*path;
   3032 	//struct _finddata_t fileinfo;
   3033 	//int		handle;
   3034   path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
   3035   sprintf (dirstring, "%s/scripts/shaderlist.txt", path);
   3036   char *pBuff = NULL;
   3037   
   3038   int nLen = LoadFile(dirstring, reinterpret_cast<void**>(&pBuff));
   3039   if (nLen == -1)
   3040   {
   3041     nLen = PakLoadAnyFile(dirstring, reinterpret_cast<void**>(&pBuff));
   3042   }
   3043   if (nLen > 0)
   3044   {
   3045     CStringList lst;
   3046     StartTokenParsing(pBuff);
   3047     nLen = 0;
   3048     while (GetToken(true))
   3049     {
   3050       // each token should be a shader filename
   3051       sprintf(dirstring, "%s/scripts/%s.shader", path, token);
   3052       lst.AddTail(dirstring);
   3053       nLen++;
   3054     }
   3055     POSITION pos = lst.GetHeadPosition();
   3056     while (pos != NULL)
   3057     {
   3058       LoadShader(lst.GetAt(pos).GetBuffer(0), NULL);
   3059       lst.GetNext(pos);
   3060     }
   3061     free(pBuff);
   3062   }
   3063   else
   3064   {
   3065     Sys_Printf("Unable to load shaderlist.txt, shaders not loaded!");
   3066   }
   3067 
   3068 /*
   3069   handle = _findfirst (dirstring, &fileinfo);
   3070   if (handle != -1)
   3071   {
   3072     do
   3073     {
   3074       if ((fileinfo.attrib & _A_SUBDIR))
   3075         continue;
   3076       sprintf(dirstring, "%s/scripts/%s", path, fileinfo.name);
   3077       LoadShader(dirstring, NULL);
   3078 	  } while (_findnext( handle, &fileinfo ) != -1);
   3079 
   3080 	  _findclose (handle);
   3081   }
   3082 */
   3083 }
   3084 
   3085 void FreeShaders()
   3086 {
   3087   int nSize = g_lstShaders.GetSize();
   3088   for (int i = 0; i < nSize; i++)
   3089   {
   3090     CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
   3091     delete pInfo;
   3092   }
   3093 
   3094   g_lstShaders.RemoveAll();
   3095 }
   3096 
   3097 void ReloadShaders()
   3098 {
   3099   FreeShaders();
   3100   LoadShaders();
   3101   qtexture_t* pTex = g_qeglobals.d_qtextures;
   3102   while (pTex != NULL)
   3103   {
   3104     SetNameShaderInfo(pTex, NULL, pTex->name);
   3105     pTex = pTex->next;
   3106   }
   3107 
   3108 }
   3109 
   3110 int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight)
   3111 {
   3112   byte *pic = NULL;
   3113   byte *pic32 = NULL;
   3114   int nTex = -1;
   3115 
   3116   strlwr(pName);
   3117   QE_ConvertDOSToUnixName(pName, pName);
   3118 
   3119   int nSize = g_lstSkinCache.GetSize();
   3120   for (int i = 0; i < nSize; i++)
   3121   {
   3122     SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
   3123     if (pInfo)
   3124     {
   3125       if (stricmp(pName, pInfo->m_strName) == 0)
   3126       {
   3127         return pInfo->m_nTextureBind;
   3128       }
   3129     }
   3130   }
   3131 
   3132   LoadImage( pName, &pic32, pnWidth, pnHeight);
   3133   if (pic32 != NULL)
   3134   {
   3135 
   3136     nTex = texture_extension_number++;
   3137     if (g_PrefsDlg.m_bSGIOpenGL)
   3138     {
   3139       //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
   3140       if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
   3141 		    Error ("wglMakeCurrent in LoadTexture failed");
   3142     }
   3143 
   3144     qglBindTexture( GL_TEXTURE_2D, nTex);
   3145     SetTexParameters ();
   3146 
   3147 	  int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
   3148 	  while (nCount-- > 0)
   3149 	  {
   3150 	    if (*pnWidth > 16 && *pnHeight > 16)
   3151 	    {
   3152 	      R_MipMap(pic32, *pnWidth, *pnHeight);
   3153 	    }
   3154 	    else
   3155 	    {
   3156 	      break;
   3157 	    }
   3158 	  }
   3159 
   3160     if (g_PrefsDlg.m_bSGIOpenGL)
   3161     {
   3162 	    if (nomips)
   3163       {
   3164 		    qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
   3165       }
   3166 	    else
   3167 		    qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
   3168     }
   3169     else
   3170     {
   3171 	    if (nomips)
   3172 		    qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
   3173 	    else
   3174 		    qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
   3175     }
   3176 	  free (pic32);
   3177 	  qglBindTexture( GL_TEXTURE_2D, 0 );
   3178   }
   3179 
   3180   SkinInfo *pInfo = new SkinInfo(pName, nTex);
   3181   g_lstSkinCache.Add(pInfo);
   3182 
   3183   return nTex;
   3184 }
   3185 
   3186