/*
   Copyright (C) 1999-2007 id Software, Inc. and contributors.
   For a list of contributors, see the accompanying CONTRIBUTORS file.

   This file is part of GtkRadiant.

   GtkRadiant is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   GtkRadiant is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GtkRadiant; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
//#include "qe3.h"

/*

   drag either multiple brushes, or select plane points from
   a single brush.

 */

extern int g_nPatchClickedView;

qboolean drag_ok;
vec3_t drag_xvec;
vec3_t drag_yvec;

//static	int	buttonstate;
int pressx, pressy;
static vec3_t pressdelta;
static vec3_t vPressStart;
//static	int	buttonx, buttony;


//int		num_move_points;
//float	*move_points[1024];

int lastx, lasty;

qboolean drag_first;


void    AxializeVector( vec3_t v ){
	vec3_t a;
	float o;
	int i;

	if ( !v[0] && !v[1] ) {
		return;
	}
	if ( !v[1] && !v[2] ) {
		return;
	}
	if ( !v[0] && !v[2] ) {
		return;
	}

	for ( i = 0 ; i < 3 ; i++ )
		a[i] = fabs( v[i] );
	if ( a[0] > a[1] && a[0] > a[2] ) {
		i = 0;
	}
	else if ( a[1] > a[0] && a[1] > a[2] ) {
		i = 1;
	}
	else{
		i = 2;
	}

	o = v[i];
	VectorCopy( vec3_origin, v );
	if ( o < 0 ) {
		v[i] = -1;
	}
	else{
		v[i] = 1;
	}

}

/*
   ===========
   Drag_Setup
   ===========
 */
extern void SelectCurvePointByRay( vec3_t org, vec3_t dir, int buttons );

void Drag_Setup( int x, int y, int buttons,
				 vec3_t xaxis, vec3_t yaxis,
				 vec3_t origin, vec3_t dir ){
	trace_t t;
	face_t    *f;

	drag_first = true;

	VectorCopy( vec3_origin, pressdelta );
	pressx = x;
	pressy = y;

	// snap to nearest axis for camwindow drags
	VectorCopy( xaxis, drag_xvec );
	AxializeVector( drag_xvec );
	VectorCopy( yaxis, drag_yvec );
	AxializeVector( drag_yvec );

	if ( g_qeglobals.d_select_mode == sel_curvepoint ) {
		SelectCurvePointByRay( origin, dir, buttons );

		if ( g_qeglobals.d_select_mode == sel_area ) {
			drag_ok = true;

			if ( g_nPatchClickedView == W_CAMERA ) {
				VectorSet( g_qeglobals.d_vAreaTL, x, y, 0 );
				VectorSet( g_qeglobals.d_vAreaBR, x, y, 0 );
			}
		}
		else if ( g_qeglobals.d_num_move_points ) { // don't add an undo if there are no points selected
			drag_ok = true;
			Sys_UpdateWindows( W_ALL );
			Undo_Start( "drag curve point" );
			Undo_AddBrushList( &selected_brushes );
		}
		return;
	}
	else
	{
		g_qeglobals.d_num_move_points = 0;
	}

	if ( g_qeglobals.d_select_mode == sel_areatall ) {
		VectorCopy( origin, g_qeglobals.d_vAreaTL );
		VectorCopy( origin, g_qeglobals.d_vAreaBR );

		Sys_UpdateWindows( W_ALL );

		drag_ok = true;
		return;
	}

	if ( selected_brushes.next == &selected_brushes ) {
		//in this case a new brush is created when the dragging
		//takes place in the XYWnd, An useless undo is created
		//when the dragging takes place in the CamWnd
		Undo_Start( "create brush" );

		Sys_Status( "No selection to drag", 0 );
		return;
	}

	if ( g_qeglobals.d_select_mode == sel_vertex ) {
		SelectVertexByRay( origin, dir );
		if ( g_qeglobals.d_num_move_points ) {
			drag_ok = true;
			Undo_Start( "drag vertex" );
			Undo_AddBrushList( &selected_brushes );
			// Need an update here for highlighting selected vertices
			Sys_UpdateWindows( W_XY | W_CAMERA );
			return;
		}
	}

	if ( g_qeglobals.d_select_mode == sel_edge ) {
		SelectEdgeByRay( origin, dir );
		if ( g_qeglobals.d_num_move_points ) {
			drag_ok = true;
			Undo_Start( "drag edge" );
			Undo_AddBrushList( &selected_brushes );
			return;
		}
	}

	//
	// check for direct hit first
	//
	t = Test_Ray( origin, dir, true );
	if ( t.selected ) {
		drag_ok = true;

		Undo_Start( "drag selection" );
		Undo_AddBrushList( &selected_brushes );

		if ( buttons == ( MK_LBUTTON | MK_CONTROL ) ) {
			Sys_Printf( "Shear dragging face\n" );
			Brush_SelectFaceForDragging( t.brush, t.face, true );
		}
		else if ( buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) ) {
			Sys_Printf( "Sticky dragging brush\n" );
			for ( f = t.brush->brush_faces ; f ; f = f->next )
				Brush_SelectFaceForDragging( t.brush, f, false );
		}
		else{
			Sys_Printf( "Dragging entire selection\n" );
		}

		return;
	}

	if ( g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge ) {
		return;
	}

	//
	// check for side hit
	//
	// multiple brushes selected?
	if ( selected_brushes.next->next != &selected_brushes ) {
		// yes, special handling
		bool bOK = ( g_PrefsDlg.m_bALTEdge ) ? Sys_AltDown() : true;
		if ( bOK ) {
			for ( brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next )
			{
				if ( buttons & MK_CONTROL ) {
					Brush_SideSelect( pBrush, origin, dir, true );
				}
				else{
					Brush_SideSelect( pBrush, origin, dir, false );
				}
			}
		}
		else
		{
			Sys_Printf( "press ALT to drag multiple edges\n" );
			return;
		}
	}
	else
	{
		// single select.. trying to drag fixed entities handle themselves and just move
		if ( buttons & MK_CONTROL ) {
			Brush_SideSelect( selected_brushes.next, origin, dir, true );
		}
		else{
			Brush_SideSelect( selected_brushes.next, origin, dir, false );
		}
	}

	Sys_Printf( "Side stretch\n" );
	drag_ok = true;

	Undo_Start( "side stretch" );
	Undo_AddBrushList( &selected_brushes );
}

entity_t *peLink;

void UpdateTarget( vec3_t origin, vec3_t dir ){
	trace_t t;
	entity_t *pe;
	int i;
	char sz[128];

	t = Test_Ray( origin, dir, 0 );

	if ( !t.brush ) {
		return;
	}

	pe = t.brush->owner;

	if ( pe == NULL ) {
		return;
	}

	// is this the first?
	if ( peLink != NULL ) {

		// Get the target id from out current target
		// if there is no id, make one

		i = IntForKey( pe, "target" );
		if ( i <= 0 ) {
			i = GetUniqueTargetId( 1 );
			sprintf( sz, "%d", i );

			SetKeyValue( pe, "target", sz );
		}

		// set the target # into our src

		sprintf( sz, "%d", i );
		SetKeyValue( peLink, "targetname", sz );

		Sys_UpdateWindows( W_ENTITY );

	}

	// promote the target to the src

	peLink = pe;

}

/*
   ===========
   Drag_Begin
   //++timo test three button mouse and three button emulation here ?
   ===========
 */
void Drag_Begin( int x, int y, int buttons,
				 vec3_t xaxis, vec3_t yaxis,
				 vec3_t origin, vec3_t dir, bool sf_camera ){
	trace_t t;
	bool altdown;
	int nFlag;

	drag_ok = false;
	VectorCopy( vec3_origin, pressdelta );
	VectorCopy( vec3_origin, vPressStart );

	drag_first = true;
	peLink = NULL;

	altdown = Sys_AltDown();

	// shift-LBUTTON = select entire brush
	// shift-alt-LBUTTON = drill select
	if ( buttons == ( MK_LBUTTON | MK_SHIFT ) && g_qeglobals.d_select_mode != sel_curvepoint ) {
		nFlag = altdown ? SF_CYCLE : 0;
		if ( sf_camera ) {
			nFlag |= SF_CAMERA;
		}
		else{
			nFlag |= SF_ENTITIES_FIRST;
		}
		Select_Ray( origin, dir, nFlag );
		return;
	}

	// (shift-)alt-LBUTTON = area select completely tall
	if ( !sf_camera &&
		 ( g_PrefsDlg.m_bALTEdge ? buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) : ( buttons == MK_LBUTTON || buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) ) ) &&
		 altdown && g_qeglobals.d_select_mode != sel_curvepoint ) {
		if ( g_pParentWnd->ActiveXY()->AreaSelectOK() ) {
			g_qeglobals.d_select_mode = sel_areatall;

			Drag_Setup( x, y, buttons, xaxis, yaxis, origin, dir );
			return;
		}
	}

	// ctrl-alt-LBUTTON = multiple brush select without selecting whole entities
	if ( buttons == ( MK_LBUTTON | MK_CONTROL ) && altdown && g_qeglobals.d_select_mode != sel_curvepoint ) {
		nFlag = 0;
		if ( sf_camera ) {
			nFlag |= SF_CAMERA;
		}
		else{
			nFlag |= SF_ENTITIES_FIRST;
		}
		Select_Ray( origin, dir, nFlag );
		UpdateSurfaceDialog();

		return;
	}

	// ctrl-shift LBUTTON = select single face
	if ( sf_camera && buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) && g_qeglobals.d_select_mode != sel_curvepoint ) {
		if ( Sys_AltDown() ) {
			brush_t *b;
			for ( b = selected_brushes.next ; b != &selected_brushes ; b = b->next )
			{
				if ( b->pPatch ) {
					continue;
				}

				for ( face_t* pFace = b->brush_faces; pFace; pFace = pFace->next )
				{
					g_ptrSelectedFaces.Add( pFace );
					g_ptrSelectedFaceBrushes.Add( b );
				}
			}

			for ( b = selected_brushes.next; b != &selected_brushes; )
			{
				brush_t *pb = b;
				b = b->next;
				Brush_RemoveFromList( pb );
				Brush_AddToList( pb, &active_brushes );
			}
		}
		else{
			Select_Deselect( true );
		}

		Select_Ray( origin, dir, ( SF_SINGLEFACE | SF_CAMERA ) );
		return;
	}


	// LBUTTON + all other modifiers = manipulate selection
	if ( buttons & MK_LBUTTON ) {
		Drag_Setup( x, y, buttons, xaxis, yaxis, origin, dir );
		return;
	}

	int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
	// middle button = grab texture
	if ( buttons == nMouseButton ) {
		t = Test_Ray( origin, dir, false );
		if ( t.face ) {
			UpdateWorkzone_ForBrush( t.brush );
			// use a local brushprimit_texdef fitted to a default 2x2 texture
			brushprimit_texdef_t bp_local;
			ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );
			Texture_SetTexture( &t.face->texdef, &bp_local, false, NULL );
			UpdateSurfaceDialog();
			UpdatePatchInspector();
		}
		else{
			Sys_Printf( "Did not select a texture\n" );
		}
		return;
	}

	// ctrl-middle button = set entire brush to texture
	if ( buttons == ( nMouseButton | MK_CONTROL ) ) {
		t = Test_Ray( origin, dir, false );
		if ( t.brush ) {
			if ( t.brush->brush_faces->texdef.GetName()[0] == '(' ) {
				Sys_Printf( "Can't change an entity texture\n" );
			}
			else
			{
				Brush_SetTexture( t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) );
				Sys_UpdateWindows( W_ALL );
			}
		}
		else{
			Sys_Printf( "Didn't hit a btrush\n" );
		}
		return;
	}

	// ctrl-shift-middle button = set single face to texture
	if ( buttons == ( nMouseButton | MK_SHIFT | MK_CONTROL ) ) {
		t = Test_Ray( origin, dir, false );
		if ( t.brush ) {
			if ( t.brush->brush_faces->texdef.GetName()[0] == '(' ) {
				Sys_Printf( "Can't change an entity texture\n" );
			}
			else
			{
				SetFaceTexdef( t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef );
				Brush_Build( t.brush );

				Sys_UpdateWindows( W_ALL );
			}
		}
		else{
			Sys_Printf( "Didn't hit a btrush\n" );
		}
		return;
	}

	if ( buttons == ( nMouseButton | MK_SHIFT ) ) {
		Sys_Printf( "Set brush face texture info\n" );
		t = Test_Ray( origin, dir, false );
		if ( t.brush ) {
			if ( t.brush->brush_faces->texdef.GetName()[0] == '(' ) {
				if ( t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT ) {
					CString strBuff;
					qtexture_t* pTex = g_qeglobals.d_texturewin.pShader->getTexture();
					if ( pTex ) {
						vec3_t vColor;
						VectorCopy( pTex->color, vColor );

						float fLargest = 0.0f;
						for ( int i = 0; i < 3; i++ )
						{
							if ( vColor[i] > fLargest ) {
								fLargest = vColor[i];
							}
						}

						if ( fLargest == 0.0f ) {
							vColor[0] = vColor[1] = vColor[2] = 1.0f;
						}
						else
						{
							float fScale = 1.0f / fLargest;
							for ( int i = 0; i < 3; i++ )
							{
								vColor[i] *= fScale;
							}
						}
						strBuff.Format( "%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2] );
						SetKeyValue( t.brush->owner, "_color", strBuff.GetBuffer() );
						Sys_UpdateWindows( W_ALL );
					}
				}
				else
				{
					Sys_Printf( "Can't select an entity brush face\n" );
				}
			}
			else
			{
				Face_SetShader( t.face, g_qeglobals.d_texturewin.texdef.GetName() );
				Brush_Build( t.brush );

				Sys_UpdateWindows( W_ALL );
			}
		}
		else{
			Sys_Printf( "Didn't hit a brush\n" );
		}
		return;
	}

}


//
//===========
//MoveSelection
//===========
//
void MoveSelection( vec3_t move ){
	int i, success;
	brush_t *b;
	CString strStatus;
	vec3_t vTemp, vTemp2, end;

	if ( !move[0] && !move[1] && !move[2] ) {
		return;
	}

	if ( !( g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall ) ) {
		move[0] = ( g_nScaleHow & SCALE_X ) ? 0 : move[0];
		move[1] = ( g_nScaleHow & SCALE_Y ) ? 0 : move[1];
		move[2] = ( g_nScaleHow & SCALE_Z ) ? 0 : move[2];
	}

	if ( g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode ) {
		float fDeg = -move[2];
		float fAdj = move[2];
		int nAxis = 0;
		if ( g_pParentWnd->ActiveXY()->GetViewType() == XY ) {
			fDeg = -move[1];
			fAdj = move[1];
			nAxis = 2;
		}
		else
		if ( g_pParentWnd->ActiveXY()->GetViewType() == XZ ) {
			fDeg = move[2];
			fAdj = move[2];
			nAxis = 1;
		}
		else{
			nAxis = 0;
		}

		g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
		strStatus.Format( "%s x:: %.1f  y:: %.1f  z:: %.1f", ( g_bPatchBendMode ) ? "Bend angle" : "Rotation", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2] );
		g_pParentWnd->SetStatusText( 2, strStatus );

		if ( g_bPatchBendMode ) {
			Patch_SelectBendNormal();
			Select_RotateAxis( nAxis, fDeg * 2, false, true );
			Patch_SelectBendAxis();
			Select_RotateAxis( nAxis, fDeg, false, true );
		}
		else
		{
			Select_RotateAxis( nAxis, fDeg, false, true );
		}
		return;
	}

	if ( g_pParentWnd->ActiveXY()->ScaleMode() ) {
		vec3_t v;
		v[0] = v[1] = v[2] = 1.0f;
		if ( move[1] > 0 ) {
			v[0] = 1.1f;
			v[1] = 1.1f;
			v[2] = 1.1f;
		}
		else
		if ( move[1] < 0 ) {
			v[0] = 0.9f;
			v[1] = 0.9f;
			v[2] = 0.9f;
		}

		Select_Scale( ( g_nScaleHow & SCALE_X ) ? 1.0f : v[0],
					  ( g_nScaleHow & SCALE_Y ) ? 1.0f : v[1],
					  ( g_nScaleHow & SCALE_Z ) ? 1.0f : v[2] );
		// is that really necessary???
		Sys_UpdateWindows( W_ALL );
		return;
	}


	vec3_t vDistance;
	VectorSubtract( pressdelta, vPressStart, vDistance );
	strStatus.Format( "Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2] );
	g_pParentWnd->SetStatusText( 3, strStatus );

	//
	// dragging only a part of the selection
	//

	// this is fairly crappy way to deal with curvepoint and area selection
	// but it touches the smallest amount of code this way
	//
	if ( g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall ) {
		//area selection
		if ( g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall ) {
			VectorAdd( g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR );
			return;
		}
		//curve point selection
		if ( g_qeglobals.d_select_mode == sel_curvepoint ) {
			Patch_UpdateSelected( move );
			return;
		}
		//vertex selection
		if ( g_qeglobals.d_select_mode == sel_vertex && g_PrefsDlg.m_bVertexSplit ) {
			if ( g_qeglobals.d_num_move_points ) {
				success = true;
				for ( b = selected_brushes.next; b != &selected_brushes; b = b->next )
				{
					success &= Brush_MoveVertex( b, g_qeglobals.d_move_points[0], move, end, true );
				}
				if ( success ) {
					VectorCopy( end, g_qeglobals.d_move_points[0] );
				}
			}
			return;
		}
		//all other selection types
		for ( i = 0 ; i < g_qeglobals.d_num_move_points ; i++ )
			VectorAdd( g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i] );
		for ( b = selected_brushes.next; b != &selected_brushes; b = b->next )
		{
			bool bMoved = false;
			for ( face_t *f = b->brush_faces; !bMoved && f != NULL; f = f->next )
				for ( int p = 0; !bMoved && p < 3; p++ )
					for ( i = 0 ; !bMoved && i < g_qeglobals.d_num_move_points ; i++ )
						if ( f->planepts[p] == g_qeglobals.d_move_points[i] ) {
							bMoved = true;
						}
			if ( !bMoved ) {
				continue;
			}

			VectorCopy( b->maxs, vTemp );
			VectorSubtract( vTemp, b->mins, vTemp );
			Brush_Build( b,true,true,false,false ); // don't filter
			for ( i = 0 ; i < 3 ; i++ )
			{
				if ( b->mins[i] > b->maxs[i]
					 || b->maxs[i] - b->mins[i] > g_MaxBrushSize ) {
					break;  // dragged backwards or fucked up
				}
			}
			if ( i != 3 ) {
				break;
			}
			if ( b->patchBrush ) {
				VectorCopy( b->maxs, vTemp2 );
				VectorSubtract( vTemp2, b->mins, vTemp2 );
				VectorSubtract( vTemp2, vTemp, vTemp2 );
				//if (!Patch_DragScale(b->nPatchID, vTemp2, move))
				if ( !Patch_DragScale( b->pPatch, vTemp2, move ) ) {
					b = NULL;
					break;
				}
			}
		}
		// if any of the brushes were crushed out of existance
		// calcel the entire move
		if ( b != &selected_brushes ) {
			Sys_Printf( "Brush dragged backwards, move canceled\n" );
			for ( i = 0 ; i < g_qeglobals.d_num_move_points ; i++ )
				VectorSubtract( g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i] );

			for ( b = selected_brushes.next ; b != &selected_brushes ; b = b->next )
				Brush_Build( b,true,true,false,false );  // don't filter
		}

	}
	else
	{
		// reset face originals from vertex edit mode
		// this is dirty, but unfortunately necessary because Brush_Build
		// can remove windings
		for ( b = selected_brushes.next; b != &selected_brushes; b = b->next )
		{
			Brush_ResetFaceOriginals( b );
		}
		//
		// if there are lots of brushes selected, just translate instead
		// of rebuilding the brushes
		// NOTE: this is not actually done, but would be a good idea
		//
		Select_Move( move );
	}
}

/*
   ===========
   Drag_MouseMoved
   ===========
 */
void Drag_MouseMoved( int x, int y, int buttons ){
	vec3_t move, delta;
	int i;

	if ( !buttons ) {
		drag_ok = false;
		return;
	}
	if ( !drag_ok ) {
		return;
	}

	// clear along one axis
	if ( buttons & MK_SHIFT && ( g_PrefsDlg.m_bALTEdge && g_qeglobals.d_select_mode != sel_areatall ) ) {
		drag_first = false;
		if ( abs( x - pressx ) > abs( y - pressy ) ) {
			y = pressy;
		}
		else{
			x = pressx;
		}
	}

	if ( g_qeglobals.d_select_mode == sel_area && g_nPatchClickedView == W_CAMERA ) {
		camera_t *m_pCamera = g_pParentWnd->GetCamWnd()->Camera();

		// snap to window
		if ( y > m_pCamera->height ) {
			y = m_pCamera->height - 1;
		}
		else if ( y < 0 ) {
			y = 0;
		}
		if ( x > m_pCamera->width ) {
			x = m_pCamera->width - 1;
		}
		else if ( x < 0 ) {
			x = 0;
		}

		VectorSet( move, x - pressx, y - pressy, 0 );
	}
	else
	{
		for ( i = 0 ; i < 3 ; i++ )
		{
			move[i] = drag_xvec[i] * ( x - pressx ) + drag_yvec[i] * ( y - pressy );
			if ( g_PrefsDlg.m_bSnap ) {
				move[i] = floor( move[i] / g_qeglobals.d_gridsize + 0.5 ) * g_qeglobals.d_gridsize;
			}
		}
	}

	VectorSubtract( move, pressdelta, delta );
	VectorCopy( move, pressdelta );

	MoveSelection( delta );
}

/*
   ===========
   Drag_MouseUp
   ===========
 */
void Drag_MouseUp( int nButtons ){
	Sys_Status( "Drag completed.", 0 );

	if ( g_qeglobals.d_select_mode == sel_area ) {
		Patch_SelectAreaPoints( nButtons & MK_CONTROL ); // adds to selection and/or deselects selected points if ctrl is held
		g_qeglobals.d_select_mode = sel_curvepoint;
		Sys_UpdateWindows( W_ALL );
	}

	if ( g_qeglobals.d_select_mode == sel_areatall ) {
		vec3_t mins, maxs;

		int nDim1 = ( g_pParentWnd->ActiveXY()->GetViewType() == YZ ) ? 1 : 0;
		int nDim2 = ( g_pParentWnd->ActiveXY()->GetViewType() == XY ) ? 1 : 2;

		// get our rectangle
		mins[nDim1] = MIN( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );
		mins[nDim2] = MIN( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );
		maxs[nDim1] = MAX( g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1] );
		maxs[nDim2] = MAX( g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2] );

		// deselect current selection
		if ( !( nButtons & ( MK_CONTROL | MK_SHIFT ) ) ) {
			Select_Deselect();
		}

		// select new selection
		Select_RealCompleteTall( mins, maxs );

		Sys_UpdateWindows( W_ALL );
	}

	if ( g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2] ) {
		Select_Move( g_qeglobals.d_select_translate );
		VectorCopy( vec3_origin, g_qeglobals.d_select_translate );
		Sys_UpdateWindows( W_CAMERA );
	}

	/* note: added cleanup here, since an edge drag will leave selected vertices
	         in g_qeglobals.d_num_move_points
	 */
	if (  g_qeglobals.d_select_mode != sel_vertex &&
		  g_qeglobals.d_select_mode != sel_curvepoint &&
		  g_qeglobals.d_select_mode != sel_edge ) {
		g_qeglobals.d_num_move_points = 0;
	}

	g_pParentWnd->SetStatusText( 3, "" );
	Undo_EndBrushList( &selected_brushes );
	Undo_End();
	UpdateSurfaceDialog();
}
