diff options
Diffstat (limited to 'indra/llwindow')
| -rw-r--r-- | indra/llwindow/lldragdropwin32.cpp | 740 | ||||
| -rw-r--r-- | indra/llwindow/lldragdropwin32.h | 160 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 7386 | 
3 files changed, 4143 insertions, 4143 deletions
| diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index 1e10626e8a..9b80fe0a84 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -1,370 +1,370 @@ -/**
 - * @file lldragdrop32.cpp
 - * @brief Handler for Windows specific drag and drop (OS to client) code
 - *
 - * $LicenseInfo:firstyear=2001&license=viewergpl$
 - *
 - * Copyright (c) 2001-2009, Linden Research, Inc.
 - *
 - * Second Life Viewer Source Code
 - * The source code in this file ("Source Code") is provided by Linden Lab
 - * to you under the terms of the GNU General Public License, version 2.0
 - * ("GPL"), unless you have obtained a separate licensing agreement
 - * ("Other License"), formally executed by you and Linden Lab.  Terms of
 - * the GPL can be found in doc/GPL-license.txt in this distribution, or
 - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 - *
 - * There are special exceptions to the terms and conditions of the GPL as
 - * it is applied to this Source Code. View the full text of the exception
 - * in the file doc/FLOSS-exception.txt in this software distribution, or
 - * online at
 - * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 - *
 - * By copying, modifying or distributing this software, you acknowledge
 - * that you have read and understood your obligations described above,
 - * and agree to abide by those obligations.
 - *
 - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 - * COMPLETENESS OR PERFORMANCE.
 - * $/LicenseInfo$
 - */
 -
 -#if LL_WINDOWS
 -
 -#if LL_OS_DRAGDROP_ENABLED
 -
 -#include "linden_common.h"
 -
 -#include "llwindowwin32.h"
 -#include "llkeyboardwin32.h"
 -#include "llwindowcallbacks.h"
 -#include "lldragdropwin32.h"
 -
 -class LLDragDropWin32Target: 
 -	public IDropTarget
 -{
 -	public:
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		LLDragDropWin32Target( HWND  hWnd ) :
 -			mRefCount( 1 ),
 -			mAppWindowHandle( hWnd ),
 -			mAllowDrop( false)
 -		{
 -		};
 -
 -		virtual ~LLDragDropWin32Target()
 -		{
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		ULONG __stdcall AddRef( void )
 -		{
 -			return InterlockedIncrement( &mRefCount );
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		ULONG __stdcall Release( void )
 -		{
 -			LONG count = InterlockedDecrement( &mRefCount );
 -				
 -			if ( count == 0 )
 -			{
 -				delete this;
 -				return 0;
 -			}
 -			else
 -			{
 -				return count;
 -			};
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject )
 -		{
 -			if ( iid == IID_IUnknown || iid == IID_IDropTarget )
 -			{
 -				AddRef();
 -				*ppvObject = this;
 -				return S_OK;
 -			}
 -			else
 -			{
 -				*ppvObject = 0;
 -				return E_NOINTERFACE;
 -			};
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
 -		{
 -			FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
 -
 -			// support CF_TEXT using a HGLOBAL?
 -			if ( S_OK == pDataObject->QueryGetData( &fmtetc ) )
 -			{
 -				mAllowDrop = true;
 -				mDropUrl = std::string();
 -				mIsSlurl = false;
 -
 -				STGMEDIUM stgmed;
 -				if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) )
 -				{
 -					PVOID data = GlobalLock( stgmed.hGlobal );
 -					mDropUrl = std::string( (char*)data );
 -					// XXX MAJOR MAJOR HACK!
 -					LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
 -					if (NULL != window_imp)
 -					{
 -						LLCoordGL gl_coord( 0, 0 );
 -
 -						POINT pt2;
 -						pt2.x = pt.x;
 -						pt2.y = pt.y;
 -						ScreenToClient( mAppWindowHandle, &pt2 );
 -
 -						LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
 -						window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -						MASK mask = gKeyboard->currentMask(TRUE);
 -
 -						LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, 
 -							LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
 -
 -						switch (result)
 -						{
 -						case LLWindowCallbacks::DND_COPY:
 -							*pdwEffect = DROPEFFECT_COPY;
 -							break;
 -						case LLWindowCallbacks::DND_LINK:
 -							*pdwEffect = DROPEFFECT_LINK;
 -							break;
 -						case LLWindowCallbacks::DND_MOVE:
 -							*pdwEffect = DROPEFFECT_MOVE;
 -							break;
 -						case LLWindowCallbacks::DND_NONE:
 -						default:
 -							*pdwEffect = DROPEFFECT_NONE;
 -							break;
 -						}
 -					};
 -
 -					GlobalUnlock( stgmed.hGlobal );
 -					ReleaseStgMedium( &stgmed );
 -				};
 -				SetFocus( mAppWindowHandle );
 -			}
 -			else
 -			{
 -				mAllowDrop = false;
 -				*pdwEffect = DROPEFFECT_NONE;
 -			};
 -
 -			return S_OK;
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
 -		{
 -			if ( mAllowDrop )
 -			{
 -				// XXX MAJOR MAJOR HACK!
 -				LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
 -				if (NULL != window_imp)
 -				{
 -					LLCoordGL gl_coord( 0, 0 );
 -
 -					POINT pt2;
 -					pt2.x = pt.x;
 -					pt2.y = pt.y;
 -					ScreenToClient( mAppWindowHandle, &pt2 );
 -
 -					LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -					MASK mask = gKeyboard->currentMask(TRUE);
 -
 -					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, 
 -						LLWindowCallbacks::DNDA_TRACK, mDropUrl );
 -					
 -					switch (result)
 -					{
 -					case LLWindowCallbacks::DND_COPY:
 -						*pdwEffect = DROPEFFECT_COPY;
 -						break;
 -					case LLWindowCallbacks::DND_LINK:
 -						*pdwEffect = DROPEFFECT_LINK;
 -						break;
 -					case LLWindowCallbacks::DND_MOVE:
 -						*pdwEffect = DROPEFFECT_MOVE;
 -						break;
 -					case LLWindowCallbacks::DND_NONE:
 -					default:
 -						*pdwEffect = DROPEFFECT_NONE;
 -						break;
 -					}
 -				};
 -			}
 -			else
 -			{
 -				*pdwEffect = DROPEFFECT_NONE;
 -			};
 -
 -			return S_OK;
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		HRESULT __stdcall DragLeave( void )
 -		{
 -			// XXX MAJOR MAJOR HACK!
 -			LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
 -			if (NULL != window_imp)
 -			{
 -				LLCoordGL gl_coord( 0, 0 );
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
 -			};
 -			return S_OK;
 -		};
 -
 -		////////////////////////////////////////////////////////////////////////////////
 -		//
 -		HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
 -		{
 -			if ( mAllowDrop )
 -			{
 -				// window impl stored in Window data (neat!)
 -				LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
 -				if ( NULL != window_imp )
 -				{
 -					LLCoordGL gl_coord( 0, 0 );
 -
 -					POINT pt_client;
 -					pt_client.x = pt.x;
 -					pt_client.y = pt.y;
 -					ScreenToClient( mAppWindowHandle, &pt_client );
 -
 -					LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -					llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
 -					llinfos << "###        raw coords are: " << pt.x << " x " << pt.y << llendl;
 -					llinfos << "###	    client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
 -					llinfos << "###         GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl;
 -					llinfos << llendl;
 -
 -					// no keyboard modifier option yet but we could one day
 -					MASK mask = gKeyboard->currentMask( TRUE );
 -
 -					// actually do the drop
 -					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, 
 -						LLWindowCallbacks::DNDA_DROPPED, mDropUrl );
 -
 -					switch (result)
 -					{
 -					case LLWindowCallbacks::DND_COPY:
 -						*pdwEffect = DROPEFFECT_COPY;
 -						break;
 -					case LLWindowCallbacks::DND_LINK:
 -						*pdwEffect = DROPEFFECT_LINK;
 -						break;
 -					case LLWindowCallbacks::DND_MOVE:
 -						*pdwEffect = DROPEFFECT_MOVE;
 -						break;
 -					case LLWindowCallbacks::DND_NONE:
 -					default:
 -						*pdwEffect = DROPEFFECT_NONE;
 -						break;
 -					}
 -				};
 -			}
 -			else
 -			{
 -				*pdwEffect = DROPEFFECT_NONE;
 -			};
 -
 -			return S_OK;
 -		};
 -
 -	////////////////////////////////////////////////////////////////////////////////
 -	//
 -	private:
 -		LONG mRefCount;
 -		HWND mAppWindowHandle;
 -		bool mAllowDrop;
 -		std::string mDropUrl;
 -		bool mIsSlurl;
 -		friend class LLWindowWin32;
 -};
 -
 -////////////////////////////////////////////////////////////////////////////////
 -//
 -LLDragDropWin32::LLDragDropWin32() :
 -	mDropTarget( NULL ),
 -	mDropWindowHandle( NULL )
 -
 -{
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////
 -//
 -LLDragDropWin32::~LLDragDropWin32()
 -{
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////
 -//
 -bool LLDragDropWin32::init( HWND hWnd )
 -{
 -	if ( NOERROR != OleInitialize( NULL ) )
 -		return FALSE; 
 -
 -	mDropTarget = new LLDragDropWin32Target( hWnd );
 -	if ( mDropTarget )
 -	{
 -		HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE );
 -		if ( S_OK == result )
 -		{
 -			result = RegisterDragDrop( hWnd, mDropTarget );
 -			if ( S_OK != result )
 -			{
 -				// RegisterDragDrop failed
 -				return false;
 -			};
 -
 -			// all ok
 -			mDropWindowHandle = hWnd;
 -		}
 -		else
 -		{
 -			// Unable to lock OLE object
 -			return false;
 -		};
 -	};
 -
 -	// success
 -	return true;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////
 -//
 -void LLDragDropWin32::reset()
 -{
 -	if ( mDropTarget )
 -	{
 -		RevokeDragDrop( mDropWindowHandle );
 -		CoLockObjectExternal( mDropTarget, FALSE, TRUE );
 -		mDropTarget->Release();  
 -	};
 -	
 -	OleUninitialize();
 -}
 -
 -#endif // LL_OS_DRAGDROP_ENABLED
 -
 -#endif // LL_WINDOWS
 -
 +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#include "linden_common.h" + +#include "llwindowwin32.h" +#include "llkeyboardwin32.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" + +class LLDragDropWin32Target:  +	public IDropTarget +{ +	public: +		//////////////////////////////////////////////////////////////////////////////// +		// +		LLDragDropWin32Target( HWND  hWnd ) : +			mRefCount( 1 ), +			mAppWindowHandle( hWnd ), +			mAllowDrop( false) +		{ +		}; + +		virtual ~LLDragDropWin32Target() +		{ +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		ULONG __stdcall AddRef( void ) +		{ +			return InterlockedIncrement( &mRefCount ); +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		ULONG __stdcall Release( void ) +		{ +			LONG count = InterlockedDecrement( &mRefCount ); +				 +			if ( count == 0 ) +			{ +				delete this; +				return 0; +			} +			else +			{ +				return count; +			}; +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) +		{ +			if ( iid == IID_IUnknown || iid == IID_IDropTarget ) +			{ +				AddRef(); +				*ppvObject = this; +				return S_OK; +			} +			else +			{ +				*ppvObject = 0; +				return E_NOINTERFACE; +			}; +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) +		{ +			FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + +			// support CF_TEXT using a HGLOBAL? +			if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) +			{ +				mAllowDrop = true; +				mDropUrl = std::string(); +				mIsSlurl = false; + +				STGMEDIUM stgmed; +				if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) +				{ +					PVOID data = GlobalLock( stgmed.hGlobal ); +					mDropUrl = std::string( (char*)data ); +					// XXX MAJOR MAJOR HACK! +					LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); +					if (NULL != window_imp) +					{ +						LLCoordGL gl_coord( 0, 0 ); + +						POINT pt2; +						pt2.x = pt.x; +						pt2.y = pt.y; +						ScreenToClient( mAppWindowHandle, &pt2 ); + +						LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); +						window_imp->convertCoords(cursor_coord_window, &gl_coord); +						MASK mask = gKeyboard->currentMask(TRUE); + +						LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,  +							LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); + +						switch (result) +						{ +						case LLWindowCallbacks::DND_COPY: +							*pdwEffect = DROPEFFECT_COPY; +							break; +						case LLWindowCallbacks::DND_LINK: +							*pdwEffect = DROPEFFECT_LINK; +							break; +						case LLWindowCallbacks::DND_MOVE: +							*pdwEffect = DROPEFFECT_MOVE; +							break; +						case LLWindowCallbacks::DND_NONE: +						default: +							*pdwEffect = DROPEFFECT_NONE; +							break; +						} +					}; + +					GlobalUnlock( stgmed.hGlobal ); +					ReleaseStgMedium( &stgmed ); +				}; +				SetFocus( mAppWindowHandle ); +			} +			else +			{ +				mAllowDrop = false; +				*pdwEffect = DROPEFFECT_NONE; +			}; + +			return S_OK; +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) +		{ +			if ( mAllowDrop ) +			{ +				// XXX MAJOR MAJOR HACK! +				LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); +				if (NULL != window_imp) +				{ +					LLCoordGL gl_coord( 0, 0 ); + +					POINT pt2; +					pt2.x = pt.x; +					pt2.y = pt.y; +					ScreenToClient( mAppWindowHandle, &pt2 ); + +					LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					MASK mask = gKeyboard->currentMask(TRUE); + +					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,  +						LLWindowCallbacks::DNDA_TRACK, mDropUrl ); +					 +					switch (result) +					{ +					case LLWindowCallbacks::DND_COPY: +						*pdwEffect = DROPEFFECT_COPY; +						break; +					case LLWindowCallbacks::DND_LINK: +						*pdwEffect = DROPEFFECT_LINK; +						break; +					case LLWindowCallbacks::DND_MOVE: +						*pdwEffect = DROPEFFECT_MOVE; +						break; +					case LLWindowCallbacks::DND_NONE: +					default: +						*pdwEffect = DROPEFFECT_NONE; +						break; +					} +				}; +			} +			else +			{ +				*pdwEffect = DROPEFFECT_NONE; +			}; + +			return S_OK; +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		HRESULT __stdcall DragLeave( void ) +		{ +			// XXX MAJOR MAJOR HACK! +			LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); +			if (NULL != window_imp) +			{ +				LLCoordGL gl_coord( 0, 0 ); +				MASK mask = gKeyboard->currentMask(TRUE); +				window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); +			}; +			return S_OK; +		}; + +		//////////////////////////////////////////////////////////////////////////////// +		// +		HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) +		{ +			if ( mAllowDrop ) +			{ +				// window impl stored in Window data (neat!) +				LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); +				if ( NULL != window_imp ) +				{ +					LLCoordGL gl_coord( 0, 0 ); + +					POINT pt_client; +					pt_client.x = pt.x; +					pt_client.y = pt.y; +					ScreenToClient( mAppWindowHandle, &pt_client ); + +					LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					llinfos << "### (Drop) URL is: " << mDropUrl << llendl; +					llinfos << "###        raw coords are: " << pt.x << " x " << pt.y << llendl; +					llinfos << "###	    client coords are: " << pt_client.x << " x " << pt_client.y << llendl; +					llinfos << "###         GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; +					llinfos << llendl; + +					// no keyboard modifier option yet but we could one day +					MASK mask = gKeyboard->currentMask( TRUE ); + +					// actually do the drop +					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,  +						LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); + +					switch (result) +					{ +					case LLWindowCallbacks::DND_COPY: +						*pdwEffect = DROPEFFECT_COPY; +						break; +					case LLWindowCallbacks::DND_LINK: +						*pdwEffect = DROPEFFECT_LINK; +						break; +					case LLWindowCallbacks::DND_MOVE: +						*pdwEffect = DROPEFFECT_MOVE; +						break; +					case LLWindowCallbacks::DND_NONE: +					default: +						*pdwEffect = DROPEFFECT_NONE; +						break; +					} +				}; +			} +			else +			{ +				*pdwEffect = DROPEFFECT_NONE; +			}; + +			return S_OK; +		}; + +	//////////////////////////////////////////////////////////////////////////////// +	// +	private: +		LONG mRefCount; +		HWND mAppWindowHandle; +		bool mAllowDrop; +		std::string mDropUrl; +		bool mIsSlurl; +		friend class LLWindowWin32; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::LLDragDropWin32() : +	mDropTarget( NULL ), +	mDropWindowHandle( NULL ) + +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::~LLDragDropWin32() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLDragDropWin32::init( HWND hWnd ) +{ +	if ( NOERROR != OleInitialize( NULL ) ) +		return FALSE;  + +	mDropTarget = new LLDragDropWin32Target( hWnd ); +	if ( mDropTarget ) +	{ +		HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); +		if ( S_OK == result ) +		{ +			result = RegisterDragDrop( hWnd, mDropTarget ); +			if ( S_OK != result ) +			{ +				// RegisterDragDrop failed +				return false; +			}; + +			// all ok +			mDropWindowHandle = hWnd; +		} +		else +		{ +			// Unable to lock OLE object +			return false; +		}; +	}; + +	// success +	return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLDragDropWin32::reset() +{ +	if ( mDropTarget ) +	{ +		RevokeDragDrop( mDropWindowHandle ); +		CoLockObjectExternal( mDropTarget, FALSE, TRUE ); +		mDropTarget->Release();   +	}; +	 +	OleUninitialize(); +} + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS + diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h index 26c8e4aeff..9686626d7c 100644 --- a/indra/llwindow/lldragdropwin32.h +++ b/indra/llwindow/lldragdropwin32.h @@ -1,80 +1,80 @@ -/**
 - * @file lldragdrop32.cpp
 - * @brief Handler for Windows specific drag and drop (OS to client) code
 - *
 - * $LicenseInfo:firstyear=2004&license=viewergpl$
 - *
 - * Copyright (c) 2004-2009, Linden Research, Inc.
 - *
 - * Second Life Viewer Source Code
 - * The source code in this file ("Source Code") is provided by Linden Lab
 - * to you under the terms of the GNU General Public License, version 2.0
 - * ("GPL"), unless you have obtained a separate licensing agreement
 - * ("Other License"), formally executed by you and Linden Lab.  Terms of
 - * the GPL can be found in doc/GPL-license.txt in this distribution, or
 - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 - *
 - * There are special exceptions to the terms and conditions of the GPL as
 - * it is applied to this Source Code. View the full text of the exception
 - * in the file doc/FLOSS-exception.txt in this software distribution, or
 - * online at
 - * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 - *
 - * By copying, modifying or distributing this software, you acknowledge
 - * that you have read and understood your obligations described above,
 - * and agree to abide by those obligations.
 - *
 - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 - * COMPLETENESS OR PERFORMANCE.
 - * $/LicenseInfo$
 - */
 -
 -#if LL_WINDOWS
 -
 -#if LL_OS_DRAGDROP_ENABLED
 -
 -#ifndef LL_LLDRAGDROP32_H
 -#define LL_LLDRAGDROP32_H
 -
 -#include <windows.h>
 -#include <ole2.h>
 -
 -class LLDragDropWin32
 -{
 -	public:
 -		LLDragDropWin32();
 -		~LLDragDropWin32();
 -
 -		bool init( HWND hWnd );
 -		void reset();
 -
 -	private:
 -		IDropTarget* mDropTarget;
 -		HWND mDropWindowHandle;
 -};
 -#endif // LL_LLDRAGDROP32_H
 -
 -#else // LL_OS_DRAGDROP_ENABLED
 -
 -#ifndef LL_LLDRAGDROP32_H
 -#define LL_LLDRAGDROP32_H
 -
 -#include <windows.h>
 -#include <ole2.h>
 -
 -// imposter class that does nothing 
 -class LLDragDropWin32
 -{
 -	public:
 -		LLDragDropWin32() {};
 -		~LLDragDropWin32() {};
 -
 -		bool init( HWND hWnd ) { return false; };
 -		void reset() { };
 -};
 -#endif // LL_LLDRAGDROP32_H
 -
 -#endif // LL_OS_DRAGDROP_ENABLED
 -
 -#endif // LL_WINDOWS
 +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +class LLDragDropWin32 +{ +	public: +		LLDragDropWin32(); +		~LLDragDropWin32(); + +		bool init( HWND hWnd ); +		void reset(); + +	private: +		IDropTarget* mDropTarget; +		HWND mDropWindowHandle; +}; +#endif // LL_LLDRAGDROP32_H + +#else // LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +// imposter class that does nothing  +class LLDragDropWin32 +{ +	public: +		LLDragDropWin32() {}; +		~LLDragDropWin32() {}; + +		bool init( HWND hWnd ) { return false; }; +		void reset() { }; +}; +#endif // LL_LLDRAGDROP32_H + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index ed39786b37..57a4921d92 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1,3693 +1,3693 @@ -/** 
 - * @file llwindowwin32.cpp
 - * @brief Platform-dependent implementation of llwindow
 - *
 - * $LicenseInfo:firstyear=2001&license=viewergpl$
 - * 
 - * Copyright (c) 2001-2009, Linden Research, Inc.
 - * 
 - * Second Life Viewer Source Code
 - * The source code in this file ("Source Code") is provided by Linden Lab
 - * to you under the terms of the GNU General Public License, version 2.0
 - * ("GPL"), unless you have obtained a separate licensing agreement
 - * ("Other License"), formally executed by you and Linden Lab.  Terms of
 - * the GPL can be found in doc/GPL-license.txt in this distribution, or
 - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 - * 
 - * There are special exceptions to the terms and conditions of the GPL as
 - * it is applied to this Source Code. View the full text of the exception
 - * in the file doc/FLOSS-exception.txt in this software distribution, or
 - * online at
 - * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 - * 
 - * By copying, modifying or distributing this software, you acknowledge
 - * that you have read and understood your obligations described above,
 - * and agree to abide by those obligations.
 - * 
 - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 - * COMPLETENESS OR PERFORMANCE.
 - * $/LicenseInfo$
 - */
 -
 -#include "linden_common.h"
 -
 -#if LL_WINDOWS && !LL_MESA_HEADLESS
 -
 -#include "llwindowwin32.h"
 -
 -// LLWindow library includes
 -#include "llkeyboardwin32.h"
 -#include "lldragdropwin32.h"
 -#include "llpreeditor.h"
 -#include "llwindowcallbacks.h"
 -
 -// Linden library includes
 -#include "llerror.h"
 -#include "llgl.h"
 -#include "llstring.h"
 -
 -// System includes
 -#include <commdlg.h>
 -#include <WinUser.h>
 -#include <mapi.h>
 -#include <process.h>	// for _spawn
 -#include <shellapi.h>
 -#include <fstream>
 -#include <Imm.h>
 -
 -// Require DirectInput version 8
 -#define DIRECTINPUT_VERSION 0x0800
 -
 -#include <dinput.h>
 -#include <Dbt.h.>
 -
 -#include "llmemtype.h"
 -// culled from winuser.h
 -#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */
 -const S32	WM_MOUSEWHEEL = 0x020A;
 -#endif
 -#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */
 -const S32	WHEEL_DELTA = 120;     /* Value for rolling one detent */
 -#endif
 -const S32	MAX_MESSAGE_PER_UPDATE = 20;
 -const S32	BITS_PER_PIXEL = 32;
 -const S32	MAX_NUM_RESOLUTIONS = 32;
 -const F32	ICON_FLASH_TIME = 0.5f;
 -
 -extern BOOL gDebugWindowProc;
 -
 -LPWSTR gIconResource = IDI_APPLICATION;
 -
 -LLW32MsgCallback gAsyncMsgCallback = NULL;
 -
 -//
 -// LLWindowWin32
 -//
 -
 -void show_window_creation_error(const std::string& title)
 -{
 -	LL_WARNS("Window") << title << LL_ENDL;
 -}
 -
 -//static
 -BOOL LLWindowWin32::sIsClassRegistered = FALSE;
 -
 -BOOL	LLWindowWin32::sLanguageTextInputAllowed = TRUE;
 -BOOL	LLWindowWin32::sWinIMEOpened = FALSE;
 -HKL		LLWindowWin32::sWinInputLocale = 0;
 -DWORD	LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
 -DWORD	LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
 -LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
 -
 -// The following class LLWinImm delegates Windows IMM APIs.
 -// We need this because some language versions of Windows,
 -// e.g., US version of Windows XP, doesn't install IMM32.DLL
 -// as a default, and we can't link against imm32.lib statically.
 -// I believe DLL loading of this type is best suited to do
 -// in a static initialization of a class.  What I'm not sure is
 -// whether it follows the Linden Conding Standard... 
 -// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members
 -
 -class LLWinImm
 -{
 -public:
 -	static bool		isAvailable() { return sTheInstance.mHImmDll != NULL; }
 -
 -public:
 -	// Wrappers for IMM API.
 -	static BOOL		isIME(HKL hkl);															
 -	static HWND		getDefaultIMEWnd(HWND hwnd);
 -	static HIMC		getContext(HWND hwnd);													
 -	static BOOL		releaseContext(HWND hwnd, HIMC himc);
 -	static BOOL		getOpenStatus(HIMC himc);												
 -	static BOOL		setOpenStatus(HIMC himc, BOOL status);									
 -	static BOOL		getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);	
 -	static BOOL		setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);		
 -	static BOOL		getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 -	static BOOL		setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 -	static LONG		getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
 -	static BOOL		setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
 -	static BOOL		setCompositionFont(HIMC himc, LPLOGFONTW logfont);
 -	static BOOL		setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
 -	static BOOL		notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
 -
 -private:
 -	LLWinImm();
 -	~LLWinImm();
 -
 -private:
 -	// Pointers to IMM API.
 -	BOOL	 	(WINAPI *mImmIsIME)(HKL);
 -	HWND		(WINAPI *mImmGetDefaultIMEWnd)(HWND);
 -	HIMC		(WINAPI *mImmGetContext)(HWND);
 -	BOOL		(WINAPI *mImmReleaseContext)(HWND, HIMC);
 -	BOOL		(WINAPI *mImmGetOpenStatus)(HIMC);
 -	BOOL		(WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
 -	BOOL		(WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
 -	BOOL		(WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
 -	BOOL		(WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 -	BOOL		(WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 -	LONG		(WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD);
 -	BOOL		(WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD);
 -	BOOL		(WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW);
 -	BOOL		(WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM);
 -	BOOL		(WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
 -
 -private:
 -	HMODULE		mHImmDll;
 -	static LLWinImm sTheInstance;
 -};
 -
 -LLWinImm LLWinImm::sTheInstance;
 -
 -LLWinImm::LLWinImm() : mHImmDll(NULL)
 -{
 -	// Check system metrics 
 -	if ( !GetSystemMetrics( SM_DBCSENABLED ) )
 -		return;
 -	
 -
 -	mHImmDll = LoadLibraryA("Imm32");
 -	if (mHImmDll != NULL)
 -	{
 -		mImmIsIME               = (BOOL (WINAPI *)(HKL))                    GetProcAddress(mHImmDll, "ImmIsIME");
 -		mImmGetDefaultIMEWnd	= (HWND (WINAPI *)(HWND))					GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd");
 -		mImmGetContext          = (HIMC (WINAPI *)(HWND))                   GetProcAddress(mHImmDll, "ImmGetContext");
 -		mImmReleaseContext      = (BOOL (WINAPI *)(HWND, HIMC))             GetProcAddress(mHImmDll, "ImmReleaseContext");
 -		mImmGetOpenStatus       = (BOOL (WINAPI *)(HIMC))                   GetProcAddress(mHImmDll, "ImmGetOpenStatus");
 -		mImmSetOpenStatus       = (BOOL (WINAPI *)(HIMC, BOOL))             GetProcAddress(mHImmDll, "ImmSetOpenStatus");
 -		mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
 -		mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD))     GetProcAddress(mHImmDll, "ImmSetConversionStatus");
 -		mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmGetCompositionWindow");
 -		mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmSetCompositionWindow");
 -		mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD))					GetProcAddress(mHImmDll, "ImmGetCompositionStringW");
 -		mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD))	GetProcAddress(mHImmDll, "ImmSetCompositionStringW");
 -		mImmSetCompositionFont  = (BOOL (WINAPI *)(HIMC, LPLOGFONTW))		GetProcAddress(mHImmDll, "ImmSetCompositionFontW");
 -		mImmSetCandidateWindow  = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM))  GetProcAddress(mHImmDll, "ImmSetCandidateWindow");
 -		mImmNotifyIME			= (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD))	GetProcAddress(mHImmDll, "ImmNotifyIME");
 -
 -		if (mImmIsIME == NULL ||
 -			mImmGetDefaultIMEWnd == NULL ||
 -			mImmGetContext == NULL ||
 -			mImmReleaseContext == NULL ||
 -			mImmGetOpenStatus == NULL ||
 -			mImmSetOpenStatus == NULL ||
 -			mImmGetConversionStatus == NULL ||
 -			mImmSetConversionStatus == NULL ||
 -			mImmGetCompostitionWindow == NULL ||
 -			mImmSetCompostitionWindow == NULL ||
 -			mImmGetCompositionString == NULL ||
 -			mImmSetCompositionString == NULL ||
 -			mImmSetCompositionFont == NULL ||
 -			mImmSetCandidateWindow == NULL ||
 -			mImmNotifyIME == NULL)
 -		{
 -			// If any of the above API entires are not found, we can't use IMM API.  
 -			// So, turn off the IMM support.  We should log some warning message in 
 -			// the case, since it is very unusual; these APIs are available from 
 -			// the beginning, and all versions of IMM32.DLL should have them all.  
 -			// Unfortunately, this code may be executed before initialization of 
 -			// the logging channel (llwarns), and we can't do it here...  Yes, this 
 -			// is one of disadvantages to use static constraction to DLL loading. 
 -			FreeLibrary(mHImmDll);
 -			mHImmDll = NULL;
 -
 -			// If we unload the library, make sure all the function pointers are cleared
 -			mImmIsIME = NULL;
 -			mImmGetDefaultIMEWnd = NULL;
 -			mImmGetContext = NULL;
 -			mImmReleaseContext = NULL;
 -			mImmGetOpenStatus = NULL;
 -			mImmSetOpenStatus = NULL;
 -			mImmGetConversionStatus = NULL;
 -			mImmSetConversionStatus = NULL;
 -			mImmGetCompostitionWindow = NULL;
 -			mImmSetCompostitionWindow = NULL;
 -			mImmGetCompositionString = NULL;
 -			mImmSetCompositionString = NULL;
 -			mImmSetCompositionFont = NULL;
 -			mImmSetCandidateWindow = NULL;
 -			mImmNotifyIME = NULL;
 -		}
 -	}
 -}
 -
 -
 -// static 
 -BOOL	LLWinImm::isIME(HKL hkl)															
 -{ 
 -	if ( sTheInstance.mImmIsIME )
 -		return sTheInstance.mImmIsIME(hkl); 
 -	return FALSE;
 -}
 -
 -// static 
 -HIMC		LLWinImm::getContext(HWND hwnd)
 -{
 -	if ( sTheInstance.mImmGetContext )
 -		return sTheInstance.mImmGetContext(hwnd); 
 -	return 0;
 -}
 -
 -//static 
 -BOOL		LLWinImm::releaseContext(HWND hwnd, HIMC himc)
 -{ 
 -	if ( sTheInstance.mImmIsIME )
 -		return sTheInstance.mImmReleaseContext(hwnd, himc); 
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::getOpenStatus(HIMC himc)
 -{ 
 -	if ( sTheInstance.mImmGetOpenStatus )
 -		return sTheInstance.mImmGetOpenStatus(himc); 
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::setOpenStatus(HIMC himc, BOOL status)									
 -{ 
 -	if ( sTheInstance.mImmSetOpenStatus )
 -		return sTheInstance.mImmSetOpenStatus(himc, status); 
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)	
 -{ 
 -	if ( sTheInstance.mImmGetConversionStatus )
 -		return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); 
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)		
 -{ 
 -	if ( sTheInstance.mImmSetConversionStatus )
 -		return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); 
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 -{ 
 -	if ( sTheInstance.mImmGetCompostitionWindow )
 -		return sTheInstance.mImmGetCompostitionWindow(himc, form);	
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 -{ 
 -	if ( sTheInstance.mImmSetCompostitionWindow )
 -		return sTheInstance.mImmSetCompostitionWindow(himc, form);	
 -	return FALSE;
 -}
 -
 -
 -// static 
 -LONG		LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)					
 -{ 
 -	if ( sTheInstance.mImmGetCompositionString )
 -		return sTheInstance.mImmGetCompositionString(himc, index, data, length);	
 -	return FALSE;
 -}
 -
 -
 -// static 
 -BOOL		LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)					
 -{ 
 -	if ( sTheInstance.mImmSetCompositionString )
 -		return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);	
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)					
 -{ 
 -	if ( sTheInstance.mImmSetCompositionFont )
 -		return sTheInstance.mImmSetCompositionFont(himc, pFont);	
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)					
 -{ 
 -	if ( sTheInstance.mImmSetCandidateWindow )
 -		return sTheInstance.mImmSetCandidateWindow(himc, form);	
 -	return FALSE;
 -}
 -
 -// static 
 -BOOL		LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)					
 -{ 
 -	if ( sTheInstance.mImmNotifyIME )
 -		return sTheInstance.mImmNotifyIME(himc, action, index, value);	
 -	return FALSE;
 -}
 -
 -
 -
 -
 -// ----------------------------------------------------------------------------------------
 -LLWinImm::~LLWinImm()
 -{
 -	if (mHImmDll != NULL)
 -	{
 -		FreeLibrary(mHImmDll);
 -		mHImmDll = NULL;
 -	}
 -}
 -
 -
 -LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
 -							 const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
 -							 S32 height, U32 flags, 
 -							 BOOL fullscreen, BOOL clearBg,
 -							 BOOL disable_vsync, BOOL use_gl,
 -							 BOOL ignore_pixel_depth,
 -							 U32 fsaa_samples)
 -	: LLWindow(callbacks, fullscreen, flags)
 -{
 -	mFSAASamples = fsaa_samples;
 -	mIconResource = gIconResource;
 -	mOverrideAspectRatio = 0.f;
 -	mNativeAspectRatio = 0.f;
 -	mMousePositionModified = FALSE;
 -	mInputProcessingPaused = FALSE;
 -	mPreeditor = NULL;
 -	mhDC = NULL;
 -	mhRC = NULL;
 -
 -	// Initialize the keyboard
 -	gKeyboard = new LLKeyboardWin32();
 -	gKeyboard->setCallbacks(callbacks);
 -
 -	// Initialize the Drag and Drop functionality
 -	mDragDrop = new LLDragDropWin32;
 -
 -	// Initialize (boot strap) the Language text input management,
 -	// based on the system's (user's) default settings.
 -	allowLanguageTextInput(mPreeditor, FALSE);
 -
 -	WNDCLASS		wc;
 -	RECT			window_rect;
 -
 -	// Set the window title
 -	if (title.empty())
 -	{
 -		mWindowTitle = new WCHAR[50];
 -		wsprintf(mWindowTitle, L"OpenGL Window");
 -	}
 -	else
 -	{
 -		mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars.
 -		mbstowcs(mWindowTitle, title.c_str(), 255);
 -		mWindowTitle[255] = 0;
 -	}
 -
 -	// Set the window class name
 -	if (name.empty())
 -	{
 -		mWindowClassName = new WCHAR[50];
 -		wsprintf(mWindowClassName, L"OpenGL Window");
 -	}
 -	else
 -	{
 -		mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars.
 -		mbstowcs(mWindowClassName, name.c_str(), 255);
 -		mWindowClassName[255] = 0;
 -	}
 -
 -
 -	// We're not clipping yet
 -	SetRect( &mOldMouseClip, 0, 0, 0, 0 );
 -
 -	// Make an instance of our window then define the window class
 -	mhInstance = GetModuleHandle(NULL);
 -	mWndProc = NULL;
 -
 -	mSwapMethod = SWAP_METHOD_UNDEFINED;
 -
 -	// No WPARAM yet.
 -	mLastSizeWParam = 0;
 -
 -	// Windows GDI rects don't include rightmost pixel
 -	window_rect.left = (long) 0;
 -	window_rect.right = (long) width;
 -	window_rect.top = (long) 0;
 -	window_rect.bottom = (long) height;
 -
 -	// Grab screen size to sanitize the window
 -	S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
 -	S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN); 
 -	S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN); 
 -	S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 -	S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 -
 -	if (x < virtual_screen_x) x = virtual_screen_x;
 -	if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
 -
 -	if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
 -	if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
 -
 -	if (!sIsClassRegistered)
 -	{
 -		// Force redraw when resized and create a private device context
 -
 -		// Makes double click messages.
 -		wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
 -
 -		// Set message handler function
 -		wc.lpfnWndProc = (WNDPROC) mainWindowProc;
 -
 -		// unused
 -		wc.cbClsExtra = 0;
 -		wc.cbWndExtra = 0;
 -
 -		wc.hInstance = mhInstance;
 -		wc.hIcon = LoadIcon(mhInstance, mIconResource);
 -
 -		// We will set the cursor ourselves
 -		wc.hCursor = NULL;
 -
 -		// background color is not used
 -		if (clearBg)
 -		{
 -			wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
 -		}
 -		else
 -		{
 -			wc.hbrBackground = (HBRUSH) NULL;
 -		}
 -
 -		// we don't use windows menus
 -		wc.lpszMenuName = NULL;
 -
 -		wc.lpszClassName = mWindowClassName;
 -
 -		if (!RegisterClass(&wc))
 -		{
 -			OSMessageBox(mCallbacks->translateString("MBRegClassFailed"), 
 -				mCallbacks->translateString("MBError"), OSMB_OK);
 -			return;
 -		}
 -		sIsClassRegistered = TRUE;
 -	}
 -
 -	//-----------------------------------------------------------------------
 -	// Get the current refresh rate
 -	//-----------------------------------------------------------------------
 -
 -	DEVMODE dev_mode;
 -	DWORD current_refresh;
 -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 -	{
 -		current_refresh = dev_mode.dmDisplayFrequency;
 -		mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
 -	}
 -	else
 -	{
 -		current_refresh = 60;
 -	}
 -
 -	//-----------------------------------------------------------------------
 -	// Drop resolution and go fullscreen
 -	// use a display mode with our desired size and depth, with a refresh
 -	// rate as close at possible to the users' default
 -	//-----------------------------------------------------------------------
 -	if (mFullscreen)
 -	{
 -		BOOL success = FALSE;
 -		DWORD closest_refresh = 0;
 -
 -		for (S32 mode_num = 0;; mode_num++)
 -		{
 -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 -			{
 -				break;
 -			}
 -
 -			if (dev_mode.dmPelsWidth == width &&
 -				dev_mode.dmPelsHeight == height &&
 -				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 -			{
 -				success = TRUE;
 -				if ((dev_mode.dmDisplayFrequency - current_refresh)
 -					< (closest_refresh - current_refresh))
 -				{
 -					closest_refresh = dev_mode.dmDisplayFrequency;
 -				}
 -			}
 -		}
 -
 -		if (closest_refresh == 0)
 -		{
 -			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 -			success = FALSE;
 -		}
 -
 -		// If we found a good resolution, use it.
 -		if (success)
 -		{
 -			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 -		}
 -
 -		// Keep a copy of the actual current device mode in case we minimize 
 -		// and change the screen resolution.   JC
 -		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 -
 -		// If it failed, we don't want to run fullscreen
 -		if (success)
 -		{
 -			mFullscreen = TRUE;
 -			mFullscreenWidth   = dev_mode.dmPelsWidth;
 -			mFullscreenHeight  = dev_mode.dmPelsHeight;
 -			mFullscreenBits    = dev_mode.dmBitsPerPel;
 -			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 -
 -			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 -				<< "x"   << dev_mode.dmPelsHeight
 -				<< "x"   << dev_mode.dmBitsPerPel
 -				<< " @ " << dev_mode.dmDisplayFrequency
 -				<< LL_ENDL;
 -		}
 -		else
 -		{
 -			mFullscreen = FALSE;
 -			mFullscreenWidth   = -1;
 -			mFullscreenHeight  = -1;
 -			mFullscreenBits    = -1;
 -			mFullscreenRefresh = -1;
 -
 -			std::map<std::string,std::string> args;
 -			args["[WIDTH]"] = llformat("%d", width);
 -			args["[HEIGHT]"] = llformat ("%d", height);
 -			OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
 -				mCallbacks->translateString("MBError"), OSMB_OK);
 -		}
 -	}
 -
 -	// TODO: add this after resolving _WIN32_WINNT issue
 -	//	if (!fullscreen)
 -	//	{
 -	//		TRACKMOUSEEVENT track_mouse_event;
 -	//		track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
 -	//		track_mouse_event.dwFlags = TME_LEAVE;
 -	//		track_mouse_event.hwndTrack = mWindowHandle;
 -	//		track_mouse_event.dwHoverTime = HOVER_DEFAULT;
 -	//		TrackMouseEvent( &track_mouse_event ); 
 -	//	}
 -
 -
 -	//-----------------------------------------------------------------------
 -	// Create GL drawing context
 -	//-----------------------------------------------------------------------
 -	LLCoordScreen windowPos(x,y);
 -	LLCoordScreen windowSize(window_rect.right - window_rect.left,
 -							 window_rect.bottom - window_rect.top);
 -	if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos))
 -	{
 -		return;
 -	}
 -	
 -	//start with arrow cursor
 -	initCursors();
 -	setCursor( UI_CURSOR_ARROW );
 -
 -	// Initialize (boot strap) the Language text input management,
 -	// based on the system's (or user's) default settings.
 -	allowLanguageTextInput(NULL, FALSE);
 -}
 -
 -
 -LLWindowWin32::~LLWindowWin32()
 -{
 -	delete mDragDrop;
 -
 -	delete [] mWindowTitle;
 -	mWindowTitle = NULL;
 -
 -	delete [] mSupportedResolutions;
 -	mSupportedResolutions = NULL;
 -
 -	delete mWindowClassName;
 -	mWindowClassName = NULL;
 -}
 -
 -void LLWindowWin32::show()
 -{
 -	ShowWindow(mWindowHandle, SW_SHOW);
 -	SetForegroundWindow(mWindowHandle);
 -	SetFocus(mWindowHandle);
 -}
 -
 -void LLWindowWin32::hide()
 -{
 -	setMouseClipping(FALSE);
 -	ShowWindow(mWindowHandle, SW_HIDE);
 -}
 -
 -//virtual
 -void LLWindowWin32::minimize()
 -{
 -	setMouseClipping(FALSE);
 -	showCursor();
 -	ShowWindow(mWindowHandle, SW_MINIMIZE);
 -}
 -
 -//virtual
 -void LLWindowWin32::restore()
 -{
 -	ShowWindow(mWindowHandle, SW_RESTORE);
 -	SetForegroundWindow(mWindowHandle);
 -	SetFocus(mWindowHandle);
 -}
 -
 -
 -// close() destroys all OS-specific code associated with a window.
 -// Usually called from LLWindowManager::destroyWindow()
 -void LLWindowWin32::close()
 -{
 -	LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL;
 -	// Is window is already closed?
 -	if (!mWindowHandle)
 -	{
 -		return;
 -	}
 -
 -	mDragDrop->reset();
 -
 -	// Make sure cursor is visible and we haven't mangled the clipping state.
 -	setMouseClipping(FALSE);
 -	showCursor();
 -
 -	// Go back to screen mode written in the registry.
 -	if (mFullscreen)
 -	{
 -		resetDisplayResolution();
 -	}
 -
 -	// Clean up remaining GL state
 -	LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL;
 -	gGLManager.shutdownGL();
 -
 -	LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
 -	if (mhRC)
 -	{
 -		if (!wglMakeCurrent(NULL, NULL))
 -		{
 -			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 -		}
 -
 -		if (!wglDeleteContext(mhRC))
 -		{
 -			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 -		}
 -
 -		mhRC = NULL;
 -	}
 -
 -	// Restore gamma to the system values.
 -	restoreGamma();
 -
 -	if (mhDC && !ReleaseDC(mWindowHandle, mhDC))
 -	{
 -		LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL;
 -		mhDC = NULL;
 -	}
 -
 -	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
 -	
 -	// Don't process events in our mainWindowProc any longer.
 -	SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
 -
 -	// Make sure we don't leave a blank toolbar button.
 -	ShowWindow(mWindowHandle, SW_HIDE);
 -
 -	// This causes WM_DESTROY to be sent *immediately*
 -	if (!DestroyWindow(mWindowHandle))
 -	{
 -		OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
 -			mCallbacks->translateString("MBShutdownErr"),
 -			OSMB_OK);
 -	}
 -
 -	mWindowHandle = NULL;
 -}
 -
 -BOOL LLWindowWin32::isValid()
 -{
 -	return (mWindowHandle != NULL);
 -}
 -
 -BOOL LLWindowWin32::getVisible()
 -{
 -	return (mWindowHandle && IsWindowVisible(mWindowHandle));
 -}
 -
 -BOOL LLWindowWin32::getMinimized()
 -{
 -	return (mWindowHandle && IsIconic(mWindowHandle));
 -}
 -
 -BOOL LLWindowWin32::getMaximized()
 -{
 -	return (mWindowHandle && IsZoomed(mWindowHandle));
 -}
 -
 -BOOL LLWindowWin32::maximize()
 -{
 -	BOOL success = FALSE;
 -	if (!mWindowHandle) return success;
 -
 -	WINDOWPLACEMENT placement;
 -	placement.length = sizeof(WINDOWPLACEMENT);
 -
 -	success = GetWindowPlacement(mWindowHandle, &placement);
 -	if (!success) return success;
 -
 -	placement.showCmd = SW_MAXIMIZE;
 -
 -	success = SetWindowPlacement(mWindowHandle, &placement);
 -	return success;
 -}
 -
 -BOOL LLWindowWin32::getFullscreen()
 -{
 -	return mFullscreen;
 -}
 -
 -BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
 -{
 -	RECT window_rect;
 -
 -	if (!mWindowHandle ||
 -		!GetWindowRect(mWindowHandle, &window_rect) ||
 -		NULL == position)
 -	{
 -		return FALSE;
 -	}
 -
 -	position->mX = window_rect.left;
 -	position->mY = window_rect.top;
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::getSize(LLCoordScreen *size)
 -{
 -	RECT window_rect;
 -
 -	if (!mWindowHandle ||
 -		!GetWindowRect(mWindowHandle, &window_rect) ||
 -		NULL == size)
 -	{
 -		return FALSE;
 -	}
 -
 -	size->mX = window_rect.right - window_rect.left;
 -	size->mY = window_rect.bottom - window_rect.top;
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::getSize(LLCoordWindow *size)
 -{
 -	RECT client_rect;
 -
 -	if (!mWindowHandle ||
 -		!GetClientRect(mWindowHandle, &client_rect) ||
 -		NULL == size)
 -	{
 -		return FALSE;
 -	}
 -
 -	size->mX = client_rect.right - client_rect.left;
 -	size->mY = client_rect.bottom - client_rect.top;
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
 -{
 -	LLCoordScreen size;
 -
 -	if (!mWindowHandle)
 -	{
 -		return FALSE;
 -	}
 -	getSize(&size);
 -	moveWindow(position, size);
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::setSize(const LLCoordScreen size)
 -{
 -	LLCoordScreen position;
 -
 -	getPosition(&position);
 -	if (!mWindowHandle)
 -	{
 -		return FALSE;
 -	}
 -
 -	moveWindow(position, size);
 -	return TRUE;
 -}
 -
 -// changing fullscreen resolution
 -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
 -{
 -	GLuint	pixel_format;
 -	DEVMODE dev_mode;
 -	DWORD	current_refresh;
 -	DWORD	dw_ex_style;
 -	DWORD	dw_style;
 -	RECT	window_rect;
 -	S32 width = size.mX;
 -	S32 height = size.mY;
 -	BOOL auto_show = FALSE;
 -
 -	if (mhRC)
 -	{
 -		auto_show = TRUE;
 -		resetDisplayResolution();
 -	}
 -
 -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 -	{
 -		current_refresh = dev_mode.dmDisplayFrequency;
 -	}
 -	else
 -	{
 -		current_refresh = 60;
 -	}
 -
 -	gGLManager.shutdownGL();
 -	//destroy gl context
 -	if (mhRC)
 -	{
 -		if (!wglMakeCurrent(NULL, NULL))
 -		{
 -			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 -		}
 -
 -		if (!wglDeleteContext(mhRC))
 -		{
 -			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 -		}
 -
 -		mhRC = NULL;
 -	}
 -
 -	if (fullscreen)
 -	{
 -		mFullscreen = TRUE;
 -		BOOL success = FALSE;
 -		DWORD closest_refresh = 0;
 -
 -		for (S32 mode_num = 0;; mode_num++)
 -		{
 -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 -			{
 -				break;
 -			}
 -
 -			if (dev_mode.dmPelsWidth == width &&
 -				dev_mode.dmPelsHeight == height &&
 -				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 -			{
 -				success = TRUE;
 -				if ((dev_mode.dmDisplayFrequency - current_refresh)
 -					< (closest_refresh - current_refresh))
 -				{
 -					closest_refresh = dev_mode.dmDisplayFrequency;
 -				}
 -			}
 -		}
 -
 -		if (closest_refresh == 0)
 -		{
 -			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 -			return FALSE;
 -		}
 -
 -		// If we found a good resolution, use it.
 -		if (success)
 -		{
 -			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 -		}
 -
 -		// Keep a copy of the actual current device mode in case we minimize 
 -		// and change the screen resolution.   JC
 -		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 -
 -		if (success)
 -		{
 -			mFullscreen = TRUE;
 -			mFullscreenWidth   = dev_mode.dmPelsWidth;
 -			mFullscreenHeight  = dev_mode.dmPelsHeight;
 -			mFullscreenBits    = dev_mode.dmBitsPerPel;
 -			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 -
 -			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 -				<< "x"   << dev_mode.dmPelsHeight
 -				<< "x"   << dev_mode.dmBitsPerPel
 -				<< " @ " << dev_mode.dmDisplayFrequency
 -				<< LL_ENDL;
 -
 -			window_rect.left = (long) 0;
 -			window_rect.right = (long) width;			// Windows GDI rects don't include rightmost pixel
 -			window_rect.top = (long) 0;
 -			window_rect.bottom = (long) height;
 -			dw_ex_style = WS_EX_APPWINDOW;
 -			dw_style = WS_POPUP;
 -
 -			// Move window borders out not to cover window contents
 -			AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
 -		}
 -		// If it failed, we don't want to run fullscreen
 -		else
 -		{
 -			mFullscreen = FALSE;
 -			mFullscreenWidth   = -1;
 -			mFullscreenHeight  = -1;
 -			mFullscreenBits    = -1;
 -			mFullscreenRefresh = -1;
 -
 -			LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
 -			return FALSE;
 -		}
 -	}
 -	else
 -	{
 -		mFullscreen = FALSE;
 -		window_rect.left = (long) (posp ? posp->mX : 0);
 -		window_rect.right = (long) width + window_rect.left;			// Windows GDI rects don't include rightmost pixel
 -		window_rect.top = (long) (posp ? posp->mY : 0);
 -		window_rect.bottom = (long) height + window_rect.top;
 -		// Window with an edge
 -		dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
 -		dw_style = WS_OVERLAPPEDWINDOW;
 -	}
 -
 -	// don't post quit messages when destroying old windows
 -	mPostQuit = FALSE;
 -
 -	// create window
 -	DestroyWindow(mWindowHandle);
 -	mWindowHandle = CreateWindowEx(dw_ex_style,
 -		mWindowClassName,
 -		mWindowTitle,
 -		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
 -		window_rect.left,								// x pos
 -		window_rect.top,								// y pos
 -		window_rect.right - window_rect.left,			// width
 -		window_rect.bottom - window_rect.top,			// height
 -		NULL,
 -		NULL,
 -		mhInstance,
 -		NULL);
 -
 -	//-----------------------------------------------------------------------
 -	// Create GL drawing context
 -	//-----------------------------------------------------------------------
 -	static PIXELFORMATDESCRIPTOR pfd =
 -	{
 -		sizeof(PIXELFORMATDESCRIPTOR), 
 -			1,
 -			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
 -			PFD_TYPE_RGBA,
 -			BITS_PER_PIXEL,
 -			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused
 -			8,					// alpha bits
 -			0,					// alpha shift
 -			0,					// accum bits
 -			0, 0, 0, 0,			// accum RGBA
 -			24,					// depth bits
 -			8,					// stencil bits, avi added for stencil test
 -			0,
 -			PFD_MAIN_PLANE,
 -			0,
 -			0, 0, 0
 -	};
 -
 -	if (!(mhDC = GetDC(mWindowHandle)))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	// Verify what pixel format we actually received.
 -	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
 -		&pfd))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (pfd.cColorBits < 32)
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (pfd.cAlphaBits < 8)
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBAlpha"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!SetPixelFormat(mhDC, pixel_format, &pfd))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!(mhRC = wglCreateContext(mhDC)))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!wglMakeCurrent(mhDC, mhRC))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
 -			mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	gGLManager.initWGL();
 -
 -	if (wglChoosePixelFormatARB)
 -	{
 -		// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
 -		// can get exactly what we want.
 -		GLint attrib_list[256];
 -		S32 cur_attrib = 0;
 -
 -		attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
 -		attrib_list[cur_attrib++] = 24;
 -
 -		attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
 -		attrib_list[cur_attrib++] = 8;
 -
 -		attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
 -		attrib_list[cur_attrib++] = GL_TRUE;
 -
 -		attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
 -		attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
 -
 -		attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
 -		attrib_list[cur_attrib++] = GL_TRUE;
 -
 -		attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
 -		attrib_list[cur_attrib++] = GL_TRUE;
 -
 -		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
 -		attrib_list[cur_attrib++] = 24;
 -
 -		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
 -		attrib_list[cur_attrib++] = 8;
 -
 -		U32 end_attrib = 0;
 -		if (mFSAASamples > 0)
 -		{
 -			end_attrib = cur_attrib;
 -			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
 -			attrib_list[cur_attrib++] = GL_TRUE;
 -
 -			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
 -			attrib_list[cur_attrib++] = mFSAASamples;
 -		}
 -
 -		// End the list
 -		attrib_list[cur_attrib++] = 0;
 -
 -		GLint pixel_formats[256];
 -		U32 num_formats = 0;
 -
 -		// First we try and get a 32 bit depth pixel format
 -		BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 -		if (!result)
 -		{
 -			close();
 -			show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
 -			return FALSE;
 -		}
 -
 -		if (!num_formats)
 -		{
 -			if (end_attrib > 0)
 -			{
 -				LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL;
 -				attrib_list[end_attrib] = 0;
 -
 -				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 -				if (!result)
 -				{
 -					close();
 -					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
 -					return FALSE;
 -				}
 -			}
 -
 -			if (!num_formats)
 -			{
 -				LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL;
 -				// Try 24-bit format
 -				attrib_list[1] = 24;
 -				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 -				if (!result)
 -				{
 -					close();
 -					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
 -					return FALSE;
 -				}
 -
 -				if (!num_formats)
 -				{
 -					LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL;
 -					attrib_list[1] = 16;
 -					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 -					if (!result || !num_formats)
 -					{
 -						close();
 -						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
 -						return FALSE;
 -					}
 -				}
 -			}
 -
 -			LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL;
 -		}
 -
 -		
 -
 -		S32 swap_method = 0;
 -		S32 cur_format = num_formats-1;
 -		GLint swap_query = WGL_SWAP_METHOD_ARB;
 -
 -		BOOL found_format = FALSE;
 -
 -		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
 -		{
 -			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0)
 -			{
 -				found_format = TRUE;
 -			}
 -			else
 -			{
 -				--cur_format;
 -			}
 -		}
 -		
 -		pixel_format = pixel_formats[cur_format];
 -		
 -		if (mhDC != 0)											// Does The Window Have A Device Context?
 -		{
 -			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero
 -			if (mhRC != 0)										// Does The Window Have A Rendering Context?
 -			{
 -				wglDeleteContext (mhRC);							// Release The Rendering Context
 -				mhRC = 0;										// Zero The Rendering Context
 -
 -			}
 -			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context
 -			mhDC = 0;											// Zero The Device Context
 -		}
 -		DestroyWindow (mWindowHandle);									// Destroy The Window
 -		
 -
 -		mWindowHandle = CreateWindowEx(dw_ex_style,
 -			mWindowClassName,
 -			mWindowTitle,
 -			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
 -			window_rect.left,								// x pos
 -			window_rect.top,								// y pos
 -			window_rect.right - window_rect.left,			// width
 -			window_rect.bottom - window_rect.top,			// height
 -			NULL,
 -			NULL,
 -			mhInstance,
 -			NULL);
 -
 -		if (!(mhDC = GetDC(mWindowHandle)))
 -		{
 -			close();
 -			OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 -			return FALSE;
 -		}
 -
 -		if (!SetPixelFormat(mhDC, pixel_format, &pfd))
 -		{
 -			close();
 -			OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
 -				mCallbacks->translateString("MBError"), OSMB_OK);
 -			return FALSE;
 -		}
 -
 -		if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
 -		{
 -			switch (swap_method)
 -			{
 -			case WGL_SWAP_EXCHANGE_ARB:
 -				mSwapMethod = SWAP_METHOD_EXCHANGE;
 -				LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL;
 -				break;
 -			case WGL_SWAP_COPY_ARB:
 -				mSwapMethod = SWAP_METHOD_COPY;
 -				LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL;
 -				break;
 -			case WGL_SWAP_UNDEFINED_ARB:
 -				mSwapMethod = SWAP_METHOD_UNDEFINED;
 -				LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL;
 -				break;
 -			default:
 -				mSwapMethod = SWAP_METHOD_UNDEFINED;
 -				LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL;
 -				break;
 -			}
 -		}		
 -	}
 -	else
 -	{
 -		LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
 -	}
 -
 -	// Verify what pixel format we actually received.
 -	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
 -		&pfd))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits) 
 -		<< " Alpha Bits " << S32(pfd.cAlphaBits)
 -		<< " Depth Bits " << S32(pfd.cDepthBits) 
 -		<< LL_ENDL;
 -
 -	// make sure we have 32 bits per pixel
 -	if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32)
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (pfd.cAlphaBits < 8)
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!(mhRC = wglCreateContext(mhDC)))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!wglMakeCurrent(mhDC, mhRC))
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	if (!gGLManager.initGL())
 -	{
 -		close();
 -		OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 -		return FALSE;
 -	}
 -
 -	// Disable vertical sync for swap
 -	if (disable_vsync && wglSwapIntervalEXT)
 -	{
 -		LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL;
 -		wglSwapIntervalEXT(0);
 -	}
 -	else
 -	{
 -		LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
 -	}
 -
 -	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
 -
 -	// register this window as handling drag/drop events from the OS
 -	DragAcceptFiles( mWindowHandle, TRUE );
 -
 -	mDragDrop->init( mWindowHandle );
 -	
 -	//register joystick timer callback
 -	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
 -
 -	// ok to post quit messages now
 -	mPostQuit = TRUE;
 -
 -	if (auto_show)
 -	{
 -		show();
 -		glClearColor(0.0f, 0.0f, 0.0f, 0.f);
 -		glClear(GL_COLOR_BUFFER_BIT);
 -		swapBuffers();
 -	}
 -
 -	return TRUE;
 -}
 -
 -void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
 -{
 -	if( mIsMouseClipping )
 -	{
 -		RECT client_rect_in_screen_space;
 -		if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
 -		{
 -			ClipCursor( &client_rect_in_screen_space );
 -		}
 -	}
 -
 -	// if the window was already maximized, MoveWindow seems to still set the maximized flag even if
 -	// the window is smaller than maximized.
 -	// So we're going to do a restore first (which is a ShowWindow call) (SL-44655).
 -
 -	// THIS CAUSES DEV-15484 and DEV-15949 
 -	//ShowWindow(mWindowHandle, SW_RESTORE);
 -	// NOW we can call MoveWindow
 -	MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE);
 -}
 -
 -BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
 -{
 -	LLCoordScreen screen_pos;
 -
 -	mMousePositionModified = TRUE;
 -	if (!mWindowHandle)
 -	{
 -		return FALSE;
 -	}
 -
 -	if (!convertCoords(position, &screen_pos))
 -	{
 -		return FALSE;
 -	}
 -
 -	// Inform the application of the new mouse position (needed for per-frame
 -	// hover/picking to function).
 -	LLCoordGL gl_pos;
 -	convertCoords(position, &gl_pos);
 -	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
 -	
 -	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
 -	// Because we have preemptively notified the application of the new
 -	// mouse position via handleMouseMove() above, we need to clear out
 -	// any stale mouse move events.  RN/JC
 -	MSG msg;
 -	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
 -	{ }
 -
 -	return SetCursorPos(screen_pos.mX, screen_pos.mY);
 -}
 -
 -BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
 -{
 -	POINT cursor_point;
 -	LLCoordScreen screen_pos;
 -
 -	if (!mWindowHandle ||
 -		!GetCursorPos(&cursor_point))
 -	{
 -		return FALSE;
 -	}
 -
 -	screen_pos.mX = cursor_point.x;
 -	screen_pos.mY = cursor_point.y;
 -
 -	return convertCoords(screen_pos, position);
 -}
 -
 -void LLWindowWin32::hideCursor()
 -{
 -	while (ShowCursor(FALSE) >= 0)
 -	{
 -		// nothing, wait for cursor to push down
 -	}
 -	mCursorHidden = TRUE;
 -	mHideCursorPermanent = TRUE;
 -}
 -
 -void LLWindowWin32::showCursor()
 -{
 -	// makes sure the cursor shows up
 -	while (ShowCursor(TRUE) < 0)
 -	{
 -		// do nothing, wait for cursor to pop out
 -	}
 -	mCursorHidden = FALSE;
 -	mHideCursorPermanent = FALSE;
 -}
 -
 -void LLWindowWin32::showCursorFromMouseMove()
 -{
 -	if (!mHideCursorPermanent)
 -	{
 -		showCursor();
 -	}
 -}
 -
 -void LLWindowWin32::hideCursorUntilMouseMove()
 -{
 -	if (!mHideCursorPermanent)
 -	{
 -		hideCursor();
 -		mHideCursorPermanent = FALSE;
 -	}
 -}
 -
 -BOOL LLWindowWin32::isCursorHidden()
 -{
 -	return mCursorHidden;
 -}
 -
 -
 -HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name)
 -{
 -	return (HCURSOR)LoadImage(mhInstance,
 -							  name,
 -							  IMAGE_CURSOR,
 -							  0,	// default width
 -							  0,	// default height
 -							  LR_DEFAULTCOLOR);
 -}
 -
 -
 -void LLWindowWin32::initCursors()
 -{
 -	mCursor[ UI_CURSOR_ARROW ]		= LoadCursor(NULL, IDC_ARROW);
 -	mCursor[ UI_CURSOR_WAIT ]		= LoadCursor(NULL, IDC_WAIT);
 -	mCursor[ UI_CURSOR_HAND ]		= LoadCursor(NULL, IDC_HAND);
 -	mCursor[ UI_CURSOR_IBEAM ]		= LoadCursor(NULL, IDC_IBEAM);
 -	mCursor[ UI_CURSOR_CROSS ]		= LoadCursor(NULL, IDC_CROSS);
 -	mCursor[ UI_CURSOR_SIZENWSE ]	= LoadCursor(NULL, IDC_SIZENWSE);
 -	mCursor[ UI_CURSOR_SIZENESW ]	= LoadCursor(NULL, IDC_SIZENESW);
 -	mCursor[ UI_CURSOR_SIZEWE ]		= LoadCursor(NULL, IDC_SIZEWE);  
 -	mCursor[ UI_CURSOR_SIZENS ]		= LoadCursor(NULL, IDC_SIZENS);  
 -	mCursor[ UI_CURSOR_NO ]			= LoadCursor(NULL, IDC_NO);
 -	mCursor[ UI_CURSOR_WORKING ]	= LoadCursor(NULL, IDC_APPSTARTING); 
 -
 -	HMODULE module = GetModuleHandle(NULL);
 -	mCursor[ UI_CURSOR_TOOLGRAB ]	= LoadCursor(module, TEXT("TOOLGRAB"));
 -	mCursor[ UI_CURSOR_TOOLLAND ]	= LoadCursor(module, TEXT("TOOLLAND"));
 -	mCursor[ UI_CURSOR_TOOLFOCUS ]	= LoadCursor(module, TEXT("TOOLFOCUS"));
 -	mCursor[ UI_CURSOR_TOOLCREATE ]	= LoadCursor(module, TEXT("TOOLCREATE"));
 -	mCursor[ UI_CURSOR_ARROWDRAG ]	= LoadCursor(module, TEXT("ARROWDRAG"));
 -	mCursor[ UI_CURSOR_ARROWCOPY ]	= LoadCursor(module, TEXT("ARROWCOPY"));
 -	mCursor[ UI_CURSOR_ARROWDRAGMULTI ]	= LoadCursor(module, TEXT("ARROWDRAGMULTI"));
 -	mCursor[ UI_CURSOR_ARROWCOPYMULTI ]	= LoadCursor(module, TEXT("ARROWCOPYMULTI"));
 -	mCursor[ UI_CURSOR_NOLOCKED ]	= LoadCursor(module, TEXT("NOLOCKED"));
 -	mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
 -	mCursor[ UI_CURSOR_GRABLOCKED ]	= LoadCursor(module, TEXT("GRABLOCKED"));
 -	mCursor[ UI_CURSOR_TOOLTRANSLATE ]	= LoadCursor(module, TEXT("TOOLTRANSLATE"));
 -	mCursor[ UI_CURSOR_TOOLROTATE ]	= LoadCursor(module, TEXT("TOOLROTATE")); 
 -	mCursor[ UI_CURSOR_TOOLSCALE ]	= LoadCursor(module, TEXT("TOOLSCALE"));
 -	mCursor[ UI_CURSOR_TOOLCAMERA ]	= LoadCursor(module, TEXT("TOOLCAMERA"));
 -	mCursor[ UI_CURSOR_TOOLPAN ]	= LoadCursor(module, TEXT("TOOLPAN"));
 -	mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
 -	mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
 -	mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
 -
 -	// Color cursors
 -	mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY"));
 -	mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE"));
 -	mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
 -
 -	// Note: custom cursors that are not found make LoadCursor() return NULL.
 -	for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
 -	{
 -		if( !mCursor[i] )
 -		{
 -			mCursor[i] = LoadCursor(NULL, IDC_ARROW);
 -		}
 -	}
 -}
 -
 -
 -
 -void LLWindowWin32::setCursor(ECursorType cursor)
 -{
 -	if (cursor == UI_CURSOR_ARROW
 -		&& mBusyCount > 0)
 -	{
 -		cursor = UI_CURSOR_WORKING;
 -	}
 -
 -	if( mCurrentCursor != cursor )
 -	{
 -		mCurrentCursor = cursor;
 -		SetCursor( mCursor[cursor] );
 -	}
 -}
 -
 -ECursorType LLWindowWin32::getCursor() const
 -{
 -	return mCurrentCursor;
 -}
 -
 -void LLWindowWin32::captureMouse()
 -{
 -	SetCapture(mWindowHandle);
 -}
 -
 -void LLWindowWin32::releaseMouse()
 -{
 -	// *NOTE:Mani ReleaseCapture will spawn new windows messages...
 -	// which will in turn call our MainWindowProc. It therefore requires
 -	// pausing *and more importantly resumption* of the mainlooptimeout...
 -	// just like DispatchMessage below.
 -	mCallbacks->handlePauseWatchdog(this);
 -	ReleaseCapture();
 -	mCallbacks->handleResumeWatchdog(this);
 -}
 -
 -
 -void LLWindowWin32::delayInputProcessing()
 -{
 -	mInputProcessingPaused = TRUE;
 -}
 -
 -void LLWindowWin32::gatherInput()
 -{
 -	MSG		msg;
 -	int		msg_count = 0;
 -
 -	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT);
 -
 -	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
 -	{
 -		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
 -		TranslateMessage(&msg);
 -
 -		// turn watchdog off in here to not fail if windows is doing something wacky
 -		mCallbacks->handlePauseWatchdog(this);
 -		DispatchMessage(&msg);
 -		mCallbacks->handleResumeWatchdog(this);
 -		msg_count++;
 -
 -		if ( mInputProcessingPaused )
 -		{
 -			break;
 -		}
 -		/* Attempted workaround for problem where typing fast and hitting
 -		   return would result in only part of the text being sent. JC
 -
 -		BOOL key_posted = TranslateMessage(&msg);
 -		DispatchMessage(&msg);
 -		msg_count++;
 -
 -		// If a key was translated, a WM_CHAR might have been posted to the end
 -		// of the event queue.  We need it immediately.
 -		if (key_posted && msg.message == WM_KEYDOWN)
 -		{
 -			if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE))
 -			{
 -				TranslateMessage(&msg);
 -				DispatchMessage(&msg);
 -				msg_count++;
 -			}
 -		}
 -		*/
 -		mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput");
 -		// For async host by name support.  Really hacky.
 -		if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message))
 -		{
 -			gAsyncMsgCallback(msg);
 -		}
 -	}
 -
 -	mInputProcessingPaused = FALSE;
 -
 -	// clear this once we've processed all mouse messages that might have occurred after
 -	// we slammed the mouse position
 -	mMousePositionModified = FALSE;
 -}
 -
 -static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard");
 -static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse");
 -
 -LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
 -{
 -	LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
 -
 -
 -	if (NULL != window_imp)
 -	{
 -		window_imp->mCallbacks->handleResumeWatchdog(window_imp);
 -		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc");
 -		// Has user provided their own window callback?
 -		if (NULL != window_imp->mWndProc)
 -		{
 -			if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param))
 -			{
 -				// user has handled window message
 -				return 0;
 -			}
 -		}
 -
 -		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc");
 -		
 -		// Juggle to make sure we can get negative positions for when
 -		// mouse is outside window.
 -		LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param));
 -
 -		// This doesn't work, as LOWORD returns unsigned short.
 -		//LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param));
 -		LLCoordGL gl_coord;
 -
 -		// pass along extended flag in mask
 -		MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0;
 -		BOOL eat_keystroke = TRUE;
 -
 -		switch(u_msg)
 -		{
 -			RECT	update_rect;
 -			S32		update_width;
 -			S32		update_height;
 -
 -		case WM_TIMER:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER");
 -			window_imp->mCallbacks->handleTimerEvent(window_imp);
 -			break;
 -
 -		case WM_DEVICECHANGE:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "  WM_DEVICECHANGE: wParam=" << w_param 
 -						<< "; lParam=" << l_param << llendl;
 -			}
 -			if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL)
 -			{
 -				if (window_imp->mCallbacks->handleDeviceChange(window_imp))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_PAINT:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT");
 -			GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE);
 -			update_width = update_rect.right - update_rect.left + 1;
 -			update_height = update_rect.bottom - update_rect.top + 1;
 -			window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top,
 -				update_width, update_height);
 -			break;
 -		case WM_PARENTNOTIFY:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY");
 -			u_msg = u_msg;
 -			break;
 -
 -		case WM_SETCURSOR:
 -			// This message is sent whenever the cursor is moved in a window.
 -			// You need to set the appropriate cursor appearance.
 -
 -			// Only take control of cursor over client region of window
 -			// This allows Windows(tm) to handle resize cursors, etc.
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR");
 -			if (LOWORD(l_param) == HTCLIENT)
 -			{
 -				SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] );
 -				return 0;
 -			}
 -			break;
 -
 -		case WM_ENTERMENULOOP:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP");
 -			window_imp->mCallbacks->handleWindowBlock(window_imp);
 -			break;
 -
 -		case WM_EXITMENULOOP:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP");
 -			window_imp->mCallbacks->handleWindowUnblock(window_imp);
 -			break;
 -
 -		case WM_ACTIVATEAPP:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP");
 -			{
 -				// This message should be sent whenever the app gains or loses focus.
 -				BOOL activating = (BOOL) w_param;
 -				BOOL minimized = window_imp->getMinimized();
 -
 -				if (gDebugWindowProc)
 -				{
 -					LL_INFOS("Window") << "WINDOWPROC ActivateApp "
 -						<< " activating " << S32(activating)
 -						<< " minimized " << S32(minimized)
 -						<< " fullscreen " << S32(window_imp->mFullscreen)
 -						<< LL_ENDL;
 -				}
 -
 -				if (window_imp->mFullscreen)
 -				{
 -					// When we run fullscreen, restoring or minimizing the app needs 
 -					// to switch the screen resolution
 -					if (activating)
 -					{
 -						window_imp->setFullscreenResolution();
 -						window_imp->restore();
 -					}
 -					else
 -					{
 -						window_imp->minimize();
 -						window_imp->resetDisplayResolution();
 -					}
 -				}
 -
 -				window_imp->mCallbacks->handleActivateApp(window_imp, activating);
 -
 -				break;
 -			}
 -
 -		case WM_ACTIVATE:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE");
 -			{
 -				// Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE
 -				BOOL activating = (LOWORD(w_param) != WA_INACTIVE);
 -
 -				BOOL minimized = BOOL(HIWORD(w_param));
 -
 -				if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor)
 -				{
 -					window_imp->interruptLanguageTextInput();
 -				}
 -
 -				// JC - I'm not sure why, but if we don't report that we handled the 
 -				// WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work 
 -				// properly when we run fullscreen.
 -				if (gDebugWindowProc)
 -				{
 -					LL_INFOS("Window") << "WINDOWPROC Activate "
 -						<< " activating " << S32(activating) 
 -						<< " minimized " << S32(minimized)
 -						<< LL_ENDL;
 -				}
 -
 -				// Don't handle this.
 -				break;
 -			}
 -
 -		case WM_QUERYOPEN:
 -			// TODO: use this to return a nice icon
 -			break;
 -
 -		case WM_SYSCOMMAND:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND");
 -			switch(w_param)
 -			{
 -			case SC_KEYMENU: 
 -				// Disallow the ALT key from triggering the default system menu.
 -				return 0;		
 -
 -			case SC_SCREENSAVE:
 -			case SC_MONITORPOWER:
 -				// eat screen save messages and prevent them!
 -				return 0;
 -			}
 -			break;
 -
 -		case WM_CLOSE:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE");
 -			// Will the app allow the window to close?
 -			if (window_imp->mCallbacks->handleCloseRequest(window_imp))
 -			{
 -				// Get the app to initiate cleanup.
 -				window_imp->mCallbacks->handleQuit(window_imp);
 -				// The app is responsible for calling destroyWindow when done with GL
 -			}
 -			return 0;
 -
 -		case WM_DESTROY:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY");
 -			if (window_imp->shouldPostQuit())
 -			{
 -				PostQuitMessage(0);  // Posts WM_QUIT with an exit code of 0
 -			}
 -			return 0;
 -
 -		case WM_COMMAND:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND");
 -			if (!HIWORD(w_param)) // this message is from a menu
 -			{
 -				window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param));
 -			}
 -			break;
 -
 -		case WM_SYSKEYDOWN:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN");
 -			// allow system keys, such as ALT-F4 to be processed by Windows
 -			eat_keystroke = FALSE;
 -		case WM_KEYDOWN:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN");
 -			{
 -				if (gDebugWindowProc)
 -				{
 -					LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN "
 -						<< " key " << S32(w_param) 
 -						<< LL_ENDL;
 -				}
 -				if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke)
 -				{
 -					return 0;
 -				}
 -				// pass on to windows if we didn't handle it
 -				break;
 -			}
 -		case WM_SYSKEYUP:
 -			eat_keystroke = FALSE;
 -		case WM_KEYUP:
 -		{
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
 -			LLFastTimer t2(FTM_KEYHANDLER);
 -
 -			if (gDebugWindowProc)
 -			{
 -				LL_INFOS("Window") << "Debug WindowProc WM_KEYUP "
 -					<< " key " << S32(w_param) 
 -					<< LL_ENDL;
 -			}
 -			if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke)
 -			{
 -				return 0;
 -			}
 -
 -			// pass on to windows
 -			break;
 -		}
 -		case WM_IME_SETCONTEXT:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "WM_IME_SETCONTEXT" << llendl;
 -			}
 -			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -			{
 -				l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW;
 -				// Invoke DefWinProc with the modified LPARAM.
 -			}
 -			break;
 -
 -		case WM_IME_STARTCOMPOSITION:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "WM_IME_STARTCOMPOSITION" << llendl;
 -			}
 -			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -			{
 -				window_imp->handleStartCompositionMessage();
 -				return 0;
 -			}
 -			break;
 -
 -		case WM_IME_ENDCOMPOSITION:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "WM_IME_ENDCOMPOSITION" << llendl;
 -			}
 -			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -			{
 -				return 0;
 -			}
 -			break;
 -
 -		case WM_IME_COMPOSITION:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "WM_IME_COMPOSITION" << llendl;
 -			}
 -			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -			{
 -				window_imp->handleCompositionMessage(l_param);
 -				return 0;
 -			}
 -			break;
 -
 -		case WM_IME_REQUEST:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST");
 -			if (gDebugWindowProc)
 -			{
 -				llinfos << "WM_IME_REQUEST" << llendl;
 -			}
 -			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -			{
 -				LRESULT result = 0;
 -				if (window_imp->handleImeRequests(w_param, l_param, &result))
 -				{
 -					return result;
 -				}
 -			}
 -			break;
 -
 -		case WM_CHAR:
 -			// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
 -			// to figure out how that works. - Doug
 -			//
 -			// ... Well, I don't think so.
 -			// How it works is explained in Win32 API document, but WM_UNICHAR didn't work
 -			// as specified at least on Windows XP SP1 Japanese version.  I have never used
 -			// it since then, and I'm not sure whether it has been fixed now, but I don't think
 -			// it is worth trying.  The good old WM_CHAR works just fine even for supplementary
 -			// characters.  We just need to take care of surrogate pairs sent as two WM_CHAR's
 -			// by ourselves.  It is not that tough.  -- Alissa Sabre @ SL
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR");
 -			if (gDebugWindowProc)
 -			{
 -				LL_INFOS("Window") << "Debug WindowProc WM_CHAR "
 -					<< " key " << S32(w_param) 
 -					<< LL_ENDL;
 -			}
 -			// Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE,
 -			// we *did* processed the event, so I believe we should not pass it to DefWindowProc...
 -			window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
 -			return 0;
 -
 -		case WM_LBUTTONDOWN:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -				{
 -					window_imp->interruptLanguageTextInput();
 -				}
 -
 -				// Because we move the cursor position in the app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_LBUTTONDBLCLK:
 -		//RN: ignore right button double clicks for now
 -		//case WM_RBUTTONDBLCLK:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK");
 -				// Because we move the cursor position in the app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) )
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_LBUTTONUP:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				//if (gDebugClicks)
 -				//{
 -				//	LL_INFOS("Window") << "WndProc left button up" << LL_ENDL;
 -				//}
 -				// Because we move the cursor position in the app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_RBUTTONDBLCLK:
 -		case WM_RBUTTONDOWN:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -				{
 -					window_imp->interruptLanguageTextInput();
 -				}
 -
 -				// Because we move the cursor position in the llviewerapp, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_RBUTTONUP:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				// Because we move the cursor position in the app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_MBUTTONDOWN:
 -//		case WM_MBUTTONDBLCLK:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 -				{
 -					window_imp->interruptLanguageTextInput();
 -				}
 -
 -				// Because we move the cursor position in tllviewerhe app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_MBUTTONUP:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP");
 -				LLFastTimer t2(FTM_MOUSEHANDLER);
 -				// Because we move the cursor position in the llviewer app, we need to query
 -				// to find out where the cursor at the time the event is handled.
 -				// If we don't do this, many clicks could get buffered up, and if the
 -				// first click changes the cursor position, all subsequent clicks
 -				// will occur at the wrong location.  JC
 -				LLCoordWindow cursor_coord_window;
 -				if (window_imp->mMousePositionModified)
 -				{
 -					window_imp->getCursorPosition(&cursor_coord_window);
 -					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 -				}
 -				else
 -				{
 -					window_imp->convertCoords(window_coord, &gl_coord);
 -				}
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				// generate move event to update mouse coordinates
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask))
 -				{
 -					return 0;
 -				}
 -			}
 -			break;
 -
 -		case WM_MOUSEWHEEL:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL");
 -				static short z_delta = 0;
 -
 -				RECT	client_rect;
 -
 -				// eat scroll events that occur outside our window, since we use mouse position to direct scroll
 -				// instead of keyboard focus
 -				// NOTE: mouse_coord is in *window* coordinates for scroll events
 -				POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)};
 -
 -				if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord)
 -					&& GetClientRect(window_imp->mWindowHandle, &client_rect))
 -				{
 -					// we have a valid mouse point and client rect
 -					if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x
 -						|| mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y)
 -					{
 -						// mouse is outside of client rect, so don't do anything
 -						return 0;
 -					}
 -				}
 -
 -				S16 incoming_z_delta = HIWORD(w_param);
 -				z_delta += incoming_z_delta;
 -				// cout << "z_delta " << z_delta << endl;
 -
 -				// current mouse wheels report changes in increments of zDelta (+120, -120)
 -				// Future, higher resolution mouse wheels may report smaller deltas.
 -				// So we sum the deltas and only act when we've exceeded WHEEL_DELTA
 -				//
 -				// If the user rapidly spins the wheel, we can get messages with
 -				// large deltas, like 480 or so.  Thus we need to scroll more quickly.
 -				if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta)
 -				{
 -					window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA);
 -					z_delta = 0;
 -				}
 -				return 0;
 -			}
 -			/*
 -			// TODO: add this after resolving _WIN32_WINNT issue
 -			case WM_MOUSELEAVE:
 -			{
 -			window_imp->mCallbacks->handleMouseLeave(window_imp);
 -
 -			//				TRACKMOUSEEVENT track_mouse_event;
 -			//				track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
 -			//				track_mouse_event.dwFlags = TME_LEAVE;
 -			//				track_mouse_event.hwndTrack = h_wnd;
 -			//				track_mouse_event.dwHoverTime = HOVER_DEFAULT;
 -			//				TrackMouseEvent( &track_mouse_event ); 
 -			return 0;
 -			}
 -			*/
 -			// Handle mouse movement within the window
 -		case WM_MOUSEMOVE:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE");
 -				window_imp->convertCoords(window_coord, &gl_coord);
 -				MASK mask = gKeyboard->currentMask(TRUE);
 -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 -				return 0;
 -			}
 -
 -		case WM_SIZE:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE");
 -				S32 width = S32( LOWORD(l_param) );
 -				S32 height = S32( HIWORD(l_param) );
 -
 -				if (gDebugWindowProc)
 -				{
 -					BOOL maximized = ( w_param == SIZE_MAXIMIZED );
 -					BOOL restored  = ( w_param == SIZE_RESTORED );
 -					BOOL minimized = ( w_param == SIZE_MINIMIZED );
 -
 -					LL_INFOS("Window") << "WINDOWPROC Size "
 -						<< width << "x" << height
 -						<< " max " << S32(maximized)
 -						<< " min " << S32(minimized)
 -						<< " rest " << S32(restored)
 -						<< LL_ENDL;
 -				}
 -
 -				// There's an odd behavior with WM_SIZE that I would call a bug. If 
 -				// the window is maximized, and you call MoveWindow() with a size smaller
 -				// than a maximized window, it ends up sending WM_SIZE with w_param set 
 -				// to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work.
 -				// (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see 
 -				// LLWindowWin32::moveWindow in this file). 
 -
 -				// If we are now restored, but we weren't before, this
 -				// means that the window was un-minimized.
 -				if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED)
 -				{
 -					window_imp->mCallbacks->handleActivate(window_imp, TRUE);
 -				}
 -
 -				// handle case of window being maximized from fully minimized state
 -				if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED)
 -				{
 -					window_imp->mCallbacks->handleActivate(window_imp, TRUE);
 -				}
 -
 -				// Also handle the minimization case
 -				if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED)
 -				{
 -					window_imp->mCallbacks->handleActivate(window_imp, FALSE);
 -				}
 -
 -				// Actually resize all of our views
 -				if (w_param != SIZE_MINIMIZED)
 -				{
 -					// Ignore updates for minimizing and minimized "windows"
 -					window_imp->mCallbacks->handleResize(	window_imp, 
 -						LOWORD(l_param), 
 -						HIWORD(l_param) );
 -				}
 -
 -				window_imp->mLastSizeWParam = w_param;
 -
 -				return 0;
 -			}
 -
 -		case WM_SETFOCUS:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS");
 -			if (gDebugWindowProc)
 -			{
 -				LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL;
 -			}
 -			window_imp->mCallbacks->handleFocus(window_imp);
 -			return 0;
 -
 -		case WM_KILLFOCUS:
 -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS");
 -			if (gDebugWindowProc)
 -			{
 -				LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL;
 -			}
 -			window_imp->mCallbacks->handleFocusLost(window_imp);
 -			return 0;
 -
 -		case WM_COPYDATA:
 -			{
 -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
 -				// received a URL
 -				PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
 -				window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
 -			};
 -			return 0;			
 -
 -			break;
 -		}
 -
 -	window_imp->mCallbacks->handlePauseWatchdog(window_imp);	
 -	}
 -
 -
 -	// pass unhandled messages down to Windows
 -	return DefWindowProc(h_wnd, u_msg, w_param, l_param);
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
 -{
 -	S32		client_height;
 -	RECT	client_rect;
 -	LLCoordWindow window_position;
 -
 -	if (!mWindowHandle ||
 -		!GetClientRect(mWindowHandle, &client_rect) ||
 -		NULL == to)
 -	{
 -		return FALSE;
 -	}
 -
 -	to->mX = from.mX;
 -	client_height = client_rect.bottom - client_rect.top;
 -	to->mY = client_height - from.mY - 1;
 -
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
 -{
 -	S32		client_height;
 -	RECT	client_rect;
 -
 -	if (!mWindowHandle ||
 -		!GetClientRect(mWindowHandle, &client_rect) ||
 -		NULL == to)
 -	{
 -		return FALSE;
 -	}
 -
 -	to->mX = from.mX;
 -	client_height = client_rect.bottom - client_rect.top;
 -	to->mY = client_height - from.mY - 1;
 -
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
 -{	
 -	POINT mouse_point;
 -
 -	mouse_point.x = from.mX;
 -	mouse_point.y = from.mY;
 -	BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
 -
 -	if (result)
 -	{
 -		to->mX = mouse_point.x;
 -		to->mY = mouse_point.y;
 -	}
 -
 -	return result;
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
 -{
 -	POINT mouse_point;
 -
 -	mouse_point.x = from.mX;
 -	mouse_point.y = from.mY;
 -	BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
 -
 -	if (result)
 -	{
 -		to->mX = mouse_point.x;
 -		to->mY = mouse_point.y;
 -	}
 -
 -	return result;
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to)
 -{
 -	LLCoordWindow window_coord;
 -
 -	if (!mWindowHandle || (NULL == to))
 -	{
 -		return FALSE;
 -	}
 -
 -	convertCoords(from, &window_coord);
 -	convertCoords(window_coord, to);
 -	return TRUE;
 -}
 -
 -BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to)
 -{
 -	LLCoordWindow window_coord;
 -
 -	if (!mWindowHandle || (NULL == to))
 -	{
 -		return FALSE;
 -	}
 -
 -	convertCoords(from, &window_coord);
 -	convertCoords(window_coord, to);
 -	return TRUE;
 -}
 -
 -
 -BOOL LLWindowWin32::isClipboardTextAvailable()
 -{
 -	return IsClipboardFormatAvailable(CF_UNICODETEXT);
 -}
 -
 -
 -BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
 -{
 -	BOOL success = FALSE;
 -
 -	if (IsClipboardFormatAvailable(CF_UNICODETEXT))
 -	{
 -		if (OpenClipboard(mWindowHandle))
 -		{
 -			HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT);
 -			if (h_data)
 -			{
 -				WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
 -				if (utf16str)
 -				{
 -					dst = utf16str_to_wstring(utf16str);
 -					LLWStringUtil::removeCRLF(dst);
 -					GlobalUnlock(h_data);
 -					success = TRUE;
 -				}
 -			}
 -			CloseClipboard();
 -		}
 -	}
 -
 -	return success;
 -}
 -
 -
 -BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
 -{
 -	BOOL success = FALSE;
 -
 -	if (OpenClipboard(mWindowHandle))
 -	{
 -		EmptyClipboard();
 -
 -		// Provide a copy of the data in Unicode format.
 -		LLWString sanitized_string(wstr);
 -		LLWStringUtil::addCRLF(sanitized_string);
 -		llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
 -		const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
 -
 -		// Memory is allocated and then ownership of it is transfered to the system.
 -		HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16); 
 -		if (hglobal_copy_utf16)
 -		{
 -			WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16);
 -			if (copy_utf16)
 -			{
 -				memcpy(copy_utf16, out_utf16.c_str(), size_utf16);	/* Flawfinder: ignore */
 -				GlobalUnlock(hglobal_copy_utf16);
 -
 -				if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
 -				{
 -					success = TRUE;
 -				}
 -			}
 -		}
 -
 -		CloseClipboard();
 -	}
 -
 -	return success;
 -}
 -
 -// Constrains the mouse to the window.
 -void LLWindowWin32::setMouseClipping( BOOL b )
 -{
 -	if( b != mIsMouseClipping )
 -	{
 -		BOOL success = FALSE;
 -
 -		if( b )
 -		{
 -			GetClipCursor( &mOldMouseClip );
 -
 -			RECT client_rect_in_screen_space;
 -			if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
 -			{
 -				success = ClipCursor( &client_rect_in_screen_space );
 -			}
 -		}
 -		else
 -		{
 -			// Must restore the old mouse clip, which may be set by another window.
 -			success = ClipCursor( &mOldMouseClip );
 -			SetRect( &mOldMouseClip, 0, 0, 0, 0 );
 -		}
 -
 -		if( success )
 -		{
 -			mIsMouseClipping = b;
 -		}
 -	}
 -}
 -
 -BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
 -{
 -	BOOL success = FALSE;
 -
 -	RECT client_rect;
 -	if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) )
 -	{
 -		POINT top_left;
 -		top_left.x = client_rect.left;
 -		top_left.y = client_rect.top;
 -		ClientToScreen(mWindowHandle, &top_left); 
 -
 -		POINT bottom_right;
 -		bottom_right.x = client_rect.right;
 -		bottom_right.y = client_rect.bottom;
 -		ClientToScreen(mWindowHandle, &bottom_right); 
 -
 -		SetRect( rectp,
 -			top_left.x,
 -			top_left.y,
 -			bottom_right.x,
 -			bottom_right.y );
 -
 -		success = TRUE;
 -	}
 -
 -	return success;
 -}
 -
 -void LLWindowWin32::flashIcon(F32 seconds)
 -{
 -	FLASHWINFO flash_info;
 -
 -	flash_info.cbSize = sizeof(FLASHWINFO);
 -	flash_info.hwnd = mWindowHandle;
 -	flash_info.dwFlags = FLASHW_TRAY;
 -	flash_info.uCount = UINT(seconds / ICON_FLASH_TIME);
 -	flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds
 -	FlashWindowEx(&flash_info);
 -}
 -
 -F32 LLWindowWin32::getGamma()
 -{
 -	return mCurrentGamma;
 -}
 -
 -BOOL LLWindowWin32::restoreGamma()
 -{
 -	return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
 -}
 -
 -BOOL LLWindowWin32::setGamma(const F32 gamma)
 -{
 -	mCurrentGamma = gamma;
 -
 -	LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL;
 -
 -	for ( int i = 0; i < 256; ++i )
 -	{
 -		int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f );
 -
 -		int value = mult * i;
 -
 -		if ( value > 0xffff )
 -			value = 0xffff;
 -
 -		mCurrentGammaRamp [ 0 * 256 + i ] = 
 -			mCurrentGammaRamp [ 1 * 256 + i ] = 
 -				mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value;
 -	};
 -
 -	return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
 -}
 -
 -void LLWindowWin32::setFSAASamples(const U32 fsaa_samples)
 -{
 -	mFSAASamples = fsaa_samples;
 -}
 -
 -U32 LLWindowWin32::getFSAASamples()
 -{
 -	return mFSAASamples;
 -}
 -
 -LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions)
 -{
 -	if (!mSupportedResolutions)
 -	{
 -		mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
 -		DEVMODE dev_mode;
 -
 -		mNumSupportedResolutions = 0;
 -		for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
 -		{
 -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 -			{
 -				break;
 -			}
 -
 -			if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL &&
 -				dev_mode.dmPelsWidth >= 800 &&
 -				dev_mode.dmPelsHeight >= 600)
 -			{
 -				BOOL resolution_exists = FALSE;
 -				for(S32 i = 0; i < mNumSupportedResolutions; i++)
 -				{
 -					if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
 -						mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
 -					{
 -						resolution_exists = TRUE;
 -					}
 -				}
 -				if (!resolution_exists)
 -				{
 -					mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth;
 -					mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight;
 -					mNumSupportedResolutions++;
 -				}
 -			}
 -		}
 -	}
 -
 -	num_resolutions = mNumSupportedResolutions;
 -	return mSupportedResolutions;
 -}
 -
 -
 -F32 LLWindowWin32::getNativeAspectRatio()
 -{
 -	if (mOverrideAspectRatio > 0.f)
 -	{
 -		return mOverrideAspectRatio;
 -	}
 -	else if (mNativeAspectRatio > 0.f)
 -	{
 -		// we grabbed this value at startup, based on the user's desktop settings
 -		return mNativeAspectRatio;
 -	}
 -	// RN: this hack presumes that the largest supported resolution is monitor-limited
 -	// and that pixels in that mode are square, therefore defining the native aspect ratio
 -	// of the monitor...this seems to work to a close approximation for most CRTs/LCDs
 -	S32 num_resolutions;
 -	LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
 -
 -	return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
 -}
 -
 -F32 LLWindowWin32::getPixelAspectRatio()
 -{
 -	F32 pixel_aspect = 1.f;
 -	if (getFullscreen())
 -	{
 -		LLCoordScreen screen_size;
 -		getSize(&screen_size);
 -		pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
 -	}
 -
 -	return pixel_aspect;
 -}
 -
 -// Change display resolution.  Returns true if successful.
 -// protected
 -BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
 -{
 -	DEVMODE dev_mode;
 -	dev_mode.dmSize = sizeof(dev_mode);
 -	BOOL success = FALSE;
 -
 -	// Don't change anything if we don't have to
 -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 -	{
 -		if (dev_mode.dmPelsWidth        == width &&
 -			dev_mode.dmPelsHeight       == height &&
 -			dev_mode.dmBitsPerPel       == bits &&
 -			dev_mode.dmDisplayFrequency == refresh )
 -		{
 -			// ...display mode identical, do nothing
 -			return TRUE;
 -		}
 -	}
 -
 -	memset(&dev_mode, 0, sizeof(dev_mode));
 -	dev_mode.dmSize = sizeof(dev_mode);
 -	dev_mode.dmPelsWidth        = width;
 -	dev_mode.dmPelsHeight       = height;
 -	dev_mode.dmBitsPerPel       = bits;
 -	dev_mode.dmDisplayFrequency = refresh;
 -	dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
 -
 -	// CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
 -	LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
 -
 -	success = (DISP_CHANGE_SUCCESSFUL == cds_result);
 -
 -	if (!success)
 -	{
 -		LL_WARNS("Window") << "setDisplayResolution failed, "
 -			<< width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
 -	}
 -
 -	return success;
 -}
 -
 -// protected
 -BOOL LLWindowWin32::setFullscreenResolution()
 -{
 -	if (mFullscreen)
 -	{
 -		return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
 -	}
 -	else
 -	{
 -		return FALSE;
 -	}
 -}
 -
 -// protected
 -BOOL LLWindowWin32::resetDisplayResolution()
 -{
 -	LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL;
 -
 -	LONG cds_result = ChangeDisplaySettings(NULL, 0);
 -
 -	BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
 -
 -	if (!success)
 -	{
 -		LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL;
 -	}
 -
 -	LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL;
 -
 -	return success;
 -}
 -
 -void LLWindowWin32::swapBuffers()
 -{
 -	SwapBuffers(mhDC);
 -}
 -
 -
 -//
 -// LLSplashScreenImp
 -//
 -LLSplashScreenWin32::LLSplashScreenWin32()
 -:	mWindow(NULL)
 -{
 -}
 -
 -LLSplashScreenWin32::~LLSplashScreenWin32()
 -{
 -}
 -
 -void LLSplashScreenWin32::showImpl()
 -{
 -	// This appears to work.  ???
 -	HINSTANCE hinst = GetModuleHandle(NULL);
 -
 -	mWindow = CreateDialog(hinst, 
 -		TEXT("SPLASHSCREEN"), 
 -		NULL,	// no parent
 -		(DLGPROC) LLSplashScreenWin32::windowProc); 
 -	ShowWindow(mWindow, SW_SHOW);
 -}
 -
 -
 -void LLSplashScreenWin32::updateImpl(const std::string& mesg)
 -{
 -	if (!mWindow) return;
 -
 -	WCHAR w_mesg[1024];
 -	mbstowcs(w_mesg, mesg.c_str(), 1024);
 -
 -	SendDlgItemMessage(mWindow,
 -		666,		// HACK: text id
 -		WM_SETTEXT,
 -		FALSE,
 -		(LPARAM)w_mesg);
 -}
 -
 -
 -void LLSplashScreenWin32::hideImpl()
 -{
 -	if (mWindow)
 -	{
 -		DestroyWindow(mWindow);
 -		mWindow = NULL; 
 -	}
 -}
 -
 -
 -// static
 -LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg,
 -											WPARAM w_param, LPARAM l_param)
 -{
 -	// Just give it to windows
 -	return DefWindowProc(h_wnd, u_msg, w_param, l_param);
 -}
 -
 -//
 -// Helper Funcs
 -//
 -
 -S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type)
 -{
 -	UINT uType;
 -
 -	switch(type)
 -	{
 -	case OSMB_OK:
 -		uType = MB_OK;
 -		break;
 -	case OSMB_OKCANCEL:
 -		uType = MB_OKCANCEL;
 -		break;
 -	case OSMB_YESNO:
 -		uType = MB_YESNO;
 -		break;
 -	default:
 -		uType = MB_OK;
 -		break;
 -	}
 -
 -	// HACK! Doesn't properly handle wide strings!
 -	int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType);
 -	S32 retval;
 -
 -	switch(retval_win)
 -	{
 -	case IDYES:
 -		retval = OSBTN_YES;
 -		break;
 -	case IDNO:
 -		retval = OSBTN_NO;
 -		break;
 -	case IDOK:
 -		retval = OSBTN_OK;
 -		break;
 -	case IDCANCEL:
 -		retval = OSBTN_CANCEL;
 -		break;
 -	default:
 -		retval = OSBTN_CANCEL;
 -		break;
 -	}
 -
 -	return retval;
 -}
 -
 -
 -void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url )
 -{
 -	bool found = false;
 -	S32 i;
 -	for (i = 0; i < gURLProtocolWhitelistCount; i++)
 -	{
 -		if (escaped_url.find(gURLProtocolWhitelist[i]) == 0)
 -		{
 -			found = true;
 -			break;
 -		}
 -	}
 -
 -	if (!found)
 -	{
 -		LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
 -		return;
 -	}
 -
 -	LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL;
 -
 -	// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
 -	// reliablly on Vista.
 -
 -	// this is madness.. no, this is..
 -	LLWString url_wstring = utf8str_to_wstring( escaped_url );
 -	llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
 -
 -	// let the OS decide what to use to open the URL
 -	SHELLEXECUTEINFO sei = { sizeof( sei ) };
 -	sei.fMask = SEE_MASK_FLAG_DDEWAIT;
 -	sei.nShow = SW_SHOWNORMAL;
 -	sei.lpVerb = L"open";
 -	sei.lpFile = url_utf16.c_str();
 -	ShellExecuteEx( &sei );
 -
 -	//// TODO: LEAVING OLD CODE HERE SO I DON'T BONE OTHER MERGES
 -	//// DELETE THIS ONCE THE MERGES ARE DONE
 -
 -	// Figure out the user's default web browser
 -	// HKEY_CLASSES_ROOT\http\shell\open\command
 -	/*
 -	std::string reg_path_str = gURLProtocolWhitelistHandler[i] + "\\shell\\open\\command";
 -	WCHAR reg_path_wstr[256];
 -	mbstowcs( reg_path_wstr, reg_path_str.c_str(), LL_ARRAY_SIZE(reg_path_wstr) );
 -
 -	HKEY key;
 -	WCHAR browser_open_wstr[1024];
 -	DWORD buffer_length = 1024;
 -	RegOpenKeyEx(HKEY_CLASSES_ROOT, reg_path_wstr, 0, KEY_QUERY_VALUE, &key);
 -	RegQueryValueEx(key, NULL, NULL, NULL, (LPBYTE)browser_open_wstr, &buffer_length);
 -	RegCloseKey(key);
 -
 -	// Convert to STL string
 -	LLWString browser_open_wstring = utf16str_to_wstring(browser_open_wstr);
 -
 -	if (browser_open_wstring.length() < 2)
 -	{
 -		LL_WARNS("Window") << "Invalid browser executable in registry " << browser_open_wstring << LL_ENDL;
 -		return;
 -	}
 -
 -	// Extract the process that's supposed to be launched
 -	LLWString browser_executable;
 -	if (browser_open_wstring[0] == '"')
 -	{
 -		// executable is quoted, find the matching quote
 -		size_t quote_pos = browser_open_wstring.find('"', 1);
 -		// copy out the string including both quotes
 -		browser_executable = browser_open_wstring.substr(0, quote_pos+1);
 -	}
 -	else
 -	{
 -		// executable not quoted, find a space
 -		size_t space_pos = browser_open_wstring.find(' ', 1);
 -		browser_executable = browser_open_wstring.substr(0, space_pos);
 -	}
 -
 -	LL_DEBUGS("Window") << "Browser reg key: " << wstring_to_utf8str(browser_open_wstring) << LL_ENDL;
 -	LL_INFOS("Window") << "Browser executable: " << wstring_to_utf8str(browser_executable) << LL_ENDL;
 -
 -	// Convert URL to wide string for Windows API
 -	// Assume URL is UTF8, as can come from scripts
 -	LLWString url_wstring = utf8str_to_wstring(escaped_url);
 -	llutf16string url_utf16 = wstring_to_utf16str(url_wstring);
 -
 -	// Convert executable and path to wide string for Windows API
 -	llutf16string browser_exec_utf16 = wstring_to_utf16str(browser_executable);
 -
 -	// ShellExecute returns HINSTANCE for backwards compatiblity.
 -	// MS docs say to cast to int and compare to 32.
 -	HWND our_window = NULL;
 -	LPCWSTR directory_wstr = NULL;
 -	int retval = (int) ShellExecute(our_window, 	// Flawfinder: ignore
 -									L"open", 
 -									browser_exec_utf16.c_str(), 
 -									url_utf16.c_str(), 
 -									directory_wstr,
 -									SW_SHOWNORMAL);
 -	if (retval > 32)
 -	{
 -		LL_DEBUGS("Window") << "load_url success with " << retval << LL_ENDL;
 -	}
 -	else
 -	{
 -		LL_INFOS("Window") << "load_url failure with " << retval << LL_ENDL;
 -	}
 -	*/
 -}
 -
 -
 -BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
 -{
 -	BOOL retval = FALSE;
 -
 -	static CHOOSECOLOR cc;
 -	static COLORREF crCustColors[16];
 -	cc.lStructSize = sizeof(CHOOSECOLOR);
 -	cc.hwndOwner = mWindowHandle;
 -	cc.hInstance = NULL;
 -	cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f));
 -	//cc.rgbResult = RGB (0x80,0x80,0x80); 
 -	cc.lpCustColors = crCustColors;
 -	cc.Flags = CC_RGBINIT | CC_FULLOPEN;
 -	cc.lCustData = 0;
 -	cc.lpfnHook = NULL;
 -	cc.lpTemplateName = NULL;
 - 
 -	// This call is modal, so pause agent
 -	//send_agent_pause();	// this is in newview and we don't want to set up a dependency
 -	{
 -		retval = ChooseColor(&cc);
 -	}
 -	//send_agent_resume();	// this is in newview and we don't want to set up a dependency
 -
 -	*b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f;
 -
 -	*g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f;
 -	
 -	*r = ((F32)(cc.rgbResult & 0xff)) / 255.f;
 -
 -	return (retval);
 -}
 -
 -void *LLWindowWin32::getPlatformWindow()
 -{
 -	return (void*)mWindowHandle;
 -}
 -
 -void LLWindowWin32::bringToFront()
 -{
 -	BringWindowToTop(mWindowHandle);
 -}
 -
 -// set (OS) window focus back to the client
 -void LLWindowWin32::focusClient()
 -{
 -	SetFocus ( mWindowHandle );
 -}
 -
 -void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
 -{
 -	if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
 -	{
 -		return;
 -	}
 -
 -	if (preeditor != mPreeditor && !b)
 -	{
 -		// This condition may occur with a call to
 -		// setEnabled(BOOL) from LLTextEditor or LLLineEditor
 -		// when the control is not focused.
 -		// We need to silently ignore the case so that
 -		// the language input status of the focused control
 -		// is not disturbed.
 -		return;
 -	}
 -
 -	// Take care of old and new preeditors.
 -	if (preeditor != mPreeditor || !b)
 -	{
 -		if (sLanguageTextInputAllowed)
 -		{
 -			interruptLanguageTextInput();
 -		}
 -		mPreeditor = (b ? preeditor : NULL);
 -	}
 -
 -	sLanguageTextInputAllowed = b;
 -
 -	if ( sLanguageTextInputAllowed )
 -	{
 -		// Allowing: Restore the previous IME status, so that the user has a feeling that the previous 
 -		// text input continues naturally.  Be careful, however, the IME status is meaningful only during the user keeps 
 -		// using same Input Locale (aka Keyboard Layout).
 -		if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
 -		{
 -			HIMC himc = LLWinImm::getContext(mWindowHandle);
 -			LLWinImm::setOpenStatus(himc, TRUE);
 -			LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode);
 -			LLWinImm::releaseContext(mWindowHandle, himc);
 -		}
 -	}
 -	else
 -	{
 -		// Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly.
 -		// However, do it after saving the current IME  status.  We need to restore the status when
 -		//   allowing language text input again.
 -		sWinInputLocale = GetKeyboardLayout(0);
 -		sWinIMEOpened = LLWinImm::isIME(sWinInputLocale);
 -		if (sWinIMEOpened)
 -		{
 -			HIMC himc = LLWinImm::getContext(mWindowHandle);
 -			sWinIMEOpened = LLWinImm::getOpenStatus(himc);
 -			if (sWinIMEOpened)
 -			{
 -				LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode);
 -
 -				// We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's 
 -				// keyboard hooking, because Some IME reacts only on the former and some other on the latter...
 -				LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
 -				LLWinImm::setOpenStatus(himc, FALSE);
 -			}
 -			LLWinImm::releaseContext(mWindowHandle, himc);
 - 		}
 -	}
 -}
 -
 -void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, 
 -		CANDIDATEFORM *form)
 -{
 -	LLCoordWindow caret_coord, top_left, bottom_right;
 -	convertCoords(caret, &caret_coord);
 -	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
 -	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
 -
 -	memset(form, 0, sizeof(CANDIDATEFORM));
 -	form->dwStyle = CFS_EXCLUDE;
 -	form->ptCurrentPos.x = caret_coord.mX;
 -	form->ptCurrentPos.y = caret_coord.mY;
 -	form->rcArea.left   = top_left.mX;
 -	form->rcArea.top    = top_left.mY;
 -	form->rcArea.right  = bottom_right.mX;
 -	form->rcArea.bottom = bottom_right.mY;
 -}
 -
 -
 -// Put the IME window at the right place (near current text input).   Point coordinates should be the top of the current text line.
 -void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
 -{
 -	if (sLanguageTextInputAllowed && LLWinImm::isAvailable())
 -	{
 -		HIMC himc = LLWinImm::getContext(mWindowHandle);
 -
 -		LLCoordWindow win_pos;
 -		convertCoords( position, &win_pos );
 -
 -		if ( win_pos.mX >= 0 && win_pos.mY >= 0 && 
 -			(win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) )
 -		{
 -			COMPOSITIONFORM ime_form;
 -			memset( &ime_form, 0, sizeof(ime_form) );
 -			ime_form.dwStyle = CFS_POINT;
 -			ime_form.ptCurrentPos.x = win_pos.mX;
 -			ime_form.ptCurrentPos.y = win_pos.mY;
 -
 -			LLWinImm::setCompositionWindow( himc, &ime_form );
 -
 -			sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY );
 -		}
 -
 -		LLWinImm::releaseContext(mWindowHandle, himc);
 -	}
 -}
 -
 -
 -void LLWindowWin32::fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control,
 -		IMECHARPOSITION *char_position)
 -{
 -	LLCoordScreen caret_coord, top_left, bottom_right;
 -	convertCoords(caret, &caret_coord);
 -	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
 -	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
 -
 -	char_position->pt.x = caret_coord.mX;
 -	char_position->pt.y = top_left.mY;	// Windows wants the coordinate of upper left corner of a character...
 -	char_position->cLineHeight = bottom_right.mY - top_left.mY;
 -	char_position->rcDocument.left   = top_left.mX;
 -	char_position->rcDocument.top    = top_left.mY;
 -	char_position->rcDocument.right  = bottom_right.mX;
 -	char_position->rcDocument.bottom = bottom_right.mY;
 -}
 -
 -void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
 -{
 -	// Our font is a list of FreeType recognized font files that may
 -	// not have a corresponding ones in Windows' fonts.  Hence, we
 -	// can't simply tell Windows which font we are using.  We will
 -	// notify a _standard_ font for a current input locale instead.
 -	// We use a hard-coded knowledge about the Windows' standard
 -	// configuration to do so...
 -
 -	memset(logfont, 0, sizeof(LOGFONT));
 -
 -	const WORD lang_id = LOWORD(GetKeyboardLayout(0));
 -	switch (PRIMARYLANGID(lang_id))
 -	{
 -	case LANG_CHINESE:
 -		// We need to identify one of two Chinese fonts.
 -		switch (SUBLANGID(lang_id))
 -		{
 -		case SUBLANG_CHINESE_SIMPLIFIED:
 -		case SUBLANG_CHINESE_SINGAPORE:
 -			logfont->lfCharSet = GB2312_CHARSET;
 -			lstrcpy(logfont->lfFaceName, TEXT("SimHei"));
 -			break;
 -		case SUBLANG_CHINESE_TRADITIONAL:
 -		case SUBLANG_CHINESE_HONGKONG:
 -		case SUBLANG_CHINESE_MACAU:
 -		default:
 -			logfont->lfCharSet = CHINESEBIG5_CHARSET;
 -			lstrcpy(logfont->lfFaceName, TEXT("MingLiU"));
 -			break;			
 -		}
 -		break;
 -	case LANG_JAPANESE:
 -		logfont->lfCharSet = SHIFTJIS_CHARSET;
 -		lstrcpy(logfont->lfFaceName, TEXT("MS Gothic"));
 -		break;		
 -	case LANG_KOREAN:
 -		logfont->lfCharSet = HANGUL_CHARSET;
 -		lstrcpy(logfont->lfFaceName, TEXT("Gulim"));
 -		break;
 -	default:
 -		logfont->lfCharSet = ANSI_CHARSET;
 -		lstrcpy(logfont->lfFaceName, TEXT("Tahoma"));
 -		break;
 -	}
 -							
 -	logfont->lfHeight = mPreeditor->getPreeditFontSize();
 -	logfont->lfWeight = FW_NORMAL;
 -}	
 -
 -U32 LLWindowWin32::fillReconvertString(const LLWString &text,
 -	S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
 -{
 -	const llutf16string text_utf16 = wstring_to_utf16str(text);
 -	const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR);
 -	if (reconvert_string && reconvert_string->dwSize >= required_size)
 -	{
 -		const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus);
 -		const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length);
 -
 -		reconvert_string->dwVersion = 0;
 -		reconvert_string->dwStrLen = text_utf16.length();
 -		reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING);
 -		reconvert_string->dwCompStrLen = focus_utf16_length;
 -		reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR);
 -		reconvert_string->dwTargetStrLen = 0;
 -		reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR);
 -
 -		const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING));
 -		memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR));
 -	}
 -	return required_size;
 -}
 -
 -void LLWindowWin32::updateLanguageTextInputArea()
 -{
 -	if (!mPreeditor || !LLWinImm::isAvailable())
 -	{
 -		return;
 -	}
 -
 -	LLCoordGL caret_coord;
 -	LLRect preedit_bounds;
 -	if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL))
 -	{
 -		mLanguageTextInputPointGL = caret_coord;
 -		mLanguageTextInputAreaGL = preedit_bounds;
 -
 -		CANDIDATEFORM candidate_form;
 -		fillCandidateForm(caret_coord, preedit_bounds, &candidate_form);
 -
 -		HIMC himc = LLWinImm::getContext(mWindowHandle);
 -		// Win32 document says there may be up to 4 candidate windows.
 -		// This magic number 4 appears only in the document, and
 -		// there are no constant/macro for the value...
 -		for (int i = 3; i >= 0; --i)
 -		{
 -			candidate_form.dwIndex = i;
 -			LLWinImm::setCandidateWindow(himc, &candidate_form);
 -		}
 -		LLWinImm::releaseContext(mWindowHandle, himc);
 -	}
 -}
 -
 -void LLWindowWin32::interruptLanguageTextInput()
 -{
 -	if (mPreeditor)
 -	{
 -		if (LLWinImm::isAvailable())
 -		{
 -			HIMC himc = LLWinImm::getContext(mWindowHandle);
 -			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
 -			LLWinImm::releaseContext(mWindowHandle, himc);
 -		}
 -
 -		// Win32 document says there will be no composition string
 -		// after NI_COMPOSITIONSTR returns.  The following call to
 -		// resetPreedit should be a NOP unless IME goes mad...
 -		mPreeditor->resetPreedit();
 -	}
 -}
 -
 -void LLWindowWin32::handleStartCompositionMessage()
 -{
 -	// Let IME know the font to use in feedback UI.
 -	LOGFONT logfont;
 -	fillCompositionLogfont(&logfont);
 -	HIMC himc = LLWinImm::getContext(mWindowHandle);
 -	LLWinImm::setCompositionFont(himc, &logfont);
 -	LLWinImm::releaseContext(mWindowHandle, himc);
 -}
 -
 -// Handle WM_IME_COMPOSITION message.
 -
 -void LLWindowWin32::handleCompositionMessage(const U32 indexes)
 -{
 -	BOOL needs_update = FALSE;
 -	LLWString result_string;
 -	LLWString preedit_string;
 -	S32 preedit_string_utf16_length = 0;
 -	LLPreeditor::segment_lengths_t preedit_segment_lengths;
 -	LLPreeditor::standouts_t preedit_standouts;
 -
 -	// Step I: Receive details of preedits from IME.
 -
 -	HIMC himc = LLWinImm::getContext(mWindowHandle);
 -
 -	if (indexes & GCS_RESULTSTR)
 -	{
 -		LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0);
 -		if (size >= 0)
 -		{
 -			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
 -			size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size);
 -			if (size > 0)
 -			{
 -				result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
 -			}
 -			delete[] data;
 -			needs_update = TRUE;
 -		}
 -	}
 -	
 -	if (indexes & GCS_COMPSTR)
 -	{
 -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0);
 -		if (size >= 0)
 -		{
 -			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
 -			size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size);
 -			if (size > 0)
 -			{
 -				preedit_string_utf16_length = size / sizeof(WCHAR);
 -				preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
 -			}
 -			delete[] data;
 -			needs_update = TRUE;
 -		}
 -	}
 -
 -	if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0)
 -	{
 -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0);
 -		if (size > 0)
 -		{
 -			const LPDWORD data = new DWORD[size / sizeof(DWORD)];
 -			size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size);
 -			if (size >= sizeof(DWORD) * 2
 -				&& data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length)
 -			{
 -				preedit_segment_lengths.resize(size / sizeof(DWORD) - 1);
 -				S32 offset = 0;
 -				for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
 -				{
 -					const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]);
 -					preedit_segment_lengths[i] = length;
 -					offset += length;
 -				}
 -			}
 -			delete[] data;
 -		}
 -	}
 -
 -	if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1)
 -	{
 -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0);
 -		if (size > 0)
 -		{
 -			const LPBYTE data = new BYTE[size / sizeof(BYTE)];
 -			size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size);
 -			if (size == preedit_string_utf16_length)
 -			{
 -				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
 -				S32 offset = 0;
 -				for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
 -				{
 -					if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset])
 -					{
 -						preedit_standouts[i] = TRUE;
 -					}
 -					offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]);
 -				}
 -			}
 -			delete[] data;
 -		}
 -	}
 -
 -	S32 caret_position = preedit_string.length();
 -	if (indexes & GCS_CURSORPOS)
 -	{
 -		const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0);
 -		if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length)
 -		{
 -			caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16);
 -		}
 -	}
 -
 -	if (indexes == 0)
 -	{
 -		// I'm not sure this condition really happens, but
 -		// Windows SDK document says it is an indication
 -		// of "reset everything."
 -		needs_update = TRUE;
 -	}
 -
 -	LLWinImm::releaseContext(mWindowHandle, himc);
 -
 -	// Step II: Update the active preeditor.
 -
 -	if (needs_update)
 -	{
 -		mPreeditor->resetPreedit();
 -
 -		if (result_string.length() > 0)
 -		{
 -			for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++)
 -			{
 -				mPreeditor->handleUnicodeCharHere(*i);
 -			}
 -		}
 -
 -		if (preedit_string.length() == 0)
 - 		{
 -			preedit_segment_lengths.clear();
 -			preedit_standouts.clear();
 -		}
 -		else
 -		{
 -			if (preedit_segment_lengths.size() == 0)
 -			{
 -				preedit_segment_lengths.assign(1, preedit_string.length());
 -			}
 -			if (preedit_standouts.size() == 0)
 -			{
 -				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
 -			}
 -		}
 -		mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
 -
 -		// Some IME doesn't query char position after WM_IME_COMPOSITION,
 -		// so we need to update them actively.
 -		updateLanguageTextInputArea();
 -	}
 -}
 -
 -// Given a text and a focus range, find_context finds and returns a
 -// surrounding context of the focused subtext.  A variable pointed
 -// to by offset receives the offset in llwchars of the beginning of
 -// the returned context string in the given wtext.
 -
 -static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_length, S32 *offset)
 -{
 -	static const S32 CONTEXT_EXCESS = 30;	// This value is by experiences.
 -
 -	const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS);
 -	S32 end = focus + focus_length;
 -	while (end < e && '\n' != wtext[end])
 -	{
 -		end++;
 -	}
 -
 -	const S32 s = llmax(0, focus - CONTEXT_EXCESS);
 -	S32 start = focus;
 -	while (start > s && '\n' != wtext[start - 1])
 -	{
 -		--start;
 -	}
 -
 -	*offset = start;
 -	return wtext.substr(start, end - start);
 -}
 -
 -// final stage of handling drop requests - both from WM_DROPFILES message
 -// for files and via IDropTarget interface requests.
 -LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url )
 -{
 -	return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url );
 -}
 -
 -// Handle WM_IME_REQUEST message.
 -// If it handled the message, returns TRUE.  Otherwise, FALSE.
 -// When it handled the message, the value to be returned from
 -// the Window Procedure is set to *result.
 -
 -BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
 -{
 -	if ( mPreeditor )
 -	{
 -		switch (request)
 -		{
 -			case IMR_CANDIDATEWINDOW:		// http://msdn2.microsoft.com/en-us/library/ms776080.aspx
 -			{
 -				LLCoordGL caret_coord;
 -				LLRect preedit_bounds;
 -				mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL);
 -				
 -				CANDIDATEFORM *const form = (CANDIDATEFORM *)param;
 -				DWORD const dwIndex = form->dwIndex;
 -				fillCandidateForm(caret_coord, preedit_bounds, form);
 -				form->dwIndex = dwIndex;
 -
 -				*result = 1;
 -				return TRUE;
 -			}
 -			case IMR_QUERYCHARPOSITION:
 -			{
 -				IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param;
 -
 -				// char_position->dwCharPos counts in number of
 -				// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
 -				// number to getPreeditLocation.  
 -
 -				const LLWString & wtext = mPreeditor->getPreeditString();
 -				S32 preedit, preedit_length;
 -				mPreeditor->getPreeditRange(&preedit, &preedit_length);
 -				LLCoordGL caret_coord;
 -				LLRect preedit_bounds, text_control;
 -				const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos);
 -
 -				if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control))
 -				{
 -					LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL;
 -					return FALSE;
 -				}
 -				fillCharPosition(caret_coord, preedit_bounds, text_control, char_position);
 -
 -				*result = 1;
 -				return TRUE;
 -			}
 -			case IMR_COMPOSITIONFONT:
 -			{
 -				fillCompositionLogfont((LOGFONT *)param);
 -
 -				*result = 1;
 -				return TRUE;
 -			}
 -			case IMR_RECONVERTSTRING:
 -			{
 -				mPreeditor->resetPreedit();
 -				const LLWString & wtext = mPreeditor->getPreeditString();
 -				S32 select, select_length;
 -				mPreeditor->getSelectionRange(&select, &select_length);
 -
 -				S32 context_offset;
 -				const LLWString context = find_context(wtext, select, select_length, &context_offset);
 -
 -				RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param;
 -				const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string);
 -				if (reconvert_string)
 -				{
 -					if (select_length == 0)
 -					{
 -						// Let the IME to decide the reconversion range, and
 -						// adjust the reconvert_string structure accordingly.
 -						HIMC himc = LLWinImm::getContext(mWindowHandle);
 -						const BOOL adjusted = LLWinImm::setCompositionString(himc,
 -									SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0);
 -						LLWinImm::releaseContext(mWindowHandle, himc);
 -						if (adjusted)
 -						{
 -							const llutf16string & text_utf16 = wstring_to_utf16str(context);
 -							const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR);
 -							const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen;
 -							select = utf16str_wstring_length(text_utf16, new_preedit_start);
 -							select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select;
 -							select += context_offset;
 -						}
 -					}
 -					mPreeditor->markAsPreedit(select, select_length);
 -				}
 -
 -				*result = size;
 -				return TRUE;
 -			}
 -			case IMR_CONFIRMRECONVERTSTRING:
 -			{
 -				*result = FALSE;
 -				return TRUE;
 -			}
 -			case IMR_DOCUMENTFEED:
 -			{
 -				const LLWString & wtext = mPreeditor->getPreeditString();
 -				S32 preedit, preedit_length;
 -				mPreeditor->getPreeditRange(&preedit, &preedit_length);
 -				
 -				S32 context_offset;
 -				LLWString context = find_context(wtext, preedit, preedit_length, &context_offset);
 -				preedit -= context_offset;
 -				if (preedit_length)
 -				{
 -					// IMR_DOCUMENTFEED may be called when we have an active preedit.
 -					// We should pass the context string *excluding* the preedit string.
 -					// Otherwise, some IME are confused.
 -					context.erase(preedit, preedit_length);
 -				}
 -				
 -				RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param;
 -				*result = fillReconvertString(context, preedit, 0, reconvert_string);
 -				return TRUE;
 -			}
 -			default:
 -				return FALSE;
 -		}
 -	}
 -
 -	return FALSE;
 -}
 -
 -//static
 -std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
 -{
 -	// Fonts previously in getFontListSans() have moved to fonts.xml.
 -	return std::vector<std::string>();
 -}
 -
 -
 -#endif // LL_WINDOWS
 +/**  + * @file llwindowwin32.cpp + * @brief Platform-dependent implementation of llwindow + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + *  + * Copyright (c) 2001-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#if LL_WINDOWS && !LL_MESA_HEADLESS + +#include "llwindowwin32.h" + +// LLWindow library includes +#include "llkeyboardwin32.h" +#include "lldragdropwin32.h" +#include "llpreeditor.h" +#include "llwindowcallbacks.h" + +// Linden library includes +#include "llerror.h" +#include "llgl.h" +#include "llstring.h" + +// System includes +#include <commdlg.h> +#include <WinUser.h> +#include <mapi.h> +#include <process.h>	// for _spawn +#include <shellapi.h> +#include <fstream> +#include <Imm.h> + +// Require DirectInput version 8 +#define DIRECTINPUT_VERSION 0x0800 + +#include <dinput.h> +#include <Dbt.h.> + +#include "llmemtype.h" +// culled from winuser.h +#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */ +const S32	WM_MOUSEWHEEL = 0x020A; +#endif +#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */ +const S32	WHEEL_DELTA = 120;     /* Value for rolling one detent */ +#endif +const S32	MAX_MESSAGE_PER_UPDATE = 20; +const S32	BITS_PER_PIXEL = 32; +const S32	MAX_NUM_RESOLUTIONS = 32; +const F32	ICON_FLASH_TIME = 0.5f; + +extern BOOL gDebugWindowProc; + +LPWSTR gIconResource = IDI_APPLICATION; + +LLW32MsgCallback gAsyncMsgCallback = NULL; + +// +// LLWindowWin32 +// + +void show_window_creation_error(const std::string& title) +{ +	LL_WARNS("Window") << title << LL_ENDL; +} + +//static +BOOL LLWindowWin32::sIsClassRegistered = FALSE; + +BOOL	LLWindowWin32::sLanguageTextInputAllowed = TRUE; +BOOL	LLWindowWin32::sWinIMEOpened = FALSE; +HKL		LLWindowWin32::sWinInputLocale = 0; +DWORD	LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE; +DWORD	LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; +LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); + +// The following class LLWinImm delegates Windows IMM APIs. +// We need this because some language versions of Windows, +// e.g., US version of Windows XP, doesn't install IMM32.DLL +// as a default, and we can't link against imm32.lib statically. +// I believe DLL loading of this type is best suited to do +// in a static initialization of a class.  What I'm not sure is +// whether it follows the Linden Conding Standard...  +// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members + +class LLWinImm +{ +public: +	static bool		isAvailable() { return sTheInstance.mHImmDll != NULL; } + +public: +	// Wrappers for IMM API. +	static BOOL		isIME(HKL hkl);															 +	static HWND		getDefaultIMEWnd(HWND hwnd); +	static HIMC		getContext(HWND hwnd);													 +	static BOOL		releaseContext(HWND hwnd, HIMC himc); +	static BOOL		getOpenStatus(HIMC himc);												 +	static BOOL		setOpenStatus(HIMC himc, BOOL status);									 +	static BOOL		getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);	 +	static BOOL		setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);		 +	static BOOL		getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					 +	static BOOL		setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					 +	static LONG		getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length); +	static BOOL		setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength); +	static BOOL		setCompositionFont(HIMC himc, LPLOGFONTW logfont); +	static BOOL		setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); +	static BOOL		notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); + +private: +	LLWinImm(); +	~LLWinImm(); + +private: +	// Pointers to IMM API. +	BOOL	 	(WINAPI *mImmIsIME)(HKL); +	HWND		(WINAPI *mImmGetDefaultIMEWnd)(HWND); +	HIMC		(WINAPI *mImmGetContext)(HWND); +	BOOL		(WINAPI *mImmReleaseContext)(HWND, HIMC); +	BOOL		(WINAPI *mImmGetOpenStatus)(HIMC); +	BOOL		(WINAPI *mImmSetOpenStatus)(HIMC, BOOL); +	BOOL		(WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); +	BOOL		(WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD); +	BOOL		(WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); +	BOOL		(WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); +	LONG		(WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); +	BOOL		(WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); +	BOOL		(WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); +	BOOL		(WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); +	BOOL		(WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); + +private: +	HMODULE		mHImmDll; +	static LLWinImm sTheInstance; +}; + +LLWinImm LLWinImm::sTheInstance; + +LLWinImm::LLWinImm() : mHImmDll(NULL) +{ +	// Check system metrics  +	if ( !GetSystemMetrics( SM_DBCSENABLED ) ) +		return; +	 + +	mHImmDll = LoadLibraryA("Imm32"); +	if (mHImmDll != NULL) +	{ +		mImmIsIME               = (BOOL (WINAPI *)(HKL))                    GetProcAddress(mHImmDll, "ImmIsIME"); +		mImmGetDefaultIMEWnd	= (HWND (WINAPI *)(HWND))					GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); +		mImmGetContext          = (HIMC (WINAPI *)(HWND))                   GetProcAddress(mHImmDll, "ImmGetContext"); +		mImmReleaseContext      = (BOOL (WINAPI *)(HWND, HIMC))             GetProcAddress(mHImmDll, "ImmReleaseContext"); +		mImmGetOpenStatus       = (BOOL (WINAPI *)(HIMC))                   GetProcAddress(mHImmDll, "ImmGetOpenStatus"); +		mImmSetOpenStatus       = (BOOL (WINAPI *)(HIMC, BOOL))             GetProcAddress(mHImmDll, "ImmSetOpenStatus"); +		mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus"); +		mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD))     GetProcAddress(mHImmDll, "ImmSetConversionStatus"); +		mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmGetCompositionWindow"); +		mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmSetCompositionWindow"); +		mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD))					GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); +		mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD))	GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); +		mImmSetCompositionFont  = (BOOL (WINAPI *)(HIMC, LPLOGFONTW))		GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); +		mImmSetCandidateWindow  = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM))  GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); +		mImmNotifyIME			= (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD))	GetProcAddress(mHImmDll, "ImmNotifyIME"); + +		if (mImmIsIME == NULL || +			mImmGetDefaultIMEWnd == NULL || +			mImmGetContext == NULL || +			mImmReleaseContext == NULL || +			mImmGetOpenStatus == NULL || +			mImmSetOpenStatus == NULL || +			mImmGetConversionStatus == NULL || +			mImmSetConversionStatus == NULL || +			mImmGetCompostitionWindow == NULL || +			mImmSetCompostitionWindow == NULL || +			mImmGetCompositionString == NULL || +			mImmSetCompositionString == NULL || +			mImmSetCompositionFont == NULL || +			mImmSetCandidateWindow == NULL || +			mImmNotifyIME == NULL) +		{ +			// If any of the above API entires are not found, we can't use IMM API.   +			// So, turn off the IMM support.  We should log some warning message in  +			// the case, since it is very unusual; these APIs are available from  +			// the beginning, and all versions of IMM32.DLL should have them all.   +			// Unfortunately, this code may be executed before initialization of  +			// the logging channel (llwarns), and we can't do it here...  Yes, this  +			// is one of disadvantages to use static constraction to DLL loading.  +			FreeLibrary(mHImmDll); +			mHImmDll = NULL; + +			// If we unload the library, make sure all the function pointers are cleared +			mImmIsIME = NULL; +			mImmGetDefaultIMEWnd = NULL; +			mImmGetContext = NULL; +			mImmReleaseContext = NULL; +			mImmGetOpenStatus = NULL; +			mImmSetOpenStatus = NULL; +			mImmGetConversionStatus = NULL; +			mImmSetConversionStatus = NULL; +			mImmGetCompostitionWindow = NULL; +			mImmSetCompostitionWindow = NULL; +			mImmGetCompositionString = NULL; +			mImmSetCompositionString = NULL; +			mImmSetCompositionFont = NULL; +			mImmSetCandidateWindow = NULL; +			mImmNotifyIME = NULL; +		} +	} +} + + +// static  +BOOL	LLWinImm::isIME(HKL hkl)															 +{  +	if ( sTheInstance.mImmIsIME ) +		return sTheInstance.mImmIsIME(hkl);  +	return FALSE; +} + +// static  +HIMC		LLWinImm::getContext(HWND hwnd) +{ +	if ( sTheInstance.mImmGetContext ) +		return sTheInstance.mImmGetContext(hwnd);  +	return 0; +} + +//static  +BOOL		LLWinImm::releaseContext(HWND hwnd, HIMC himc) +{  +	if ( sTheInstance.mImmIsIME ) +		return sTheInstance.mImmReleaseContext(hwnd, himc);  +	return FALSE; +} + +// static  +BOOL		LLWinImm::getOpenStatus(HIMC himc) +{  +	if ( sTheInstance.mImmGetOpenStatus ) +		return sTheInstance.mImmGetOpenStatus(himc);  +	return FALSE; +} + +// static  +BOOL		LLWinImm::setOpenStatus(HIMC himc, BOOL status)									 +{  +	if ( sTheInstance.mImmSetOpenStatus ) +		return sTheInstance.mImmSetOpenStatus(himc, status);  +	return FALSE; +} + +// static  +BOOL		LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)	 +{  +	if ( sTheInstance.mImmGetConversionStatus ) +		return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence);  +	return FALSE; +} + +// static  +BOOL		LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)		 +{  +	if ( sTheInstance.mImmSetConversionStatus ) +		return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence);  +	return FALSE; +} + +// static  +BOOL		LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					 +{  +	if ( sTheInstance.mImmGetCompostitionWindow ) +		return sTheInstance.mImmGetCompostitionWindow(himc, form);	 +	return FALSE; +} + +// static  +BOOL		LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					 +{  +	if ( sTheInstance.mImmSetCompostitionWindow ) +		return sTheInstance.mImmSetCompostitionWindow(himc, form);	 +	return FALSE; +} + + +// static  +LONG		LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)					 +{  +	if ( sTheInstance.mImmGetCompositionString ) +		return sTheInstance.mImmGetCompositionString(himc, index, data, length);	 +	return FALSE; +} + + +// static  +BOOL		LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)					 +{  +	if ( sTheInstance.mImmSetCompositionString ) +		return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);	 +	return FALSE; +} + +// static  +BOOL		LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)					 +{  +	if ( sTheInstance.mImmSetCompositionFont ) +		return sTheInstance.mImmSetCompositionFont(himc, pFont);	 +	return FALSE; +} + +// static  +BOOL		LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)					 +{  +	if ( sTheInstance.mImmSetCandidateWindow ) +		return sTheInstance.mImmSetCandidateWindow(himc, form);	 +	return FALSE; +} + +// static  +BOOL		LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)					 +{  +	if ( sTheInstance.mImmNotifyIME ) +		return sTheInstance.mImmNotifyIME(himc, action, index, value);	 +	return FALSE; +} + + + + +// ---------------------------------------------------------------------------------------- +LLWinImm::~LLWinImm() +{ +	if (mHImmDll != NULL) +	{ +		FreeLibrary(mHImmDll); +		mHImmDll = NULL; +	} +} + + +LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, +							 const std::string& title, const std::string& name, S32 x, S32 y, S32 width, +							 S32 height, U32 flags,  +							 BOOL fullscreen, BOOL clearBg, +							 BOOL disable_vsync, BOOL use_gl, +							 BOOL ignore_pixel_depth, +							 U32 fsaa_samples) +	: LLWindow(callbacks, fullscreen, flags) +{ +	mFSAASamples = fsaa_samples; +	mIconResource = gIconResource; +	mOverrideAspectRatio = 0.f; +	mNativeAspectRatio = 0.f; +	mMousePositionModified = FALSE; +	mInputProcessingPaused = FALSE; +	mPreeditor = NULL; +	mhDC = NULL; +	mhRC = NULL; + +	// Initialize the keyboard +	gKeyboard = new LLKeyboardWin32(); +	gKeyboard->setCallbacks(callbacks); + +	// Initialize the Drag and Drop functionality +	mDragDrop = new LLDragDropWin32; + +	// Initialize (boot strap) the Language text input management, +	// based on the system's (user's) default settings. +	allowLanguageTextInput(mPreeditor, FALSE); + +	WNDCLASS		wc; +	RECT			window_rect; + +	// Set the window title +	if (title.empty()) +	{ +		mWindowTitle = new WCHAR[50]; +		wsprintf(mWindowTitle, L"OpenGL Window"); +	} +	else +	{ +		mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars. +		mbstowcs(mWindowTitle, title.c_str(), 255); +		mWindowTitle[255] = 0; +	} + +	// Set the window class name +	if (name.empty()) +	{ +		mWindowClassName = new WCHAR[50]; +		wsprintf(mWindowClassName, L"OpenGL Window"); +	} +	else +	{ +		mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars. +		mbstowcs(mWindowClassName, name.c_str(), 255); +		mWindowClassName[255] = 0; +	} + + +	// We're not clipping yet +	SetRect( &mOldMouseClip, 0, 0, 0, 0 ); + +	// Make an instance of our window then define the window class +	mhInstance = GetModuleHandle(NULL); +	mWndProc = NULL; + +	mSwapMethod = SWAP_METHOD_UNDEFINED; + +	// No WPARAM yet. +	mLastSizeWParam = 0; + +	// Windows GDI rects don't include rightmost pixel +	window_rect.left = (long) 0; +	window_rect.right = (long) width; +	window_rect.top = (long) 0; +	window_rect.bottom = (long) height; + +	// Grab screen size to sanitize the window +	S32 window_border_y = GetSystemMetrics(SM_CYBORDER); +	S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);  +	S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);  +	S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); +	S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); + +	if (x < virtual_screen_x) x = virtual_screen_x; +	if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y; + +	if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width; +	if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height; + +	if (!sIsClassRegistered) +	{ +		// Force redraw when resized and create a private device context + +		// Makes double click messages. +		wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + +		// Set message handler function +		wc.lpfnWndProc = (WNDPROC) mainWindowProc; + +		// unused +		wc.cbClsExtra = 0; +		wc.cbWndExtra = 0; + +		wc.hInstance = mhInstance; +		wc.hIcon = LoadIcon(mhInstance, mIconResource); + +		// We will set the cursor ourselves +		wc.hCursor = NULL; + +		// background color is not used +		if (clearBg) +		{ +			wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); +		} +		else +		{ +			wc.hbrBackground = (HBRUSH) NULL; +		} + +		// we don't use windows menus +		wc.lpszMenuName = NULL; + +		wc.lpszClassName = mWindowClassName; + +		if (!RegisterClass(&wc)) +		{ +			OSMessageBox(mCallbacks->translateString("MBRegClassFailed"),  +				mCallbacks->translateString("MBError"), OSMB_OK); +			return; +		} +		sIsClassRegistered = TRUE; +	} + +	//----------------------------------------------------------------------- +	// Get the current refresh rate +	//----------------------------------------------------------------------- + +	DEVMODE dev_mode; +	DWORD current_refresh; +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) +	{ +		current_refresh = dev_mode.dmDisplayFrequency; +		mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight); +	} +	else +	{ +		current_refresh = 60; +	} + +	//----------------------------------------------------------------------- +	// Drop resolution and go fullscreen +	// use a display mode with our desired size and depth, with a refresh +	// rate as close at possible to the users' default +	//----------------------------------------------------------------------- +	if (mFullscreen) +	{ +		BOOL success = FALSE; +		DWORD closest_refresh = 0; + +		for (S32 mode_num = 0;; mode_num++) +		{ +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) +			{ +				break; +			} + +			if (dev_mode.dmPelsWidth == width && +				dev_mode.dmPelsHeight == height && +				dev_mode.dmBitsPerPel == BITS_PER_PIXEL) +			{ +				success = TRUE; +				if ((dev_mode.dmDisplayFrequency - current_refresh) +					< (closest_refresh - current_refresh)) +				{ +					closest_refresh = dev_mode.dmDisplayFrequency; +				} +			} +		} + +		if (closest_refresh == 0) +		{ +			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; +			success = FALSE; +		} + +		// If we found a good resolution, use it. +		if (success) +		{ +			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); +		} + +		// Keep a copy of the actual current device mode in case we minimize  +		// and change the screen resolution.   JC +		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); + +		// If it failed, we don't want to run fullscreen +		if (success) +		{ +			mFullscreen = TRUE; +			mFullscreenWidth   = dev_mode.dmPelsWidth; +			mFullscreenHeight  = dev_mode.dmPelsHeight; +			mFullscreenBits    = dev_mode.dmBitsPerPel; +			mFullscreenRefresh = dev_mode.dmDisplayFrequency; + +			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth +				<< "x"   << dev_mode.dmPelsHeight +				<< "x"   << dev_mode.dmBitsPerPel +				<< " @ " << dev_mode.dmDisplayFrequency +				<< LL_ENDL; +		} +		else +		{ +			mFullscreen = FALSE; +			mFullscreenWidth   = -1; +			mFullscreenHeight  = -1; +			mFullscreenBits    = -1; +			mFullscreenRefresh = -1; + +			std::map<std::string,std::string> args; +			args["[WIDTH]"] = llformat("%d", width); +			args["[HEIGHT]"] = llformat ("%d", height); +			OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args), +				mCallbacks->translateString("MBError"), OSMB_OK); +		} +	} + +	// TODO: add this after resolving _WIN32_WINNT issue +	//	if (!fullscreen) +	//	{ +	//		TRACKMOUSEEVENT track_mouse_event; +	//		track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); +	//		track_mouse_event.dwFlags = TME_LEAVE; +	//		track_mouse_event.hwndTrack = mWindowHandle; +	//		track_mouse_event.dwHoverTime = HOVER_DEFAULT; +	//		TrackMouseEvent( &track_mouse_event );  +	//	} + + +	//----------------------------------------------------------------------- +	// Create GL drawing context +	//----------------------------------------------------------------------- +	LLCoordScreen windowPos(x,y); +	LLCoordScreen windowSize(window_rect.right - window_rect.left, +							 window_rect.bottom - window_rect.top); +	if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos)) +	{ +		return; +	} +	 +	//start with arrow cursor +	initCursors(); +	setCursor( UI_CURSOR_ARROW ); + +	// Initialize (boot strap) the Language text input management, +	// based on the system's (or user's) default settings. +	allowLanguageTextInput(NULL, FALSE); +} + + +LLWindowWin32::~LLWindowWin32() +{ +	delete mDragDrop; + +	delete [] mWindowTitle; +	mWindowTitle = NULL; + +	delete [] mSupportedResolutions; +	mSupportedResolutions = NULL; + +	delete mWindowClassName; +	mWindowClassName = NULL; +} + +void LLWindowWin32::show() +{ +	ShowWindow(mWindowHandle, SW_SHOW); +	SetForegroundWindow(mWindowHandle); +	SetFocus(mWindowHandle); +} + +void LLWindowWin32::hide() +{ +	setMouseClipping(FALSE); +	ShowWindow(mWindowHandle, SW_HIDE); +} + +//virtual +void LLWindowWin32::minimize() +{ +	setMouseClipping(FALSE); +	showCursor(); +	ShowWindow(mWindowHandle, SW_MINIMIZE); +} + +//virtual +void LLWindowWin32::restore() +{ +	ShowWindow(mWindowHandle, SW_RESTORE); +	SetForegroundWindow(mWindowHandle); +	SetFocus(mWindowHandle); +} + + +// close() destroys all OS-specific code associated with a window. +// Usually called from LLWindowManager::destroyWindow() +void LLWindowWin32::close() +{ +	LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL; +	// Is window is already closed? +	if (!mWindowHandle) +	{ +		return; +	} + +	mDragDrop->reset(); + +	// Make sure cursor is visible and we haven't mangled the clipping state. +	setMouseClipping(FALSE); +	showCursor(); + +	// Go back to screen mode written in the registry. +	if (mFullscreen) +	{ +		resetDisplayResolution(); +	} + +	// Clean up remaining GL state +	LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL; +	gGLManager.shutdownGL(); + +	LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL; +	if (mhRC) +	{ +		if (!wglMakeCurrent(NULL, NULL)) +		{ +			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; +		} + +		if (!wglDeleteContext(mhRC)) +		{ +			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; +		} + +		mhRC = NULL; +	} + +	// Restore gamma to the system values. +	restoreGamma(); + +	if (mhDC && !ReleaseDC(mWindowHandle, mhDC)) +	{ +		LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL; +		mhDC = NULL; +	} + +	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; +	 +	// Don't process events in our mainWindowProc any longer. +	SetWindowLong(mWindowHandle, GWL_USERDATA, NULL); + +	// Make sure we don't leave a blank toolbar button. +	ShowWindow(mWindowHandle, SW_HIDE); + +	// This causes WM_DESTROY to be sent *immediately* +	if (!DestroyWindow(mWindowHandle)) +	{ +		OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), +			mCallbacks->translateString("MBShutdownErr"), +			OSMB_OK); +	} + +	mWindowHandle = NULL; +} + +BOOL LLWindowWin32::isValid() +{ +	return (mWindowHandle != NULL); +} + +BOOL LLWindowWin32::getVisible() +{ +	return (mWindowHandle && IsWindowVisible(mWindowHandle)); +} + +BOOL LLWindowWin32::getMinimized() +{ +	return (mWindowHandle && IsIconic(mWindowHandle)); +} + +BOOL LLWindowWin32::getMaximized() +{ +	return (mWindowHandle && IsZoomed(mWindowHandle)); +} + +BOOL LLWindowWin32::maximize() +{ +	BOOL success = FALSE; +	if (!mWindowHandle) return success; + +	WINDOWPLACEMENT placement; +	placement.length = sizeof(WINDOWPLACEMENT); + +	success = GetWindowPlacement(mWindowHandle, &placement); +	if (!success) return success; + +	placement.showCmd = SW_MAXIMIZE; + +	success = SetWindowPlacement(mWindowHandle, &placement); +	return success; +} + +BOOL LLWindowWin32::getFullscreen() +{ +	return mFullscreen; +} + +BOOL LLWindowWin32::getPosition(LLCoordScreen *position) +{ +	RECT window_rect; + +	if (!mWindowHandle || +		!GetWindowRect(mWindowHandle, &window_rect) || +		NULL == position) +	{ +		return FALSE; +	} + +	position->mX = window_rect.left; +	position->mY = window_rect.top; +	return TRUE; +} + +BOOL LLWindowWin32::getSize(LLCoordScreen *size) +{ +	RECT window_rect; + +	if (!mWindowHandle || +		!GetWindowRect(mWindowHandle, &window_rect) || +		NULL == size) +	{ +		return FALSE; +	} + +	size->mX = window_rect.right - window_rect.left; +	size->mY = window_rect.bottom - window_rect.top; +	return TRUE; +} + +BOOL LLWindowWin32::getSize(LLCoordWindow *size) +{ +	RECT client_rect; + +	if (!mWindowHandle || +		!GetClientRect(mWindowHandle, &client_rect) || +		NULL == size) +	{ +		return FALSE; +	} + +	size->mX = client_rect.right - client_rect.left; +	size->mY = client_rect.bottom - client_rect.top; +	return TRUE; +} + +BOOL LLWindowWin32::setPosition(const LLCoordScreen position) +{ +	LLCoordScreen size; + +	if (!mWindowHandle) +	{ +		return FALSE; +	} +	getSize(&size); +	moveWindow(position, size); +	return TRUE; +} + +BOOL LLWindowWin32::setSize(const LLCoordScreen size) +{ +	LLCoordScreen position; + +	getPosition(&position); +	if (!mWindowHandle) +	{ +		return FALSE; +	} + +	moveWindow(position, size); +	return TRUE; +} + +// changing fullscreen resolution +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) +{ +	GLuint	pixel_format; +	DEVMODE dev_mode; +	DWORD	current_refresh; +	DWORD	dw_ex_style; +	DWORD	dw_style; +	RECT	window_rect; +	S32 width = size.mX; +	S32 height = size.mY; +	BOOL auto_show = FALSE; + +	if (mhRC) +	{ +		auto_show = TRUE; +		resetDisplayResolution(); +	} + +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) +	{ +		current_refresh = dev_mode.dmDisplayFrequency; +	} +	else +	{ +		current_refresh = 60; +	} + +	gGLManager.shutdownGL(); +	//destroy gl context +	if (mhRC) +	{ +		if (!wglMakeCurrent(NULL, NULL)) +		{ +			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; +		} + +		if (!wglDeleteContext(mhRC)) +		{ +			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; +		} + +		mhRC = NULL; +	} + +	if (fullscreen) +	{ +		mFullscreen = TRUE; +		BOOL success = FALSE; +		DWORD closest_refresh = 0; + +		for (S32 mode_num = 0;; mode_num++) +		{ +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) +			{ +				break; +			} + +			if (dev_mode.dmPelsWidth == width && +				dev_mode.dmPelsHeight == height && +				dev_mode.dmBitsPerPel == BITS_PER_PIXEL) +			{ +				success = TRUE; +				if ((dev_mode.dmDisplayFrequency - current_refresh) +					< (closest_refresh - current_refresh)) +				{ +					closest_refresh = dev_mode.dmDisplayFrequency; +				} +			} +		} + +		if (closest_refresh == 0) +		{ +			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; +			return FALSE; +		} + +		// If we found a good resolution, use it. +		if (success) +		{ +			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); +		} + +		// Keep a copy of the actual current device mode in case we minimize  +		// and change the screen resolution.   JC +		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); + +		if (success) +		{ +			mFullscreen = TRUE; +			mFullscreenWidth   = dev_mode.dmPelsWidth; +			mFullscreenHeight  = dev_mode.dmPelsHeight; +			mFullscreenBits    = dev_mode.dmBitsPerPel; +			mFullscreenRefresh = dev_mode.dmDisplayFrequency; + +			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth +				<< "x"   << dev_mode.dmPelsHeight +				<< "x"   << dev_mode.dmBitsPerPel +				<< " @ " << dev_mode.dmDisplayFrequency +				<< LL_ENDL; + +			window_rect.left = (long) 0; +			window_rect.right = (long) width;			// Windows GDI rects don't include rightmost pixel +			window_rect.top = (long) 0; +			window_rect.bottom = (long) height; +			dw_ex_style = WS_EX_APPWINDOW; +			dw_style = WS_POPUP; + +			// Move window borders out not to cover window contents +			AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); +		} +		// If it failed, we don't want to run fullscreen +		else +		{ +			mFullscreen = FALSE; +			mFullscreenWidth   = -1; +			mFullscreenHeight  = -1; +			mFullscreenBits    = -1; +			mFullscreenRefresh = -1; + +			LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; +			return FALSE; +		} +	} +	else +	{ +		mFullscreen = FALSE; +		window_rect.left = (long) (posp ? posp->mX : 0); +		window_rect.right = (long) width + window_rect.left;			// Windows GDI rects don't include rightmost pixel +		window_rect.top = (long) (posp ? posp->mY : 0); +		window_rect.bottom = (long) height + window_rect.top; +		// Window with an edge +		dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; +		dw_style = WS_OVERLAPPEDWINDOW; +	} + +	// don't post quit messages when destroying old windows +	mPostQuit = FALSE; + +	// create window +	DestroyWindow(mWindowHandle); +	mWindowHandle = CreateWindowEx(dw_ex_style, +		mWindowClassName, +		mWindowTitle, +		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, +		window_rect.left,								// x pos +		window_rect.top,								// y pos +		window_rect.right - window_rect.left,			// width +		window_rect.bottom - window_rect.top,			// height +		NULL, +		NULL, +		mhInstance, +		NULL); + +	//----------------------------------------------------------------------- +	// Create GL drawing context +	//----------------------------------------------------------------------- +	static PIXELFORMATDESCRIPTOR pfd = +	{ +		sizeof(PIXELFORMATDESCRIPTOR),  +			1, +			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,  +			PFD_TYPE_RGBA, +			BITS_PER_PIXEL, +			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused +			8,					// alpha bits +			0,					// alpha shift +			0,					// accum bits +			0, 0, 0, 0,			// accum RGBA +			24,					// depth bits +			8,					// stencil bits, avi added for stencil test +			0, +			PFD_MAIN_PLANE, +			0, +			0, 0, 0 +	}; + +	if (!(mhDC = GetDC(mWindowHandle))) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBDevContextErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd))) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	// Verify what pixel format we actually received. +	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), +		&pfd)) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (pfd.cColorBits < 32) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (pfd.cAlphaBits < 8) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBAlpha"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!SetPixelFormat(mhDC, pixel_format, &pfd)) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!(mhRC = wglCreateContext(mhDC))) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!wglMakeCurrent(mhDC, mhRC)) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), +			mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	gGLManager.initWGL(); + +	if (wglChoosePixelFormatARB) +	{ +		// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we +		// can get exactly what we want. +		GLint attrib_list[256]; +		S32 cur_attrib = 0; + +		attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB; +		attrib_list[cur_attrib++] = 24; + +		attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB; +		attrib_list[cur_attrib++] = 8; + +		attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB; +		attrib_list[cur_attrib++] = GL_TRUE; + +		attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB; +		attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB; + +		attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB; +		attrib_list[cur_attrib++] = GL_TRUE; + +		attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB; +		attrib_list[cur_attrib++] = GL_TRUE; + +		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB; +		attrib_list[cur_attrib++] = 24; + +		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB; +		attrib_list[cur_attrib++] = 8; + +		U32 end_attrib = 0; +		if (mFSAASamples > 0) +		{ +			end_attrib = cur_attrib; +			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB; +			attrib_list[cur_attrib++] = GL_TRUE; + +			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB; +			attrib_list[cur_attrib++] = mFSAASamples; +		} + +		// End the list +		attrib_list[cur_attrib++] = 0; + +		GLint pixel_formats[256]; +		U32 num_formats = 0; + +		// First we try and get a 32 bit depth pixel format +		BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); +		if (!result) +		{ +			close(); +			show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit"); +			return FALSE; +		} + +		if (!num_formats) +		{ +			if (end_attrib > 0) +			{ +				LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL; +				attrib_list[end_attrib] = 0; + +				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); +				if (!result) +				{ +					close(); +					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA"); +					return FALSE; +				} +			} + +			if (!num_formats) +			{ +				LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL; +				// Try 24-bit format +				attrib_list[1] = 24; +				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); +				if (!result) +				{ +					close(); +					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit"); +					return FALSE; +				} + +				if (!num_formats) +				{ +					LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL; +					attrib_list[1] = 16; +					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); +					if (!result || !num_formats) +					{ +						close(); +						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit"); +						return FALSE; +					} +				} +			} + +			LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL; +		} + +		 + +		S32 swap_method = 0; +		S32 cur_format = num_formats-1; +		GLint swap_query = WGL_SWAP_METHOD_ARB; + +		BOOL found_format = FALSE; + +		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) +		{ +			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0) +			{ +				found_format = TRUE; +			} +			else +			{ +				--cur_format; +			} +		} +		 +		pixel_format = pixel_formats[cur_format]; +		 +		if (mhDC != 0)											// Does The Window Have A Device Context? +		{ +			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero +			if (mhRC != 0)										// Does The Window Have A Rendering Context? +			{ +				wglDeleteContext (mhRC);							// Release The Rendering Context +				mhRC = 0;										// Zero The Rendering Context + +			} +			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context +			mhDC = 0;											// Zero The Device Context +		} +		DestroyWindow (mWindowHandle);									// Destroy The Window +		 + +		mWindowHandle = CreateWindowEx(dw_ex_style, +			mWindowClassName, +			mWindowTitle, +			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, +			window_rect.left,								// x pos +			window_rect.top,								// y pos +			window_rect.right - window_rect.left,			// width +			window_rect.bottom - window_rect.top,			// height +			NULL, +			NULL, +			mhInstance, +			NULL); + +		if (!(mhDC = GetDC(mWindowHandle))) +		{ +			close(); +			OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); +			return FALSE; +		} + +		if (!SetPixelFormat(mhDC, pixel_format, &pfd)) +		{ +			close(); +			OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), +				mCallbacks->translateString("MBError"), OSMB_OK); +			return FALSE; +		} + +		if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) +		{ +			switch (swap_method) +			{ +			case WGL_SWAP_EXCHANGE_ARB: +				mSwapMethod = SWAP_METHOD_EXCHANGE; +				LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL; +				break; +			case WGL_SWAP_COPY_ARB: +				mSwapMethod = SWAP_METHOD_COPY; +				LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL; +				break; +			case WGL_SWAP_UNDEFINED_ARB: +				mSwapMethod = SWAP_METHOD_UNDEFINED; +				LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL; +				break; +			default: +				mSwapMethod = SWAP_METHOD_UNDEFINED; +				LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL; +				break; +			} +		}		 +	} +	else +	{ +		LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL; +	} + +	// Verify what pixel format we actually received. +	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), +		&pfd)) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits)  +		<< " Alpha Bits " << S32(pfd.cAlphaBits) +		<< " Depth Bits " << S32(pfd.cDepthBits)  +		<< LL_ENDL; + +	// make sure we have 32 bits per pixel +	if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (pfd.cAlphaBits < 8) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!(mhRC = wglCreateContext(mhDC))) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!wglMakeCurrent(mhDC, mhRC)) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	if (!gGLManager.initGL()) +	{ +		close(); +		OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); +		return FALSE; +	} + +	// Disable vertical sync for swap +	if (disable_vsync && wglSwapIntervalEXT) +	{ +		LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL; +		wglSwapIntervalEXT(0); +	} +	else +	{ +		LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL; +	} + +	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this); + +	// register this window as handling drag/drop events from the OS +	DragAcceptFiles( mWindowHandle, TRUE ); + +	mDragDrop->init( mWindowHandle ); +	 +	//register joystick timer callback +	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer + +	// ok to post quit messages now +	mPostQuit = TRUE; + +	if (auto_show) +	{ +		show(); +		glClearColor(0.0f, 0.0f, 0.0f, 0.f); +		glClear(GL_COLOR_BUFFER_BIT); +		swapBuffers(); +	} + +	return TRUE; +} + +void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size ) +{ +	if( mIsMouseClipping ) +	{ +		RECT client_rect_in_screen_space; +		if( getClientRectInScreenSpace( &client_rect_in_screen_space ) ) +		{ +			ClipCursor( &client_rect_in_screen_space ); +		} +	} + +	// if the window was already maximized, MoveWindow seems to still set the maximized flag even if +	// the window is smaller than maximized. +	// So we're going to do a restore first (which is a ShowWindow call) (SL-44655). + +	// THIS CAUSES DEV-15484 and DEV-15949  +	//ShowWindow(mWindowHandle, SW_RESTORE); +	// NOW we can call MoveWindow +	MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); +} + +BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) +{ +	LLCoordScreen screen_pos; + +	mMousePositionModified = TRUE; +	if (!mWindowHandle) +	{ +		return FALSE; +	} + +	if (!convertCoords(position, &screen_pos)) +	{ +		return FALSE; +	} + +	// Inform the application of the new mouse position (needed for per-frame +	// hover/picking to function). +	LLCoordGL gl_pos; +	convertCoords(position, &gl_pos); +	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); +	 +	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. +	// Because we have preemptively notified the application of the new +	// mouse position via handleMouseMove() above, we need to clear out +	// any stale mouse move events.  RN/JC +	MSG msg; +	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) +	{ } + +	return SetCursorPos(screen_pos.mX, screen_pos.mY); +} + +BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) +{ +	POINT cursor_point; +	LLCoordScreen screen_pos; + +	if (!mWindowHandle || +		!GetCursorPos(&cursor_point)) +	{ +		return FALSE; +	} + +	screen_pos.mX = cursor_point.x; +	screen_pos.mY = cursor_point.y; + +	return convertCoords(screen_pos, position); +} + +void LLWindowWin32::hideCursor() +{ +	while (ShowCursor(FALSE) >= 0) +	{ +		// nothing, wait for cursor to push down +	} +	mCursorHidden = TRUE; +	mHideCursorPermanent = TRUE; +} + +void LLWindowWin32::showCursor() +{ +	// makes sure the cursor shows up +	while (ShowCursor(TRUE) < 0) +	{ +		// do nothing, wait for cursor to pop out +	} +	mCursorHidden = FALSE; +	mHideCursorPermanent = FALSE; +} + +void LLWindowWin32::showCursorFromMouseMove() +{ +	if (!mHideCursorPermanent) +	{ +		showCursor(); +	} +} + +void LLWindowWin32::hideCursorUntilMouseMove() +{ +	if (!mHideCursorPermanent) +	{ +		hideCursor(); +		mHideCursorPermanent = FALSE; +	} +} + +BOOL LLWindowWin32::isCursorHidden() +{ +	return mCursorHidden; +} + + +HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name) +{ +	return (HCURSOR)LoadImage(mhInstance, +							  name, +							  IMAGE_CURSOR, +							  0,	// default width +							  0,	// default height +							  LR_DEFAULTCOLOR); +} + + +void LLWindowWin32::initCursors() +{ +	mCursor[ UI_CURSOR_ARROW ]		= LoadCursor(NULL, IDC_ARROW); +	mCursor[ UI_CURSOR_WAIT ]		= LoadCursor(NULL, IDC_WAIT); +	mCursor[ UI_CURSOR_HAND ]		= LoadCursor(NULL, IDC_HAND); +	mCursor[ UI_CURSOR_IBEAM ]		= LoadCursor(NULL, IDC_IBEAM); +	mCursor[ UI_CURSOR_CROSS ]		= LoadCursor(NULL, IDC_CROSS); +	mCursor[ UI_CURSOR_SIZENWSE ]	= LoadCursor(NULL, IDC_SIZENWSE); +	mCursor[ UI_CURSOR_SIZENESW ]	= LoadCursor(NULL, IDC_SIZENESW); +	mCursor[ UI_CURSOR_SIZEWE ]		= LoadCursor(NULL, IDC_SIZEWE);   +	mCursor[ UI_CURSOR_SIZENS ]		= LoadCursor(NULL, IDC_SIZENS);   +	mCursor[ UI_CURSOR_NO ]			= LoadCursor(NULL, IDC_NO); +	mCursor[ UI_CURSOR_WORKING ]	= LoadCursor(NULL, IDC_APPSTARTING);  + +	HMODULE module = GetModuleHandle(NULL); +	mCursor[ UI_CURSOR_TOOLGRAB ]	= LoadCursor(module, TEXT("TOOLGRAB")); +	mCursor[ UI_CURSOR_TOOLLAND ]	= LoadCursor(module, TEXT("TOOLLAND")); +	mCursor[ UI_CURSOR_TOOLFOCUS ]	= LoadCursor(module, TEXT("TOOLFOCUS")); +	mCursor[ UI_CURSOR_TOOLCREATE ]	= LoadCursor(module, TEXT("TOOLCREATE")); +	mCursor[ UI_CURSOR_ARROWDRAG ]	= LoadCursor(module, TEXT("ARROWDRAG")); +	mCursor[ UI_CURSOR_ARROWCOPY ]	= LoadCursor(module, TEXT("ARROWCOPY")); +	mCursor[ UI_CURSOR_ARROWDRAGMULTI ]	= LoadCursor(module, TEXT("ARROWDRAGMULTI")); +	mCursor[ UI_CURSOR_ARROWCOPYMULTI ]	= LoadCursor(module, TEXT("ARROWCOPYMULTI")); +	mCursor[ UI_CURSOR_NOLOCKED ]	= LoadCursor(module, TEXT("NOLOCKED")); +	mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED")); +	mCursor[ UI_CURSOR_GRABLOCKED ]	= LoadCursor(module, TEXT("GRABLOCKED")); +	mCursor[ UI_CURSOR_TOOLTRANSLATE ]	= LoadCursor(module, TEXT("TOOLTRANSLATE")); +	mCursor[ UI_CURSOR_TOOLROTATE ]	= LoadCursor(module, TEXT("TOOLROTATE"));  +	mCursor[ UI_CURSOR_TOOLSCALE ]	= LoadCursor(module, TEXT("TOOLSCALE")); +	mCursor[ UI_CURSOR_TOOLCAMERA ]	= LoadCursor(module, TEXT("TOOLCAMERA")); +	mCursor[ UI_CURSOR_TOOLPAN ]	= LoadCursor(module, TEXT("TOOLPAN")); +	mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN")); +	mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3")); +	mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE")); + +	// Color cursors +	mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY")); +	mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE")); +	mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN")); + +	// Note: custom cursors that are not found make LoadCursor() return NULL. +	for( S32 i = 0; i < UI_CURSOR_COUNT; i++ ) +	{ +		if( !mCursor[i] ) +		{ +			mCursor[i] = LoadCursor(NULL, IDC_ARROW); +		} +	} +} + + + +void LLWindowWin32::setCursor(ECursorType cursor) +{ +	if (cursor == UI_CURSOR_ARROW +		&& mBusyCount > 0) +	{ +		cursor = UI_CURSOR_WORKING; +	} + +	if( mCurrentCursor != cursor ) +	{ +		mCurrentCursor = cursor; +		SetCursor( mCursor[cursor] ); +	} +} + +ECursorType LLWindowWin32::getCursor() const +{ +	return mCurrentCursor; +} + +void LLWindowWin32::captureMouse() +{ +	SetCapture(mWindowHandle); +} + +void LLWindowWin32::releaseMouse() +{ +	// *NOTE:Mani ReleaseCapture will spawn new windows messages... +	// which will in turn call our MainWindowProc. It therefore requires +	// pausing *and more importantly resumption* of the mainlooptimeout... +	// just like DispatchMessage below. +	mCallbacks->handlePauseWatchdog(this); +	ReleaseCapture(); +	mCallbacks->handleResumeWatchdog(this); +} + + +void LLWindowWin32::delayInputProcessing() +{ +	mInputProcessingPaused = TRUE; +} + +void LLWindowWin32::gatherInput() +{ +	MSG		msg; +	int		msg_count = 0; + +	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT); + +	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE) +	{ +		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput"); +		TranslateMessage(&msg); + +		// turn watchdog off in here to not fail if windows is doing something wacky +		mCallbacks->handlePauseWatchdog(this); +		DispatchMessage(&msg); +		mCallbacks->handleResumeWatchdog(this); +		msg_count++; + +		if ( mInputProcessingPaused ) +		{ +			break; +		} +		/* Attempted workaround for problem where typing fast and hitting +		   return would result in only part of the text being sent. JC + +		BOOL key_posted = TranslateMessage(&msg); +		DispatchMessage(&msg); +		msg_count++; + +		// If a key was translated, a WM_CHAR might have been posted to the end +		// of the event queue.  We need it immediately. +		if (key_posted && msg.message == WM_KEYDOWN) +		{ +			if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE)) +			{ +				TranslateMessage(&msg); +				DispatchMessage(&msg); +				msg_count++; +			} +		} +		*/ +		mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput"); +		// For async host by name support.  Really hacky. +		if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) +		{ +			gAsyncMsgCallback(msg); +		} +	} + +	mInputProcessingPaused = FALSE; + +	// clear this once we've processed all mouse messages that might have occurred after +	// we slammed the mouse position +	mMousePositionModified = FALSE; +} + +static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard"); +static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse"); + +LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) +{ +	LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA); + + +	if (NULL != window_imp) +	{ +		window_imp->mCallbacks->handleResumeWatchdog(window_imp); +		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc"); +		// Has user provided their own window callback? +		if (NULL != window_imp->mWndProc) +		{ +			if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) +			{ +				// user has handled window message +				return 0; +			} +		} + +		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc"); +		 +		// Juggle to make sure we can get negative positions for when +		// mouse is outside window. +		LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); + +		// This doesn't work, as LOWORD returns unsigned short. +		//LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); +		LLCoordGL gl_coord; + +		// pass along extended flag in mask +		MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; +		BOOL eat_keystroke = TRUE; + +		switch(u_msg) +		{ +			RECT	update_rect; +			S32		update_width; +			S32		update_height; + +		case WM_TIMER: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER"); +			window_imp->mCallbacks->handleTimerEvent(window_imp); +			break; + +		case WM_DEVICECHANGE: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE"); +			if (gDebugWindowProc) +			{ +				llinfos << "  WM_DEVICECHANGE: wParam=" << w_param  +						<< "; lParam=" << l_param << llendl; +			} +			if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) +			{ +				if (window_imp->mCallbacks->handleDeviceChange(window_imp)) +				{ +					return 0; +				} +			} +			break; + +		case WM_PAINT: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT"); +			GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); +			update_width = update_rect.right - update_rect.left + 1; +			update_height = update_rect.bottom - update_rect.top + 1; +			window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, +				update_width, update_height); +			break; +		case WM_PARENTNOTIFY: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY"); +			u_msg = u_msg; +			break; + +		case WM_SETCURSOR: +			// This message is sent whenever the cursor is moved in a window. +			// You need to set the appropriate cursor appearance. + +			// Only take control of cursor over client region of window +			// This allows Windows(tm) to handle resize cursors, etc. +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR"); +			if (LOWORD(l_param) == HTCLIENT) +			{ +				SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] ); +				return 0; +			} +			break; + +		case WM_ENTERMENULOOP: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP"); +			window_imp->mCallbacks->handleWindowBlock(window_imp); +			break; + +		case WM_EXITMENULOOP: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP"); +			window_imp->mCallbacks->handleWindowUnblock(window_imp); +			break; + +		case WM_ACTIVATEAPP: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP"); +			{ +				// This message should be sent whenever the app gains or loses focus. +				BOOL activating = (BOOL) w_param; +				BOOL minimized = window_imp->getMinimized(); + +				if (gDebugWindowProc) +				{ +					LL_INFOS("Window") << "WINDOWPROC ActivateApp " +						<< " activating " << S32(activating) +						<< " minimized " << S32(minimized) +						<< " fullscreen " << S32(window_imp->mFullscreen) +						<< LL_ENDL; +				} + +				if (window_imp->mFullscreen) +				{ +					// When we run fullscreen, restoring or minimizing the app needs  +					// to switch the screen resolution +					if (activating) +					{ +						window_imp->setFullscreenResolution(); +						window_imp->restore(); +					} +					else +					{ +						window_imp->minimize(); +						window_imp->resetDisplayResolution(); +					} +				} + +				window_imp->mCallbacks->handleActivateApp(window_imp, activating); + +				break; +			} + +		case WM_ACTIVATE: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE"); +			{ +				// Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE +				BOOL activating = (LOWORD(w_param) != WA_INACTIVE); + +				BOOL minimized = BOOL(HIWORD(w_param)); + +				if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) +				{ +					window_imp->interruptLanguageTextInput(); +				} + +				// JC - I'm not sure why, but if we don't report that we handled the  +				// WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work  +				// properly when we run fullscreen. +				if (gDebugWindowProc) +				{ +					LL_INFOS("Window") << "WINDOWPROC Activate " +						<< " activating " << S32(activating)  +						<< " minimized " << S32(minimized) +						<< LL_ENDL; +				} + +				// Don't handle this. +				break; +			} + +		case WM_QUERYOPEN: +			// TODO: use this to return a nice icon +			break; + +		case WM_SYSCOMMAND: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND"); +			switch(w_param) +			{ +			case SC_KEYMENU:  +				// Disallow the ALT key from triggering the default system menu. +				return 0;		 + +			case SC_SCREENSAVE: +			case SC_MONITORPOWER: +				// eat screen save messages and prevent them! +				return 0; +			} +			break; + +		case WM_CLOSE: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE"); +			// Will the app allow the window to close? +			if (window_imp->mCallbacks->handleCloseRequest(window_imp)) +			{ +				// Get the app to initiate cleanup. +				window_imp->mCallbacks->handleQuit(window_imp); +				// The app is responsible for calling destroyWindow when done with GL +			} +			return 0; + +		case WM_DESTROY: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY"); +			if (window_imp->shouldPostQuit()) +			{ +				PostQuitMessage(0);  // Posts WM_QUIT with an exit code of 0 +			} +			return 0; + +		case WM_COMMAND: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND"); +			if (!HIWORD(w_param)) // this message is from a menu +			{ +				window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param)); +			} +			break; + +		case WM_SYSKEYDOWN: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN"); +			// allow system keys, such as ALT-F4 to be processed by Windows +			eat_keystroke = FALSE; +		case WM_KEYDOWN: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); +			{ +				if (gDebugWindowProc) +				{ +					LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " +						<< " key " << S32(w_param)  +						<< LL_ENDL; +				} +				if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke) +				{ +					return 0; +				} +				// pass on to windows if we didn't handle it +				break; +			} +		case WM_SYSKEYUP: +			eat_keystroke = FALSE; +		case WM_KEYUP: +		{ +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); +			LLFastTimer t2(FTM_KEYHANDLER); + +			if (gDebugWindowProc) +			{ +				LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " +					<< " key " << S32(w_param)  +					<< LL_ENDL; +			} +			if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke) +			{ +				return 0; +			} + +			// pass on to windows +			break; +		} +		case WM_IME_SETCONTEXT: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT"); +			if (gDebugWindowProc) +			{ +				llinfos << "WM_IME_SETCONTEXT" << llendl; +			} +			if (LLWinImm::isAvailable() && window_imp->mPreeditor) +			{ +				l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; +				// Invoke DefWinProc with the modified LPARAM. +			} +			break; + +		case WM_IME_STARTCOMPOSITION: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION"); +			if (gDebugWindowProc) +			{ +				llinfos << "WM_IME_STARTCOMPOSITION" << llendl; +			} +			if (LLWinImm::isAvailable() && window_imp->mPreeditor) +			{ +				window_imp->handleStartCompositionMessage(); +				return 0; +			} +			break; + +		case WM_IME_ENDCOMPOSITION: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION"); +			if (gDebugWindowProc) +			{ +				llinfos << "WM_IME_ENDCOMPOSITION" << llendl; +			} +			if (LLWinImm::isAvailable() && window_imp->mPreeditor) +			{ +				return 0; +			} +			break; + +		case WM_IME_COMPOSITION: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION"); +			if (gDebugWindowProc) +			{ +				llinfos << "WM_IME_COMPOSITION" << llendl; +			} +			if (LLWinImm::isAvailable() && window_imp->mPreeditor) +			{ +				window_imp->handleCompositionMessage(l_param); +				return 0; +			} +			break; + +		case WM_IME_REQUEST: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST"); +			if (gDebugWindowProc) +			{ +				llinfos << "WM_IME_REQUEST" << llendl; +			} +			if (LLWinImm::isAvailable() && window_imp->mPreeditor) +			{ +				LRESULT result = 0; +				if (window_imp->handleImeRequests(w_param, l_param, &result)) +				{ +					return result; +				} +			} +			break; + +		case WM_CHAR: +			// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need +			// to figure out how that works. - Doug +			// +			// ... Well, I don't think so. +			// How it works is explained in Win32 API document, but WM_UNICHAR didn't work +			// as specified at least on Windows XP SP1 Japanese version.  I have never used +			// it since then, and I'm not sure whether it has been fixed now, but I don't think +			// it is worth trying.  The good old WM_CHAR works just fine even for supplementary +			// characters.  We just need to take care of surrogate pairs sent as two WM_CHAR's +			// by ourselves.  It is not that tough.  -- Alissa Sabre @ SL +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR"); +			if (gDebugWindowProc) +			{ +				LL_INFOS("Window") << "Debug WindowProc WM_CHAR " +					<< " key " << S32(w_param)  +					<< LL_ENDL; +			} +			// Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, +			// we *did* processed the event, so I believe we should not pass it to DefWindowProc... +			window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); +			return 0; + +		case WM_LBUTTONDOWN: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				if (LLWinImm::isAvailable() && window_imp->mPreeditor) +				{ +					window_imp->interruptLanguageTextInput(); +				} + +				// Because we move the cursor position in the app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_LBUTTONDBLCLK: +		//RN: ignore right button double clicks for now +		//case WM_RBUTTONDBLCLK: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK"); +				// Because we move the cursor position in the app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) ) +				{ +					return 0; +				} +			} +			break; + +		case WM_LBUTTONUP: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				//if (gDebugClicks) +				//{ +				//	LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; +				//} +				// Because we move the cursor position in the app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_RBUTTONDBLCLK: +		case WM_RBUTTONDOWN: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				if (LLWinImm::isAvailable() && window_imp->mPreeditor) +				{ +					window_imp->interruptLanguageTextInput(); +				} + +				// Because we move the cursor position in the llviewerapp, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_RBUTTONUP: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				// Because we move the cursor position in the app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_MBUTTONDOWN: +//		case WM_MBUTTONDBLCLK: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				if (LLWinImm::isAvailable() && window_imp->mPreeditor) +				{ +					window_imp->interruptLanguageTextInput(); +				} + +				// Because we move the cursor position in tllviewerhe app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_MBUTTONUP: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); +				LLFastTimer t2(FTM_MOUSEHANDLER); +				// Because we move the cursor position in the llviewer app, we need to query +				// to find out where the cursor at the time the event is handled. +				// If we don't do this, many clicks could get buffered up, and if the +				// first click changes the cursor position, all subsequent clicks +				// will occur at the wrong location.  JC +				LLCoordWindow cursor_coord_window; +				if (window_imp->mMousePositionModified) +				{ +					window_imp->getCursorPosition(&cursor_coord_window); +					window_imp->convertCoords(cursor_coord_window, &gl_coord); +				} +				else +				{ +					window_imp->convertCoords(window_coord, &gl_coord); +				} +				MASK mask = gKeyboard->currentMask(TRUE); +				// generate move event to update mouse coordinates +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) +				{ +					return 0; +				} +			} +			break; + +		case WM_MOUSEWHEEL: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL"); +				static short z_delta = 0; + +				RECT	client_rect; + +				// eat scroll events that occur outside our window, since we use mouse position to direct scroll +				// instead of keyboard focus +				// NOTE: mouse_coord is in *window* coordinates for scroll events +				POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + +				if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) +					&& GetClientRect(window_imp->mWindowHandle, &client_rect)) +				{ +					// we have a valid mouse point and client rect +					if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x +						|| mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) +					{ +						// mouse is outside of client rect, so don't do anything +						return 0; +					} +				} + +				S16 incoming_z_delta = HIWORD(w_param); +				z_delta += incoming_z_delta; +				// cout << "z_delta " << z_delta << endl; + +				// current mouse wheels report changes in increments of zDelta (+120, -120) +				// Future, higher resolution mouse wheels may report smaller deltas. +				// So we sum the deltas and only act when we've exceeded WHEEL_DELTA +				// +				// If the user rapidly spins the wheel, we can get messages with +				// large deltas, like 480 or so.  Thus we need to scroll more quickly. +				if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) +				{ +					window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); +					z_delta = 0; +				} +				return 0; +			} +			/* +			// TODO: add this after resolving _WIN32_WINNT issue +			case WM_MOUSELEAVE: +			{ +			window_imp->mCallbacks->handleMouseLeave(window_imp); + +			//				TRACKMOUSEEVENT track_mouse_event; +			//				track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); +			//				track_mouse_event.dwFlags = TME_LEAVE; +			//				track_mouse_event.hwndTrack = h_wnd; +			//				track_mouse_event.dwHoverTime = HOVER_DEFAULT; +			//				TrackMouseEvent( &track_mouse_event );  +			return 0; +			} +			*/ +			// Handle mouse movement within the window +		case WM_MOUSEMOVE: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); +				window_imp->convertCoords(window_coord, &gl_coord); +				MASK mask = gKeyboard->currentMask(TRUE); +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				return 0; +			} + +		case WM_SIZE: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE"); +				S32 width = S32( LOWORD(l_param) ); +				S32 height = S32( HIWORD(l_param) ); + +				if (gDebugWindowProc) +				{ +					BOOL maximized = ( w_param == SIZE_MAXIMIZED ); +					BOOL restored  = ( w_param == SIZE_RESTORED ); +					BOOL minimized = ( w_param == SIZE_MINIMIZED ); + +					LL_INFOS("Window") << "WINDOWPROC Size " +						<< width << "x" << height +						<< " max " << S32(maximized) +						<< " min " << S32(minimized) +						<< " rest " << S32(restored) +						<< LL_ENDL; +				} + +				// There's an odd behavior with WM_SIZE that I would call a bug. If  +				// the window is maximized, and you call MoveWindow() with a size smaller +				// than a maximized window, it ends up sending WM_SIZE with w_param set  +				// to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. +				// (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see  +				// LLWindowWin32::moveWindow in this file).  + +				// If we are now restored, but we weren't before, this +				// means that the window was un-minimized. +				if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) +				{ +					window_imp->mCallbacks->handleActivate(window_imp, TRUE); +				} + +				// handle case of window being maximized from fully minimized state +				if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) +				{ +					window_imp->mCallbacks->handleActivate(window_imp, TRUE); +				} + +				// Also handle the minimization case +				if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) +				{ +					window_imp->mCallbacks->handleActivate(window_imp, FALSE); +				} + +				// Actually resize all of our views +				if (w_param != SIZE_MINIMIZED) +				{ +					// Ignore updates for minimizing and minimized "windows" +					window_imp->mCallbacks->handleResize(	window_imp,  +						LOWORD(l_param),  +						HIWORD(l_param) ); +				} + +				window_imp->mLastSizeWParam = w_param; + +				return 0; +			} + +		case WM_SETFOCUS: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS"); +			if (gDebugWindowProc) +			{ +				LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; +			} +			window_imp->mCallbacks->handleFocus(window_imp); +			return 0; + +		case WM_KILLFOCUS: +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS"); +			if (gDebugWindowProc) +			{ +				LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; +			} +			window_imp->mCallbacks->handleFocusLost(window_imp); +			return 0; + +		case WM_COPYDATA: +			{ +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); +				// received a URL +				PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; +				window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); +			}; +			return 0;			 + +			break; +		} + +	window_imp->mCallbacks->handlePauseWatchdog(window_imp);	 +	} + + +	// pass unhandled messages down to Windows +	return DefWindowProc(h_wnd, u_msg, w_param, l_param); +} + +BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) +{ +	S32		client_height; +	RECT	client_rect; +	LLCoordWindow window_position; + +	if (!mWindowHandle || +		!GetClientRect(mWindowHandle, &client_rect) || +		NULL == to) +	{ +		return FALSE; +	} + +	to->mX = from.mX; +	client_height = client_rect.bottom - client_rect.top; +	to->mY = client_height - from.mY - 1; + +	return TRUE; +} + +BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) +{ +	S32		client_height; +	RECT	client_rect; + +	if (!mWindowHandle || +		!GetClientRect(mWindowHandle, &client_rect) || +		NULL == to) +	{ +		return FALSE; +	} + +	to->mX = from.mX; +	client_height = client_rect.bottom - client_rect.top; +	to->mY = client_height - from.mY - 1; + +	return TRUE; +} + +BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) +{	 +	POINT mouse_point; + +	mouse_point.x = from.mX; +	mouse_point.y = from.mY; +	BOOL result = ScreenToClient(mWindowHandle, &mouse_point); + +	if (result) +	{ +		to->mX = mouse_point.x; +		to->mY = mouse_point.y; +	} + +	return result; +} + +BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) +{ +	POINT mouse_point; + +	mouse_point.x = from.mX; +	mouse_point.y = from.mY; +	BOOL result = ClientToScreen(mWindowHandle, &mouse_point); + +	if (result) +	{ +		to->mX = mouse_point.x; +		to->mY = mouse_point.y; +	} + +	return result; +} + +BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) +{ +	LLCoordWindow window_coord; + +	if (!mWindowHandle || (NULL == to)) +	{ +		return FALSE; +	} + +	convertCoords(from, &window_coord); +	convertCoords(window_coord, to); +	return TRUE; +} + +BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) +{ +	LLCoordWindow window_coord; + +	if (!mWindowHandle || (NULL == to)) +	{ +		return FALSE; +	} + +	convertCoords(from, &window_coord); +	convertCoords(window_coord, to); +	return TRUE; +} + + +BOOL LLWindowWin32::isClipboardTextAvailable() +{ +	return IsClipboardFormatAvailable(CF_UNICODETEXT); +} + + +BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst) +{ +	BOOL success = FALSE; + +	if (IsClipboardFormatAvailable(CF_UNICODETEXT)) +	{ +		if (OpenClipboard(mWindowHandle)) +		{ +			HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT); +			if (h_data) +			{ +				WCHAR *utf16str = (WCHAR*) GlobalLock(h_data); +				if (utf16str) +				{ +					dst = utf16str_to_wstring(utf16str); +					LLWStringUtil::removeCRLF(dst); +					GlobalUnlock(h_data); +					success = TRUE; +				} +			} +			CloseClipboard(); +		} +	} + +	return success; +} + + +BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) +{ +	BOOL success = FALSE; + +	if (OpenClipboard(mWindowHandle)) +	{ +		EmptyClipboard(); + +		// Provide a copy of the data in Unicode format. +		LLWString sanitized_string(wstr); +		LLWStringUtil::addCRLF(sanitized_string); +		llutf16string out_utf16 = wstring_to_utf16str(sanitized_string); +		const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR); + +		// Memory is allocated and then ownership of it is transfered to the system. +		HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);  +		if (hglobal_copy_utf16) +		{ +			WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16); +			if (copy_utf16) +			{ +				memcpy(copy_utf16, out_utf16.c_str(), size_utf16);	/* Flawfinder: ignore */ +				GlobalUnlock(hglobal_copy_utf16); + +				if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16)) +				{ +					success = TRUE; +				} +			} +		} + +		CloseClipboard(); +	} + +	return success; +} + +// Constrains the mouse to the window. +void LLWindowWin32::setMouseClipping( BOOL b ) +{ +	if( b != mIsMouseClipping ) +	{ +		BOOL success = FALSE; + +		if( b ) +		{ +			GetClipCursor( &mOldMouseClip ); + +			RECT client_rect_in_screen_space; +			if( getClientRectInScreenSpace( &client_rect_in_screen_space ) ) +			{ +				success = ClipCursor( &client_rect_in_screen_space ); +			} +		} +		else +		{ +			// Must restore the old mouse clip, which may be set by another window. +			success = ClipCursor( &mOldMouseClip ); +			SetRect( &mOldMouseClip, 0, 0, 0, 0 ); +		} + +		if( success ) +		{ +			mIsMouseClipping = b; +		} +	} +} + +BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) +{ +	BOOL success = FALSE; + +	RECT client_rect; +	if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) ) +	{ +		POINT top_left; +		top_left.x = client_rect.left; +		top_left.y = client_rect.top; +		ClientToScreen(mWindowHandle, &top_left);  + +		POINT bottom_right; +		bottom_right.x = client_rect.right; +		bottom_right.y = client_rect.bottom; +		ClientToScreen(mWindowHandle, &bottom_right);  + +		SetRect( rectp, +			top_left.x, +			top_left.y, +			bottom_right.x, +			bottom_right.y ); + +		success = TRUE; +	} + +	return success; +} + +void LLWindowWin32::flashIcon(F32 seconds) +{ +	FLASHWINFO flash_info; + +	flash_info.cbSize = sizeof(FLASHWINFO); +	flash_info.hwnd = mWindowHandle; +	flash_info.dwFlags = FLASHW_TRAY; +	flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); +	flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds +	FlashWindowEx(&flash_info); +} + +F32 LLWindowWin32::getGamma() +{ +	return mCurrentGamma; +} + +BOOL LLWindowWin32::restoreGamma() +{ +	return SetDeviceGammaRamp(mhDC, mPrevGammaRamp); +} + +BOOL LLWindowWin32::setGamma(const F32 gamma) +{ +	mCurrentGamma = gamma; + +	LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL; + +	for ( int i = 0; i < 256; ++i ) +	{ +		int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f ); + +		int value = mult * i; + +		if ( value > 0xffff ) +			value = 0xffff; + +		mCurrentGammaRamp [ 0 * 256 + i ] =  +			mCurrentGammaRamp [ 1 * 256 + i ] =  +				mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value; +	}; + +	return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp ); +} + +void LLWindowWin32::setFSAASamples(const U32 fsaa_samples) +{ +	mFSAASamples = fsaa_samples; +} + +U32 LLWindowWin32::getFSAASamples() +{ +	return mFSAASamples; +} + +LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions) +{ +	if (!mSupportedResolutions) +	{ +		mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; +		DEVMODE dev_mode; + +		mNumSupportedResolutions = 0; +		for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++) +		{ +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) +			{ +				break; +			} + +			if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL && +				dev_mode.dmPelsWidth >= 800 && +				dev_mode.dmPelsHeight >= 600) +			{ +				BOOL resolution_exists = FALSE; +				for(S32 i = 0; i < mNumSupportedResolutions; i++) +				{ +					if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth && +						mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight) +					{ +						resolution_exists = TRUE; +					} +				} +				if (!resolution_exists) +				{ +					mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth; +					mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight; +					mNumSupportedResolutions++; +				} +			} +		} +	} + +	num_resolutions = mNumSupportedResolutions; +	return mSupportedResolutions; +} + + +F32 LLWindowWin32::getNativeAspectRatio() +{ +	if (mOverrideAspectRatio > 0.f) +	{ +		return mOverrideAspectRatio; +	} +	else if (mNativeAspectRatio > 0.f) +	{ +		// we grabbed this value at startup, based on the user's desktop settings +		return mNativeAspectRatio; +	} +	// RN: this hack presumes that the largest supported resolution is monitor-limited +	// and that pixels in that mode are square, therefore defining the native aspect ratio +	// of the monitor...this seems to work to a close approximation for most CRTs/LCDs +	S32 num_resolutions; +	LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions); + +	return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight); +} + +F32 LLWindowWin32::getPixelAspectRatio() +{ +	F32 pixel_aspect = 1.f; +	if (getFullscreen()) +	{ +		LLCoordScreen screen_size; +		getSize(&screen_size); +		pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX; +	} + +	return pixel_aspect; +} + +// Change display resolution.  Returns true if successful. +// protected +BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh) +{ +	DEVMODE dev_mode; +	dev_mode.dmSize = sizeof(dev_mode); +	BOOL success = FALSE; + +	// Don't change anything if we don't have to +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) +	{ +		if (dev_mode.dmPelsWidth        == width && +			dev_mode.dmPelsHeight       == height && +			dev_mode.dmBitsPerPel       == bits && +			dev_mode.dmDisplayFrequency == refresh ) +		{ +			// ...display mode identical, do nothing +			return TRUE; +		} +	} + +	memset(&dev_mode, 0, sizeof(dev_mode)); +	dev_mode.dmSize = sizeof(dev_mode); +	dev_mode.dmPelsWidth        = width; +	dev_mode.dmPelsHeight       = height; +	dev_mode.dmBitsPerPel       = bits; +	dev_mode.dmDisplayFrequency = refresh; +	dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + +	// CDS_FULLSCREEN indicates that this is a temporary change to the device mode. +	LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN); + +	success = (DISP_CHANGE_SUCCESSFUL == cds_result); + +	if (!success) +	{ +		LL_WARNS("Window") << "setDisplayResolution failed, " +			<< width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL; +	} + +	return success; +} + +// protected +BOOL LLWindowWin32::setFullscreenResolution() +{ +	if (mFullscreen) +	{ +		return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh); +	} +	else +	{ +		return FALSE; +	} +} + +// protected +BOOL LLWindowWin32::resetDisplayResolution() +{ +	LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL; + +	LONG cds_result = ChangeDisplaySettings(NULL, 0); + +	BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result); + +	if (!success) +	{ +		LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL; +	} + +	LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL; + +	return success; +} + +void LLWindowWin32::swapBuffers() +{ +	SwapBuffers(mhDC); +} + + +// +// LLSplashScreenImp +// +LLSplashScreenWin32::LLSplashScreenWin32() +:	mWindow(NULL) +{ +} + +LLSplashScreenWin32::~LLSplashScreenWin32() +{ +} + +void LLSplashScreenWin32::showImpl() +{ +	// This appears to work.  ??? +	HINSTANCE hinst = GetModuleHandle(NULL); + +	mWindow = CreateDialog(hinst,  +		TEXT("SPLASHSCREEN"),  +		NULL,	// no parent +		(DLGPROC) LLSplashScreenWin32::windowProc);  +	ShowWindow(mWindow, SW_SHOW); +} + + +void LLSplashScreenWin32::updateImpl(const std::string& mesg) +{ +	if (!mWindow) return; + +	WCHAR w_mesg[1024]; +	mbstowcs(w_mesg, mesg.c_str(), 1024); + +	SendDlgItemMessage(mWindow, +		666,		// HACK: text id +		WM_SETTEXT, +		FALSE, +		(LPARAM)w_mesg); +} + + +void LLSplashScreenWin32::hideImpl() +{ +	if (mWindow) +	{ +		DestroyWindow(mWindow); +		mWindow = NULL;  +	} +} + + +// static +LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg, +											WPARAM w_param, LPARAM l_param) +{ +	// Just give it to windows +	return DefWindowProc(h_wnd, u_msg, w_param, l_param); +} + +// +// Helper Funcs +// + +S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type) +{ +	UINT uType; + +	switch(type) +	{ +	case OSMB_OK: +		uType = MB_OK; +		break; +	case OSMB_OKCANCEL: +		uType = MB_OKCANCEL; +		break; +	case OSMB_YESNO: +		uType = MB_YESNO; +		break; +	default: +		uType = MB_OK; +		break; +	} + +	// HACK! Doesn't properly handle wide strings! +	int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType); +	S32 retval; + +	switch(retval_win) +	{ +	case IDYES: +		retval = OSBTN_YES; +		break; +	case IDNO: +		retval = OSBTN_NO; +		break; +	case IDOK: +		retval = OSBTN_OK; +		break; +	case IDCANCEL: +		retval = OSBTN_CANCEL; +		break; +	default: +		retval = OSBTN_CANCEL; +		break; +	} + +	return retval; +} + + +void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url ) +{ +	bool found = false; +	S32 i; +	for (i = 0; i < gURLProtocolWhitelistCount; i++) +	{ +		if (escaped_url.find(gURLProtocolWhitelist[i]) == 0) +		{ +			found = true; +			break; +		} +	} + +	if (!found) +	{ +		LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; +		return; +	} + +	LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL; + +	// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work +	// reliablly on Vista. + +	// this is madness.. no, this is.. +	LLWString url_wstring = utf8str_to_wstring( escaped_url ); +	llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); + +	// let the OS decide what to use to open the URL +	SHELLEXECUTEINFO sei = { sizeof( sei ) }; +	sei.fMask = SEE_MASK_FLAG_DDEWAIT; +	sei.nShow = SW_SHOWNORMAL; +	sei.lpVerb = L"open"; +	sei.lpFile = url_utf16.c_str(); +	ShellExecuteEx( &sei ); + +	//// TODO: LEAVING OLD CODE HERE SO I DON'T BONE OTHER MERGES +	//// DELETE THIS ONCE THE MERGES ARE DONE + +	// Figure out the user's default web browser +	// HKEY_CLASSES_ROOT\http\shell\open\command +	/* +	std::string reg_path_str = gURLProtocolWhitelistHandler[i] + "\\shell\\open\\command"; +	WCHAR reg_path_wstr[256]; +	mbstowcs( reg_path_wstr, reg_path_str.c_str(), LL_ARRAY_SIZE(reg_path_wstr) ); + +	HKEY key; +	WCHAR browser_open_wstr[1024]; +	DWORD buffer_length = 1024; +	RegOpenKeyEx(HKEY_CLASSES_ROOT, reg_path_wstr, 0, KEY_QUERY_VALUE, &key); +	RegQueryValueEx(key, NULL, NULL, NULL, (LPBYTE)browser_open_wstr, &buffer_length); +	RegCloseKey(key); + +	// Convert to STL string +	LLWString browser_open_wstring = utf16str_to_wstring(browser_open_wstr); + +	if (browser_open_wstring.length() < 2) +	{ +		LL_WARNS("Window") << "Invalid browser executable in registry " << browser_open_wstring << LL_ENDL; +		return; +	} + +	// Extract the process that's supposed to be launched +	LLWString browser_executable; +	if (browser_open_wstring[0] == '"') +	{ +		// executable is quoted, find the matching quote +		size_t quote_pos = browser_open_wstring.find('"', 1); +		// copy out the string including both quotes +		browser_executable = browser_open_wstring.substr(0, quote_pos+1); +	} +	else +	{ +		// executable not quoted, find a space +		size_t space_pos = browser_open_wstring.find(' ', 1); +		browser_executable = browser_open_wstring.substr(0, space_pos); +	} + +	LL_DEBUGS("Window") << "Browser reg key: " << wstring_to_utf8str(browser_open_wstring) << LL_ENDL; +	LL_INFOS("Window") << "Browser executable: " << wstring_to_utf8str(browser_executable) << LL_ENDL; + +	// Convert URL to wide string for Windows API +	// Assume URL is UTF8, as can come from scripts +	LLWString url_wstring = utf8str_to_wstring(escaped_url); +	llutf16string url_utf16 = wstring_to_utf16str(url_wstring); + +	// Convert executable and path to wide string for Windows API +	llutf16string browser_exec_utf16 = wstring_to_utf16str(browser_executable); + +	// ShellExecute returns HINSTANCE for backwards compatiblity. +	// MS docs say to cast to int and compare to 32. +	HWND our_window = NULL; +	LPCWSTR directory_wstr = NULL; +	int retval = (int) ShellExecute(our_window, 	// Flawfinder: ignore +									L"open",  +									browser_exec_utf16.c_str(),  +									url_utf16.c_str(),  +									directory_wstr, +									SW_SHOWNORMAL); +	if (retval > 32) +	{ +		LL_DEBUGS("Window") << "load_url success with " << retval << LL_ENDL; +	} +	else +	{ +		LL_INFOS("Window") << "load_url failure with " << retval << LL_ENDL; +	} +	*/ +} + + +BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b ) +{ +	BOOL retval = FALSE; + +	static CHOOSECOLOR cc; +	static COLORREF crCustColors[16]; +	cc.lStructSize = sizeof(CHOOSECOLOR); +	cc.hwndOwner = mWindowHandle; +	cc.hInstance = NULL; +	cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f)); +	//cc.rgbResult = RGB (0x80,0x80,0x80);  +	cc.lpCustColors = crCustColors; +	cc.Flags = CC_RGBINIT | CC_FULLOPEN; +	cc.lCustData = 0; +	cc.lpfnHook = NULL; +	cc.lpTemplateName = NULL; +  +	// This call is modal, so pause agent +	//send_agent_pause();	// this is in newview and we don't want to set up a dependency +	{ +		retval = ChooseColor(&cc); +	} +	//send_agent_resume();	// this is in newview and we don't want to set up a dependency + +	*b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f; + +	*g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f; +	 +	*r = ((F32)(cc.rgbResult & 0xff)) / 255.f; + +	return (retval); +} + +void *LLWindowWin32::getPlatformWindow() +{ +	return (void*)mWindowHandle; +} + +void LLWindowWin32::bringToFront() +{ +	BringWindowToTop(mWindowHandle); +} + +// set (OS) window focus back to the client +void LLWindowWin32::focusClient() +{ +	SetFocus ( mWindowHandle ); +} + +void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) +{ +	if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable()) +	{ +		return; +	} + +	if (preeditor != mPreeditor && !b) +	{ +		// This condition may occur with a call to +		// setEnabled(BOOL) from LLTextEditor or LLLineEditor +		// when the control is not focused. +		// We need to silently ignore the case so that +		// the language input status of the focused control +		// is not disturbed. +		return; +	} + +	// Take care of old and new preeditors. +	if (preeditor != mPreeditor || !b) +	{ +		if (sLanguageTextInputAllowed) +		{ +			interruptLanguageTextInput(); +		} +		mPreeditor = (b ? preeditor : NULL); +	} + +	sLanguageTextInputAllowed = b; + +	if ( sLanguageTextInputAllowed ) +	{ +		// Allowing: Restore the previous IME status, so that the user has a feeling that the previous  +		// text input continues naturally.  Be careful, however, the IME status is meaningful only during the user keeps  +		// using same Input Locale (aka Keyboard Layout). +		if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale) +		{ +			HIMC himc = LLWinImm::getContext(mWindowHandle); +			LLWinImm::setOpenStatus(himc, TRUE); +			LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); +			LLWinImm::releaseContext(mWindowHandle, himc); +		} +	} +	else +	{ +		// Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly. +		// However, do it after saving the current IME  status.  We need to restore the status when +		//   allowing language text input again. +		sWinInputLocale = GetKeyboardLayout(0); +		sWinIMEOpened = LLWinImm::isIME(sWinInputLocale); +		if (sWinIMEOpened) +		{ +			HIMC himc = LLWinImm::getContext(mWindowHandle); +			sWinIMEOpened = LLWinImm::getOpenStatus(himc); +			if (sWinIMEOpened) +			{ +				LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode); + +				// We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's  +				// keyboard hooking, because Some IME reacts only on the former and some other on the latter... +				LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode); +				LLWinImm::setOpenStatus(himc, FALSE); +			} +			LLWinImm::releaseContext(mWindowHandle, himc); + 		} +	} +} + +void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds,  +		CANDIDATEFORM *form) +{ +	LLCoordWindow caret_coord, top_left, bottom_right; +	convertCoords(caret, &caret_coord); +	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left); +	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right); + +	memset(form, 0, sizeof(CANDIDATEFORM)); +	form->dwStyle = CFS_EXCLUDE; +	form->ptCurrentPos.x = caret_coord.mX; +	form->ptCurrentPos.y = caret_coord.mY; +	form->rcArea.left   = top_left.mX; +	form->rcArea.top    = top_left.mY; +	form->rcArea.right  = bottom_right.mX; +	form->rcArea.bottom = bottom_right.mY; +} + + +// Put the IME window at the right place (near current text input).   Point coordinates should be the top of the current text line. +void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position ) +{ +	if (sLanguageTextInputAllowed && LLWinImm::isAvailable()) +	{ +		HIMC himc = LLWinImm::getContext(mWindowHandle); + +		LLCoordWindow win_pos; +		convertCoords( position, &win_pos ); + +		if ( win_pos.mX >= 0 && win_pos.mY >= 0 &&  +			(win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) ) +		{ +			COMPOSITIONFORM ime_form; +			memset( &ime_form, 0, sizeof(ime_form) ); +			ime_form.dwStyle = CFS_POINT; +			ime_form.ptCurrentPos.x = win_pos.mX; +			ime_form.ptCurrentPos.y = win_pos.mY; + +			LLWinImm::setCompositionWindow( himc, &ime_form ); + +			sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY ); +		} + +		LLWinImm::releaseContext(mWindowHandle, himc); +	} +} + + +void LLWindowWin32::fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, +		IMECHARPOSITION *char_position) +{ +	LLCoordScreen caret_coord, top_left, bottom_right; +	convertCoords(caret, &caret_coord); +	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left); +	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right); + +	char_position->pt.x = caret_coord.mX; +	char_position->pt.y = top_left.mY;	// Windows wants the coordinate of upper left corner of a character... +	char_position->cLineHeight = bottom_right.mY - top_left.mY; +	char_position->rcDocument.left   = top_left.mX; +	char_position->rcDocument.top    = top_left.mY; +	char_position->rcDocument.right  = bottom_right.mX; +	char_position->rcDocument.bottom = bottom_right.mY; +} + +void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont) +{ +	// Our font is a list of FreeType recognized font files that may +	// not have a corresponding ones in Windows' fonts.  Hence, we +	// can't simply tell Windows which font we are using.  We will +	// notify a _standard_ font for a current input locale instead. +	// We use a hard-coded knowledge about the Windows' standard +	// configuration to do so... + +	memset(logfont, 0, sizeof(LOGFONT)); + +	const WORD lang_id = LOWORD(GetKeyboardLayout(0)); +	switch (PRIMARYLANGID(lang_id)) +	{ +	case LANG_CHINESE: +		// We need to identify one of two Chinese fonts. +		switch (SUBLANGID(lang_id)) +		{ +		case SUBLANG_CHINESE_SIMPLIFIED: +		case SUBLANG_CHINESE_SINGAPORE: +			logfont->lfCharSet = GB2312_CHARSET; +			lstrcpy(logfont->lfFaceName, TEXT("SimHei")); +			break; +		case SUBLANG_CHINESE_TRADITIONAL: +		case SUBLANG_CHINESE_HONGKONG: +		case SUBLANG_CHINESE_MACAU: +		default: +			logfont->lfCharSet = CHINESEBIG5_CHARSET; +			lstrcpy(logfont->lfFaceName, TEXT("MingLiU")); +			break;			 +		} +		break; +	case LANG_JAPANESE: +		logfont->lfCharSet = SHIFTJIS_CHARSET; +		lstrcpy(logfont->lfFaceName, TEXT("MS Gothic")); +		break;		 +	case LANG_KOREAN: +		logfont->lfCharSet = HANGUL_CHARSET; +		lstrcpy(logfont->lfFaceName, TEXT("Gulim")); +		break; +	default: +		logfont->lfCharSet = ANSI_CHARSET; +		lstrcpy(logfont->lfFaceName, TEXT("Tahoma")); +		break; +	} +							 +	logfont->lfHeight = mPreeditor->getPreeditFontSize(); +	logfont->lfWeight = FW_NORMAL; +}	 + +U32 LLWindowWin32::fillReconvertString(const LLWString &text, +	S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string) +{ +	const llutf16string text_utf16 = wstring_to_utf16str(text); +	const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR); +	if (reconvert_string && reconvert_string->dwSize >= required_size) +	{ +		const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus); +		const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length); + +		reconvert_string->dwVersion = 0; +		reconvert_string->dwStrLen = text_utf16.length(); +		reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING); +		reconvert_string->dwCompStrLen = focus_utf16_length; +		reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR); +		reconvert_string->dwTargetStrLen = 0; +		reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR); + +		const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING)); +		memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR)); +	} +	return required_size; +} + +void LLWindowWin32::updateLanguageTextInputArea() +{ +	if (!mPreeditor || !LLWinImm::isAvailable()) +	{ +		return; +	} + +	LLCoordGL caret_coord; +	LLRect preedit_bounds; +	if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL)) +	{ +		mLanguageTextInputPointGL = caret_coord; +		mLanguageTextInputAreaGL = preedit_bounds; + +		CANDIDATEFORM candidate_form; +		fillCandidateForm(caret_coord, preedit_bounds, &candidate_form); + +		HIMC himc = LLWinImm::getContext(mWindowHandle); +		// Win32 document says there may be up to 4 candidate windows. +		// This magic number 4 appears only in the document, and +		// there are no constant/macro for the value... +		for (int i = 3; i >= 0; --i) +		{ +			candidate_form.dwIndex = i; +			LLWinImm::setCandidateWindow(himc, &candidate_form); +		} +		LLWinImm::releaseContext(mWindowHandle, himc); +	} +} + +void LLWindowWin32::interruptLanguageTextInput() +{ +	if (mPreeditor) +	{ +		if (LLWinImm::isAvailable()) +		{ +			HIMC himc = LLWinImm::getContext(mWindowHandle); +			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); +			LLWinImm::releaseContext(mWindowHandle, himc); +		} + +		// Win32 document says there will be no composition string +		// after NI_COMPOSITIONSTR returns.  The following call to +		// resetPreedit should be a NOP unless IME goes mad... +		mPreeditor->resetPreedit(); +	} +} + +void LLWindowWin32::handleStartCompositionMessage() +{ +	// Let IME know the font to use in feedback UI. +	LOGFONT logfont; +	fillCompositionLogfont(&logfont); +	HIMC himc = LLWinImm::getContext(mWindowHandle); +	LLWinImm::setCompositionFont(himc, &logfont); +	LLWinImm::releaseContext(mWindowHandle, himc); +} + +// Handle WM_IME_COMPOSITION message. + +void LLWindowWin32::handleCompositionMessage(const U32 indexes) +{ +	BOOL needs_update = FALSE; +	LLWString result_string; +	LLWString preedit_string; +	S32 preedit_string_utf16_length = 0; +	LLPreeditor::segment_lengths_t preedit_segment_lengths; +	LLPreeditor::standouts_t preedit_standouts; + +	// Step I: Receive details of preedits from IME. + +	HIMC himc = LLWinImm::getContext(mWindowHandle); + +	if (indexes & GCS_RESULTSTR) +	{ +		LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0); +		if (size >= 0) +		{ +			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1]; +			size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size); +			if (size > 0) +			{ +				result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR))); +			} +			delete[] data; +			needs_update = TRUE; +		} +	} +	 +	if (indexes & GCS_COMPSTR) +	{ +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0); +		if (size >= 0) +		{ +			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1]; +			size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size); +			if (size > 0) +			{ +				preedit_string_utf16_length = size / sizeof(WCHAR); +				preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR))); +			} +			delete[] data; +			needs_update = TRUE; +		} +	} + +	if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0) +	{ +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0); +		if (size > 0) +		{ +			const LPDWORD data = new DWORD[size / sizeof(DWORD)]; +			size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size); +			if (size >= sizeof(DWORD) * 2 +				&& data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length) +			{ +				preedit_segment_lengths.resize(size / sizeof(DWORD) - 1); +				S32 offset = 0; +				for (U32 i = 0; i < preedit_segment_lengths.size(); i++) +				{ +					const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]); +					preedit_segment_lengths[i] = length; +					offset += length; +				} +			} +			delete[] data; +		} +	} + +	if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1) +	{ +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0); +		if (size > 0) +		{ +			const LPBYTE data = new BYTE[size / sizeof(BYTE)]; +			size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size); +			if (size == preedit_string_utf16_length) +			{ +				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE); +				S32 offset = 0; +				for (U32 i = 0; i < preedit_segment_lengths.size(); i++) +				{ +					if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset]) +					{ +						preedit_standouts[i] = TRUE; +					} +					offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]); +				} +			} +			delete[] data; +		} +	} + +	S32 caret_position = preedit_string.length(); +	if (indexes & GCS_CURSORPOS) +	{ +		const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0); +		if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length) +		{ +			caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16); +		} +	} + +	if (indexes == 0) +	{ +		// I'm not sure this condition really happens, but +		// Windows SDK document says it is an indication +		// of "reset everything." +		needs_update = TRUE; +	} + +	LLWinImm::releaseContext(mWindowHandle, himc); + +	// Step II: Update the active preeditor. + +	if (needs_update) +	{ +		mPreeditor->resetPreedit(); + +		if (result_string.length() > 0) +		{ +			for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++) +			{ +				mPreeditor->handleUnicodeCharHere(*i); +			} +		} + +		if (preedit_string.length() == 0) + 		{ +			preedit_segment_lengths.clear(); +			preedit_standouts.clear(); +		} +		else +		{ +			if (preedit_segment_lengths.size() == 0) +			{ +				preedit_segment_lengths.assign(1, preedit_string.length()); +			} +			if (preedit_standouts.size() == 0) +			{ +				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE); +			} +		} +		mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); + +		// Some IME doesn't query char position after WM_IME_COMPOSITION, +		// so we need to update them actively. +		updateLanguageTextInputArea(); +	} +} + +// Given a text and a focus range, find_context finds and returns a +// surrounding context of the focused subtext.  A variable pointed +// to by offset receives the offset in llwchars of the beginning of +// the returned context string in the given wtext. + +static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_length, S32 *offset) +{ +	static const S32 CONTEXT_EXCESS = 30;	// This value is by experiences. + +	const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS); +	S32 end = focus + focus_length; +	while (end < e && '\n' != wtext[end]) +	{ +		end++; +	} + +	const S32 s = llmax(0, focus - CONTEXT_EXCESS); +	S32 start = focus; +	while (start > s && '\n' != wtext[start - 1]) +	{ +		--start; +	} + +	*offset = start; +	return wtext.substr(start, end - start); +} + +// final stage of handling drop requests - both from WM_DROPFILES message +// for files and via IDropTarget interface requests. +LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ) +{ +	return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url ); +} + +// Handle WM_IME_REQUEST message. +// If it handled the message, returns TRUE.  Otherwise, FALSE. +// When it handled the message, the value to be returned from +// the Window Procedure is set to *result. + +BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) +{ +	if ( mPreeditor ) +	{ +		switch (request) +		{ +			case IMR_CANDIDATEWINDOW:		// http://msdn2.microsoft.com/en-us/library/ms776080.aspx +			{ +				LLCoordGL caret_coord; +				LLRect preedit_bounds; +				mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL); +				 +				CANDIDATEFORM *const form = (CANDIDATEFORM *)param; +				DWORD const dwIndex = form->dwIndex; +				fillCandidateForm(caret_coord, preedit_bounds, form); +				form->dwIndex = dwIndex; + +				*result = 1; +				return TRUE; +			} +			case IMR_QUERYCHARPOSITION: +			{ +				IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param; + +				// char_position->dwCharPos counts in number of +				// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the +				// number to getPreeditLocation.   + +				const LLWString & wtext = mPreeditor->getPreeditString(); +				S32 preedit, preedit_length; +				mPreeditor->getPreeditRange(&preedit, &preedit_length); +				LLCoordGL caret_coord; +				LLRect preedit_bounds, text_control; +				const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos); + +				if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control)) +				{ +					LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL; +					return FALSE; +				} +				fillCharPosition(caret_coord, preedit_bounds, text_control, char_position); + +				*result = 1; +				return TRUE; +			} +			case IMR_COMPOSITIONFONT: +			{ +				fillCompositionLogfont((LOGFONT *)param); + +				*result = 1; +				return TRUE; +			} +			case IMR_RECONVERTSTRING: +			{ +				mPreeditor->resetPreedit(); +				const LLWString & wtext = mPreeditor->getPreeditString(); +				S32 select, select_length; +				mPreeditor->getSelectionRange(&select, &select_length); + +				S32 context_offset; +				const LLWString context = find_context(wtext, select, select_length, &context_offset); + +				RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param; +				const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string); +				if (reconvert_string) +				{ +					if (select_length == 0) +					{ +						// Let the IME to decide the reconversion range, and +						// adjust the reconvert_string structure accordingly. +						HIMC himc = LLWinImm::getContext(mWindowHandle); +						const BOOL adjusted = LLWinImm::setCompositionString(himc, +									SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0); +						LLWinImm::releaseContext(mWindowHandle, himc); +						if (adjusted) +						{ +							const llutf16string & text_utf16 = wstring_to_utf16str(context); +							const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR); +							const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen; +							select = utf16str_wstring_length(text_utf16, new_preedit_start); +							select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select; +							select += context_offset; +						} +					} +					mPreeditor->markAsPreedit(select, select_length); +				} + +				*result = size; +				return TRUE; +			} +			case IMR_CONFIRMRECONVERTSTRING: +			{ +				*result = FALSE; +				return TRUE; +			} +			case IMR_DOCUMENTFEED: +			{ +				const LLWString & wtext = mPreeditor->getPreeditString(); +				S32 preedit, preedit_length; +				mPreeditor->getPreeditRange(&preedit, &preedit_length); +				 +				S32 context_offset; +				LLWString context = find_context(wtext, preedit, preedit_length, &context_offset); +				preedit -= context_offset; +				if (preedit_length) +				{ +					// IMR_DOCUMENTFEED may be called when we have an active preedit. +					// We should pass the context string *excluding* the preedit string. +					// Otherwise, some IME are confused. +					context.erase(preedit, preedit_length); +				} +				 +				RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param; +				*result = fillReconvertString(context, preedit, 0, reconvert_string); +				return TRUE; +			} +			default: +				return FALSE; +		} +	} + +	return FALSE; +} + +//static +std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() +{ +	// Fonts previously in getFontListSans() have moved to fonts.xml. +	return std::vector<std::string>(); +} + + +#endif // LL_WINDOWS | 
