Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

XYWnd.cpp (89114B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // XYWnd.cpp : implementation file
     23 //
     24 // QERadiant
     25 //
     26 // 
     27 
     28 #include "stdafx.h"
     29 #include "Radiant.h"
     30 #include "XYWnd.h"
     31 #include "qe3.h"
     32 #include "PrefsDlg.h"
     33 #include "DialogInfo.h"
     34 #include "splines/splines.h"
     35 
     36 #ifdef _DEBUG
     37 #define new DEBUG_NEW
     38 #undef THIS_FILE
     39 static char THIS_FILE[] = __FILE__;
     40 #endif
     41 
     42 #define	PAGEFLIPS	2
     43 
     44 
     45 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
     46 const char* g_pOrgStrings[] = {"(x:%.f  y:%.f)", "(x:%.f  z:%.f)", "(y:%.f  z:%.f)"};
     47 CString g_strDim;
     48 CString g_strStatus;
     49 
     50 bool g_bCrossHairs = false;
     51 bool g_bScaleMode;
     52 int g_nScaleHow;
     53 bool g_bRotateMode;
     54 bool g_bClipMode;
     55 bool g_bRogueClipMode;
     56 bool g_bSwitch;
     57 CClipPoint g_Clip1;
     58 CClipPoint g_Clip2;
     59 CClipPoint g_Clip3;
     60 CClipPoint* g_pMovingClip;
     61 brush_t g_brFrontSplits;
     62 brush_t g_brBackSplits;
     63 
     64 brush_t g_brClipboard;
     65 brush_t g_brUndo;
     66 entity_t	g_enClipboard;
     67 
     68 vec3_t g_vRotateOrigin;
     69 vec3_t g_vRotation;
     70 
     71 bool g_bPathMode;
     72 CClipPoint g_PathPoints[256];
     73 CClipPoint* g_pMovingPath;
     74 int g_nPathCount;
     75 int g_nPathLimit;
     76 
     77 bool g_bSmartGo;
     78 
     79 bool g_bPointMode;
     80 CClipPoint g_PointPoints[512];
     81 CClipPoint* g_pMovingPoint;
     82 int g_nPointCount;
     83 int g_nPointLimit;
     84 
     85 
     86 const int XY_LEFT = 0x01;
     87 const int XY_RIGHT = 0x02;
     88 const int XY_UP = 0x04;
     89 const int XY_DOWN = 0x08;
     90 
     91 PFNPathCallback* g_pPathFunc = NULL;
     92 
     93 void AcquirePath(int nCount, PFNPathCallback* pFunc)
     94 {
     95   g_nPathCount = 0;
     96   g_nPathLimit = nCount;
     97   g_pPathFunc = pFunc;
     98   g_bPathMode = true;
     99 }
    100 
    101 
    102 CPtrArray g_ptrMenus;
    103 
    104 CMemFile g_Clipboard(4096);
    105 CMemFile g_PatchClipboard(4096);
    106 
    107 extern int pressx;
    108 extern int pressy;
    109 
    110 
    111 /////////////////////////////////////////////////////////////////////////////
    112 // CXYWnd
    113 
    114 IMPLEMENT_DYNCREATE(CXYWnd, CWnd);
    115 
    116 CXYWnd::CXYWnd()
    117 {
    118   g_brClipboard.next = &g_brClipboard;
    119   g_brUndo.next = &g_brUndo;
    120   g_nScaleHow = 0;
    121   g_bRotateMode = false;
    122   g_bClipMode = false;
    123   g_bRogueClipMode = false;
    124   g_bSwitch = true;
    125   g_pMovingClip = NULL;
    126   g_pMovingPath = NULL;
    127   g_brFrontSplits.next = &g_brFrontSplits;
    128   g_brBackSplits.next = &g_brBackSplits;
    129   m_bActive = false;
    130   //m_bTiming = true;
    131   m_bTiming = false;
    132   m_bRButtonDown = false;
    133   m_nUpdateBits = W_XY;
    134   g_bPathMode = false;
    135   g_nPathCount = 0;
    136   g_nPathLimit = 0;
    137   m_nTimerID = -1;
    138   XY_Init();
    139 }
    140 
    141 CXYWnd::~CXYWnd()
    142 {
    143   int nSize = g_ptrMenus.GetSize();
    144   while (nSize > 0)
    145   {
    146     CMenu* pMenu = reinterpret_cast<CMenu*>(g_ptrMenus.GetAt(nSize-1));
    147     ASSERT(pMenu);
    148     pMenu->DestroyMenu();
    149     delete pMenu;
    150     nSize--;
    151   }
    152   g_ptrMenus.RemoveAll();
    153   m_mnuDrop.DestroyMenu();
    154 }
    155 
    156 
    157 BEGIN_MESSAGE_MAP(CXYWnd, CWnd)
    158 	//{{AFX_MSG_MAP(CXYWnd)
    159 	ON_WM_CREATE()
    160 	ON_WM_LBUTTONDOWN()
    161 	ON_WM_MBUTTONDOWN()
    162 	ON_WM_RBUTTONDOWN()
    163 	ON_WM_LBUTTONUP()
    164 	ON_WM_MBUTTONUP()
    165 	ON_WM_RBUTTONUP()
    166 	ON_WM_MOUSEMOVE()
    167 	ON_WM_PAINT()
    168 	ON_WM_KEYDOWN()
    169 	ON_WM_SIZE()
    170 	ON_WM_DESTROY()
    171 	ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate)
    172 	ON_WM_TIMER()
    173 	ON_WM_KEYUP()
    174 	ON_WM_NCCALCSIZE()
    175 	ON_WM_KILLFOCUS()
    176 	ON_WM_SETFOCUS()
    177 	ON_WM_CLOSE()
    178 	ON_COMMAND(ID_SELECTION_MAKE_DETAIL, CMainFrame::OnSelectionMakeDetail)
    179 	ON_COMMAND(ID_SELECTION_MAKE_STRUCTURAL, CMainFrame::OnSelectionMakeStructural)
    180 	ON_COMMAND(ID_SELECTION_SELECTCOMPLETETALL, CMainFrame::OnSelectionSelectcompletetall)
    181 	ON_COMMAND(ID_SELECTION_SELECTINSIDE, CMainFrame::OnSelectionSelectinside)
    182 	ON_COMMAND(ID_SELECTION_SELECTPARTIALTALL, CMainFrame::OnSelectionSelectpartialtall)
    183 	ON_COMMAND(ID_SELECTION_SELECTTOUCHING, CMainFrame::OnSelectionSelecttouching)
    184 	ON_COMMAND(ID_SELECTION_UNGROUPENTITY, CMainFrame::OnSelectionUngroupentity)
    185 	//}}AFX_MSG_MAP
    186   ON_COMMAND_RANGE(ID_ENTITY_START, ID_ENTITY_END, OnEntityCreate)
    187 END_MESSAGE_MAP()
    188 
    189 
    190 /////////////////////////////////////////////////////////////////////////////
    191 // CXYWnd message handlers
    192 LONG WINAPI XYWndProc(HWND, UINT, WPARAM, LPARAM);
    193 BOOL CXYWnd::PreCreateWindow(CREATESTRUCT& cs) 
    194 {
    195   WNDCLASS wc;
    196   HINSTANCE hInstance = AfxGetInstanceHandle();
    197   if (::GetClassInfo(hInstance, XY_WINDOW_CLASS, &wc) == FALSE)
    198   {
    199     // Register a new class
    200   	memset (&wc, 0, sizeof(wc));
    201     wc.style         = CS_NOCLOSE | CS_OWNDC;
    202     wc.lpszClassName = XY_WINDOW_CLASS;
    203     wc.hCursor       = NULL; //LoadCursor (NULL,IDC_ARROW);
    204     wc.lpfnWndProc   = ::DefWindowProc;
    205     if (AfxRegisterClass(&wc) == FALSE)
    206       Error ("CCamWnd RegisterClass: failed");
    207   }
    208 
    209   cs.lpszClass = XY_WINDOW_CLASS;
    210   cs.lpszName = "VIEW";
    211   if (cs.style != QE3_CHILDSTYLE)
    212     cs.style = QE3_SPLITTER_STYLE;
    213 
    214 	return CWnd::PreCreateWindow(cs);
    215 }
    216 
    217 HDC   s_hdcXY;
    218 HGLRC s_hglrcXY;
    219 
    220 static unsigned s_stipple[32] =
    221 {
    222 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    223 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    224 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    225 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    226 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    227 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    228 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    229 	0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
    230 };
    231 
    232 /*
    233 ============
    234 WXY_WndProc
    235 ============
    236 */
    237 LONG WINAPI XYWndProc (
    238     HWND    hWnd,
    239     UINT    uMsg,
    240     WPARAM  wParam,
    241     LPARAM  lParam)
    242 {
    243     switch (uMsg)
    244     {
    245 	case WM_DESTROY:
    246 		QEW_StopGL( hWnd, s_hglrcXY, s_hdcXY );
    247 		return 0;
    248 
    249 	case WM_NCCALCSIZE:// don't let windows copy pixels
    250 		DefWindowProc (hWnd, uMsg, wParam, lParam);
    251 		return WVR_REDRAW;
    252 
    253 	case WM_KILLFOCUS:
    254 	case WM_SETFOCUS:
    255 		SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
    256 		return 0;
    257 
    258    	case WM_CLOSE:
    259         DestroyWindow (hWnd);
    260 		return 0;
    261     }
    262 
    263 	return DefWindowProc (hWnd, uMsg, wParam, lParam);
    264 }
    265 
    266 
    267 static void WXY_InitPixelFormat( PIXELFORMATDESCRIPTOR *pPFD )
    268 {
    269 	memset( pPFD, 0, sizeof( *pPFD ) );
    270 
    271 	pPFD->nSize    = sizeof( PIXELFORMATDESCRIPTOR );
    272 	pPFD->nVersion = 1;
    273 	pPFD->dwFlags  = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    274 	pPFD->iPixelType = PFD_TYPE_RGBA;
    275 	pPFD->cColorBits = 24;
    276 	pPFD->cDepthBits = 32;
    277 	pPFD->iLayerType = PFD_MAIN_PLANE;
    278 
    279 }
    280 
    281 void WXY_Print( void )
    282 {
    283 	DOCINFO di;
    284 
    285 	PRINTDLG pd;
    286 
    287 	/*
    288 	** initialize the PRINTDLG struct and execute it
    289 	*/
    290 	memset( &pd, 0, sizeof( pd ) );
    291 	pd.lStructSize = sizeof( pd );
    292 	pd.hwndOwner = g_qeglobals.d_hwndXY;
    293 	pd.Flags = PD_RETURNDC;
    294 	pd.hInstance = 0;
    295 	if ( !PrintDlg( &pd ) || !pd.hDC )
    296 	{
    297 		MessageBox( g_qeglobals.d_hwndMain, "Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR );
    298 		return;
    299 	}
    300 
    301 	/*
    302 	** StartDoc
    303 	*/
    304 	memset( &di, 0, sizeof( di ) );
    305 	di.cbSize = sizeof( di );
    306 	di.lpszDocName = "QE4";
    307 	if ( StartDoc( pd.hDC, &di ) <= 0 )
    308 	{
    309 		MessageBox( g_qeglobals.d_hwndMain, "Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR );
    310 		return;
    311 	}
    312 
    313 	/*
    314 	** StartPage
    315 	*/
    316 	if ( StartPage( pd.hDC ) <= 0 )
    317 	{
    318 		MessageBox( g_qeglobals.d_hwndMain, "Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR );
    319 		return;
    320 	}
    321 
    322 	/*
    323 	** read pixels from the XY window
    324 	*/
    325 	{
    326 		int bmwidth = 320, bmheight = 320;
    327 		int pwidth, pheight;
    328 
    329 		RECT r;
    330 
    331 		GetWindowRect( g_qeglobals.d_hwndXY, &r );
    332 
    333 		bmwidth  = r.right - r.left;
    334 		bmheight = r.bottom - r.top;
    335 
    336 		pwidth  = GetDeviceCaps( pd.hDC, PHYSICALWIDTH ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETX );
    337 		pheight = GetDeviceCaps( pd.hDC, PHYSICALHEIGHT ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETY );
    338 
    339 		StretchBlt( pd.hDC,
    340 			0, 0,
    341 			pwidth, pheight,
    342 			s_hdcXY,
    343 			0, 0,
    344 			bmwidth, bmheight,
    345 			SRCCOPY );
    346 	}
    347 
    348 	/*
    349 	** EndPage and EndDoc
    350 	*/
    351 	if ( EndPage( pd.hDC ) <= 0 )
    352 	{
    353 		MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR );
    354 		return;
    355 	}
    356 
    357 	if ( EndDoc( pd.hDC ) <= 0 )
    358 	{
    359 		MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR );
    360 		return;
    361 	}
    362 }
    363 
    364 int CXYWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    365 {
    366 	if (CWnd::OnCreate(lpCreateStruct) == -1)
    367 		return -1;
    368 
    369   s_hdcXY = ::GetDC(GetSafeHwnd());
    370 	QEW_SetupPixelFormat(s_hdcXY, false);
    371 	if ( ( s_hglrcXY = qwglCreateContext( s_hdcXY ) ) == 0 )
    372 	  Error( "wglCreateContext in WXY_WndProc failed" );
    373 
    374 	if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcXY ) )
    375 	  Error( "wglShareLists in WXY_WndProc failed" );
    376 
    377   if (!qwglMakeCurrent( s_hdcXY, s_hglrcXY ))
    378 	  Error ("wglMakeCurrent failed");
    379 
    380 	qglPolygonStipple ((unsigned char *)s_stipple);
    381 	qglLineStipple (3, 0xaaaa);
    382   g_qeglobals.d_hwndXY = GetSafeHwnd();
    383 	return 0;
    384 }
    385 
    386 float ptSum(vec3_t pt)
    387 {
    388   return pt[0] + pt[1] + pt[2];
    389 }
    390 
    391 void CXYWnd::DropClipPoint(UINT nFlags, CPoint point)
    392 {
    393   CRect rctZ;
    394   GetClientRect(rctZ);
    395   if (g_pMovingClip)
    396   {
    397     SetCapture();
    398     SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingClip);
    399   }
    400   else
    401   {
    402     vec3_t* pPt = NULL;
    403     if (g_Clip1.Set() == false)
    404     {
    405       pPt = g_Clip1;
    406       g_Clip1.Set(true);
    407       g_Clip1.m_ptScreen = point;
    408     }
    409     else 
    410     if (g_Clip2.Set() == false)
    411     {
    412       pPt = g_Clip2;
    413       g_Clip2.Set(true);
    414       g_Clip2.m_ptScreen = point;
    415     }
    416     else 
    417     if (g_Clip3.Set() == false)
    418     {
    419       pPt = g_Clip3;
    420       g_Clip3.Set(true);
    421       g_Clip3.m_ptScreen = point;
    422     }
    423     else 
    424     {
    425       RetainClipMode(true);
    426       pPt = g_Clip1;
    427       g_Clip1.Set(true);
    428       g_Clip1.m_ptScreen = point;
    429     }
    430     SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *pPt);
    431   }
    432   Sys_UpdateWindows(XY | W_CAMERA_IFON);
    433 }
    434 
    435 
    436 void CXYWnd::DropPathPoint(UINT nFlags, CPoint point)
    437 {
    438   CRect rctZ;
    439   GetClientRect(rctZ);
    440   if (g_pMovingPath)
    441   {
    442     SetCapture();
    443     SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingPath);
    444   }
    445   else
    446   {
    447     g_PathPoints[g_nPathCount].Set(true);
    448     g_PathPoints[g_nPathCount].m_ptScreen = point;
    449     SnapToPoint(point.x, rctZ.Height() - 1 - point.y, g_PathPoints[g_nPathCount]);
    450     g_nPathCount++;
    451     if (g_nPathCount == g_nPathLimit)
    452     {
    453       if (g_pPathFunc)
    454         g_pPathFunc(true, g_nPathCount);
    455       g_nPathCount = 0;
    456       g_bPathMode = false;
    457       g_pPathFunc = NULL;
    458     }
    459   }
    460   Sys_UpdateWindows(XY | W_CAMERA_IFON);
    461 }
    462 
    463 void CXYWnd::AddPointPoint(UINT nFlags, vec3_t* pVec)
    464 {
    465   g_PointPoints[g_nPointCount].Set(true);
    466   //g_PointPoints[g_nPointCount].m_ptScreen = point;
    467   _VectorCopy(*pVec, g_PointPoints[g_nPointCount]);
    468   g_PointPoints[g_nPointCount].SetPointPtr(pVec);
    469   g_nPointCount++;
    470   Sys_UpdateWindows(XY | W_CAMERA_IFON);
    471 }
    472 
    473 
    474 void CXYWnd::OnLButtonDown(UINT nFlags, CPoint point) 
    475 {
    476   g_pParentWnd->SetActiveXY(this);
    477   UndoCopy();
    478 
    479 	// plugin entities
    480 	if (DispatchOnLButtonDown(nFlags, point.x, point.y ))
    481 		return;
    482 
    483   if (ClipMode() && !RogueClipMode())
    484   {
    485     DropClipPoint(nFlags, point);
    486   }
    487   else if (PathMode())
    488   {
    489     DropPathPoint(nFlags, point);
    490   }
    491   else OriginalButtonDown(nFlags, point);
    492 }
    493 
    494 void CXYWnd::OnMButtonDown(UINT nFlags, CPoint point) 
    495 {
    496   OriginalButtonDown(nFlags, point);
    497 }
    498 
    499 
    500 float Betwixt(float f1, float f2)
    501 {
    502   if (f1 > f2)
    503     return f2 + ((f1 - f2) / 2);
    504   else
    505     return f1 + ((f2 - f1) / 2);
    506 }
    507 
    508 void CXYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack)
    509 {
    510   *pFront = NULL;
    511   *pBack = NULL;
    512   if (ClipMode())
    513   {
    514     if (g_Clip1.Set() && g_Clip2.Set())
    515     {
    516       face_t face;
    517       VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
    518       VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
    519       VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
    520       if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes))
    521       {
    522         if (g_Clip3.Set() == false)
    523         {
    524           if (m_nViewType == XY)
    525           {
    526             face.planepts[0][2] = selected_brushes.next->mins[2];
    527             face.planepts[1][2] = selected_brushes.next->mins[2];
    528             face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
    529             face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
    530             face.planepts[2][2] = selected_brushes.next->maxs[2];
    531           }
    532           else if (m_nViewType == YZ)
    533           {
    534             face.planepts[0][0] = selected_brushes.next->mins[0];
    535             face.planepts[1][0] = selected_brushes.next->mins[0];
    536             face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
    537             face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
    538             face.planepts[2][0] = selected_brushes.next->maxs[0];
    539           }
    540           else
    541           {
    542             face.planepts[0][1] = selected_brushes.next->mins[1];
    543             face.planepts[1][1] = selected_brushes.next->mins[1];
    544             face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
    545             face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
    546             face.planepts[2][1] = selected_brushes.next->maxs[1];
    547           }
    548         }
    549 
    550         Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack);
    551       }
    552 
    553     }
    554   }
    555 }
    556 
    557 void CleanList(brush_t* pList)
    558 {
    559   brush_t* pBrush = pList->next; 
    560   while (pBrush != NULL && pBrush != pList)
    561   {
    562     brush_t* pNext = pBrush->next;
    563     Brush_Free(pBrush);
    564     pBrush = pNext;
    565   }
    566 }
    567 
    568 void CXYWnd::ProduceSplitLists()
    569 {
    570 	if (AnyPatchesSelected())
    571 	{
    572 		Sys_Printf("Deslecting patches for clip operation.\n");
    573 		brush_t *next;
    574 		for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next)
    575 		{
    576 			next = pb->next;
    577 			if (pb->patchBrush)
    578 			{
    579 				Brush_RemoveFromList (pb);
    580 				Brush_AddToList (pb, &active_brushes);
    581 				UpdatePatchInspector();
    582 			}
    583 			if (pb->terrainBrush)
    584 			{
    585 				Brush_RemoveFromList (pb);
    586 				Brush_AddToList (pb, &active_brushes);
    587 				UpdateTerrainInspector();
    588 			}
    589 		}
    590 	}
    591 
    592 	CleanList(&g_brFrontSplits);
    593 	CleanList(&g_brBackSplits);
    594 	g_brFrontSplits.next = &g_brFrontSplits;
    595 	g_brBackSplits.next = &g_brBackSplits;
    596 	brush_t* pBrush;
    597 	for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
    598 	{
    599 		brush_t* pFront = NULL;
    600 		brush_t* pBack = NULL;
    601 		if (ClipMode())
    602 		{
    603 			if (g_Clip1.Set() && g_Clip2.Set())
    604 			{
    605 				face_t face;
    606 				VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
    607 				VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
    608 				VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
    609 				if (g_Clip3.Set() == false)
    610 				{
    611 					if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
    612 					{
    613 						face.planepts[0][2] = pBrush->mins[2];
    614 						face.planepts[1][2] = pBrush->mins[2];
    615 						face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
    616 						face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
    617 						face.planepts[2][2] = pBrush->maxs[2];
    618 					}
    619 					else if (g_pParentWnd->ActiveXY()->GetViewType() == YZ)
    620 					{
    621 						face.planepts[0][0] = pBrush->mins[0];
    622 						face.planepts[1][0] = pBrush->mins[0];
    623 						face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
    624 						face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
    625 						face.planepts[2][0] = pBrush->maxs[0];
    626 					}
    627 					else
    628 					{
    629 						face.planepts[0][1] = pBrush->mins[1];
    630 						face.planepts[1][1] = pBrush->mins[1];
    631 						face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
    632 						face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
    633 						face.planepts[2][1] = pBrush->maxs[1];
    634 					}
    635 				}
    636 				Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack);
    637 				if (pBack)
    638 					Brush_AddToList(pBack, &g_brBackSplits);
    639 				if (pFront)
    640 					Brush_AddToList(pFront, &g_brFrontSplits);
    641 			}
    642 		}
    643 	}
    644 }
    645 
    646 void Brush_CopyList (brush_t* pFrom, brush_t* pTo)
    647 {
    648 	brush_t* pBrush = pFrom->next; 
    649 	while (pBrush != NULL && pBrush != pFrom)
    650 	{
    651 		brush_t* pNext = pBrush->next;
    652 		Brush_RemoveFromList(pBrush);
    653 		Brush_AddToList(pBrush, pTo);
    654 		pBrush = pNext;
    655 	}
    656 }
    657 
    658 void CXYWnd::OnRButtonDown(UINT nFlags, CPoint point) 
    659 {
    660   g_pParentWnd->SetActiveXY(this);
    661   m_ptDown = point;
    662   m_bRButtonDown = true;
    663 
    664   if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse 
    665   {
    666     if ((GetKeyState(VK_CONTROL) & 0x8000))
    667     {
    668       if (ClipMode()) // already there?
    669         DropClipPoint(nFlags, point);
    670       else
    671       {
    672         SetClipMode(true);
    673         g_bRogueClipMode = true;
    674         DropClipPoint(nFlags, point);
    675       }
    676       return;
    677     }
    678   }
    679   OriginalButtonDown(nFlags, point);
    680 }
    681 
    682 void CXYWnd::OnLButtonUp(UINT nFlags, CPoint point) 
    683 {
    684 	// plugin entities
    685 	if (DispatchOnLButtonUp(nFlags, point.x, point.y ))
    686 		return;
    687 
    688 	if (ClipMode())
    689   {
    690     if (g_pMovingClip)
    691     {
    692       ReleaseCapture();
    693       g_pMovingClip = NULL;
    694     }
    695   }
    696   OriginalButtonUp(nFlags, point);
    697 }
    698 
    699 void CXYWnd::OnMButtonUp(UINT nFlags, CPoint point) 
    700 {
    701   OriginalButtonUp(nFlags, point);
    702 }
    703 
    704 void CXYWnd::OnRButtonUp(UINT nFlags, CPoint point) 
    705 {
    706   m_bRButtonDown = false;
    707   if (point == m_ptDown)    // mouse didn't move
    708   {
    709     bool bGo = true;
    710     if ((GetKeyState(VK_MENU) & 0x8000))
    711       bGo = false;
    712     if ((GetKeyState(VK_CONTROL) & 0x8000))
    713       bGo = false;
    714     if ((GetKeyState(VK_SHIFT) & 0x8000))
    715       bGo = false;
    716     if (bGo)
    717       HandleDrop();
    718   }
    719   OriginalButtonUp(nFlags, point);
    720 }
    721 
    722 void CXYWnd::OriginalButtonDown(UINT nFlags, CPoint point)
    723 {
    724   CRect rctZ;
    725   GetClientRect(rctZ);
    726   SetWindowPos(&wndTop, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
    727   if (::GetTopWindow( g_qeglobals.d_hwndMain ) != GetSafeHwnd())
    728     ::BringWindowToTop(GetSafeHwnd());
    729 	SetFocus();
    730 	SetCapture();
    731 	XY_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags);
    732   m_nScrollFlags = nFlags;
    733 }          
    734 
    735 void CXYWnd::OriginalButtonUp(UINT nFlags, CPoint point)
    736 {
    737   CRect rctZ;
    738   GetClientRect(rctZ);
    739   XY_MouseUp (point.x, rctZ.Height() - 1 - point.y , nFlags);
    740 	if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
    741 		ReleaseCapture ();
    742 }
    743 
    744 
    745 float fDiff(float f1, float f2)
    746 {
    747   if (f1 > f2)
    748     return f1 - f2;
    749   else
    750     return f2 - f1;
    751 }
    752 
    753 
    754 vec3_t tdp;
    755 void CXYWnd::OnMouseMove(UINT nFlags, CPoint point) 
    756 {
    757 	// plugin entities
    758 	//++timo TODO: handle return code
    759 	DispatchOnMouseMove( nFlags, point.x, point.y );
    760 
    761   m_ptDown.x = 0;
    762   m_ptDown.y = 0;
    763 
    764   if ( g_PrefsDlg.m_bChaseMouse == TRUE &&
    765        (point.x < 0 || point.y < 0 || 
    766        point.x > m_nWidth || point.y > m_nHeight) &&
    767        GetCapture() == this)
    768   {
    769     float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
    770     //m_ptDrag = point;
    771     m_ptDragAdj.x = 0;
    772     m_ptDragAdj.y = 0;
    773     if (point.x < 0)
    774     {
    775       m_ptDragAdj.x = -fAdjustment;
    776     }
    777     else 
    778     if (point.x > m_nWidth)
    779     {
    780       m_ptDragAdj.x = fAdjustment;
    781     }
    782     if (point.y < 0)
    783     {
    784       m_ptDragAdj.y = -fAdjustment;
    785     }
    786     else
    787     if (point.y > m_nHeight)
    788     {
    789       m_ptDragAdj.y = fAdjustment;
    790     }
    791     if (m_nTimerID == -1)
    792     {
    793       m_nTimerID = SetTimer(100, 50, NULL);
    794       m_ptDrag = point;
    795       m_ptDragTotal = 0;
    796     }
    797     return;
    798   }
    799   //else if (m_nTimerID != -1)
    800   if (m_nTimerID != -1)
    801   {
    802     KillTimer(m_nTimerID);
    803     pressx -= m_ptDragTotal.x;
    804     pressy += m_ptDragTotal.y;
    805     m_nTimerID = -1;
    806     //return;
    807   }
    808 
    809   bool bCrossHair = false;
    810   if (!m_bRButtonDown)
    811   {
    812     tdp[0] = tdp[1] = tdp[2] = 0.0;
    813     SnapToPoint (point.x, m_nHeight - 1 - point.y , tdp);
    814 
    815     g_strStatus.Format("x:: %.1f  y:: %.1f  z:: %.1f", tdp[0], tdp[1], tdp[2]);
    816     g_pParentWnd->SetStatusText(1, g_strStatus);
    817 
    818     // i need to generalize the point code.. having 3 flavors pretty much sucks.. 
    819     // once the new curve stuff looks like it is going to stick i will 
    820     // rationalize this down to a single interface.. 
    821     if (PointMode())
    822     {
    823       if (g_pMovingPoint && GetCapture() == this)
    824       {
    825         bCrossHair = true;
    826         SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPoint->m_ptClip);
    827         g_pMovingPoint->UpdatePointPtr();
    828         Sys_UpdateWindows(XY | W_CAMERA_IFON);
    829       }
    830       else
    831       {
    832         g_pMovingPoint = NULL;
    833         int nDim1 = (m_nViewType == YZ) ? 1 : 0;
    834         int nDim2 = (m_nViewType == XY) ? 1 : 2;
    835         for (int n = 0; n < g_nPointCount; n++)
    836         {
    837           if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
    838                fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
    839           {
    840             bCrossHair = true;
    841             g_pMovingPoint = &g_PointPoints[n];
    842           }
    843         }
    844       }
    845     }
    846     else if (ClipMode())
    847     {
    848       if (g_pMovingClip && GetCapture() == this)
    849       {
    850         bCrossHair = true;
    851         SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingClip->m_ptClip);
    852         Sys_UpdateWindows(XY | W_CAMERA_IFON);
    853       }
    854       else
    855       {
    856         g_pMovingClip = NULL;
    857         int nDim1 = (m_nViewType == YZ) ? 1 : 0;
    858         int nDim2 = (m_nViewType == XY) ? 1 : 2;
    859         if (g_Clip1.Set())
    860         {
    861           if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
    862                fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 )
    863           {
    864             bCrossHair = true;
    865             g_pMovingClip = &g_Clip1;
    866           }
    867         }
    868         if (g_Clip2.Set())
    869         {
    870           if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
    871                fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 )
    872           {
    873             bCrossHair = true;
    874             g_pMovingClip = &g_Clip2;
    875           }
    876         }
    877         if (g_Clip3.Set())
    878         {
    879           if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
    880                fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 )
    881           {
    882             bCrossHair = true;
    883             g_pMovingClip = &g_Clip3;
    884           }
    885         }
    886       }
    887       if (bCrossHair == false)
    888         XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
    889     }
    890     else if (PathMode())
    891     {
    892       if (g_pMovingPath && GetCapture() == this)
    893       {
    894         bCrossHair = true;
    895         SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPath->m_ptClip);
    896         Sys_UpdateWindows(XY | W_CAMERA_IFON);
    897       }
    898       else
    899       {
    900         g_pMovingPath = NULL;
    901         int nDim1 = (m_nViewType == YZ) ? 1 : 0;
    902         int nDim2 = (m_nViewType == XY) ? 1 : 2;
    903         for (int n = 0; n < g_nPathCount; n++)
    904         {
    905           if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
    906                fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
    907           {
    908             bCrossHair = true;
    909             g_pMovingPath = &g_PathPoints[n];
    910           }
    911         }
    912       }
    913     }
    914     else
    915     {
    916       XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
    917     }
    918   }
    919   else 
    920   {
    921     XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
    922   }
    923   if (bCrossHair)
    924     SetCursor(::LoadCursor(NULL, IDC_CROSS));
    925   else
    926     SetCursor(::LoadCursor(NULL, IDC_ARROW));
    927 }
    928 
    929 void CXYWnd::RetainClipMode(bool bMode)
    930 {
    931   bool bSave = g_bRogueClipMode;
    932   SetClipMode(bMode);
    933   if (bMode == true)
    934     g_bRogueClipMode = bSave;
    935   else
    936     g_bRogueClipMode = false;
    937 }
    938 
    939 void CXYWnd::SetClipMode(bool bMode)
    940 {
    941   g_bClipMode = bMode;
    942   g_bRogueClipMode = false;
    943   if (bMode)
    944   {
    945     g_Clip1.Reset();
    946     g_Clip2.Reset();
    947     g_Clip3.Reset();
    948     CleanList(&g_brFrontSplits);
    949     CleanList(&g_brBackSplits);
    950     g_brFrontSplits.next = &g_brFrontSplits;
    951     g_brBackSplits.next = &g_brBackSplits;
    952   }
    953   else
    954   {
    955     if (g_pMovingClip)
    956     {
    957       ReleaseCapture();
    958       g_pMovingClip = NULL;
    959     }
    960     CleanList(&g_brFrontSplits);
    961     CleanList(&g_brBackSplits);
    962     g_brFrontSplits.next = &g_brFrontSplits;
    963     g_brBackSplits.next = &g_brBackSplits;
    964     Sys_UpdateWindows(XY | W_CAMERA_IFON);
    965   }
    966 }
    967 
    968 bool CXYWnd::ClipMode()
    969 {
    970   return g_bClipMode;
    971 }
    972 
    973 bool CXYWnd::RogueClipMode()
    974 {
    975   return g_bRogueClipMode;
    976 }
    977 
    978 bool CXYWnd::PathMode()
    979 {
    980   return g_bPathMode;
    981 }
    982 
    983 
    984 bool CXYWnd::PointMode()
    985 {
    986   return g_bPointMode;
    987 }
    988 
    989 void CXYWnd::SetPointMode(bool b)
    990 {
    991   g_bPointMode = b;
    992   if (!b)
    993     g_nPointCount = 0;
    994 }
    995 
    996 
    997 void CXYWnd::OnPaint() 
    998 {
    999 	CPaintDC dc(this); // device context for painting
   1000   bool bPaint = true;
   1001   if (!qwglMakeCurrent(dc.m_hDC, s_hglrcXY))
   1002   {
   1003     Sys_Printf("ERROR: wglMakeCurrent failed.. Error:%i\n",qglGetError());
   1004     Sys_Printf("Please restart Q3Radiant if the Map view is not working\n");
   1005     bPaint = false;
   1006   }
   1007   if (bPaint)
   1008   {
   1009     QE_CheckOpenGLForErrors();
   1010 		XY_Draw ();
   1011     QE_CheckOpenGLForErrors();
   1012 
   1013     if (m_nViewType != XY)
   1014     {
   1015       qglPushMatrix();
   1016       if (m_nViewType == YZ)
   1017         qglRotatef (-90,  0, 1, 0);	    // put Z going up
   1018       qglRotatef (-90,  1, 0, 0);	    // put Z going up
   1019     }
   1020  
   1021     if (g_bCrossHairs)
   1022     {
   1023 	    qglColor4f(0.2, 0.9, 0.2, 0.8);
   1024 		  qglBegin (GL_LINES);
   1025       if (m_nViewType == XY)
   1026       {
   1027         qglVertex2f(-16384, tdp[1]);
   1028         qglVertex2f(16384, tdp[1]);
   1029         qglVertex2f(tdp[0], -16384);
   1030         qglVertex2f(tdp[0], 16384);
   1031       }
   1032       else if (m_nViewType == YZ)
   1033       {
   1034         qglVertex3f(tdp[0], -16384, tdp[2]);
   1035         qglVertex3f(tdp[0], 16384, tdp[2]);
   1036         qglVertex3f(tdp[0], tdp[1], -16384);
   1037         qglVertex3f(tdp[0], tdp[1], 16384);
   1038       }
   1039       else
   1040       {
   1041         qglVertex3f(-16384, tdp[1], tdp[2]);
   1042         qglVertex3f( 16384, tdp[1], tdp[2]);
   1043         qglVertex3f(tdp[0], tdp[1], -16384);
   1044         qglVertex3f(tdp[0], tdp[1], 16384);
   1045       }
   1046 		  qglEnd();
   1047     }
   1048 
   1049     if (ClipMode())
   1050     {
   1051       qglPointSize (4);
   1052 		  qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
   1053 		  qglBegin (GL_POINTS);
   1054       if (g_Clip1.Set())
   1055 			  qglVertex3fv (g_Clip1);
   1056       if (g_Clip2.Set())
   1057 			  qglVertex3fv (g_Clip2);
   1058       if (g_Clip3.Set())
   1059 			  qglVertex3fv (g_Clip3);
   1060 		  qglEnd ();
   1061 		  qglPointSize (1);
   1062 
   1063       CString strMsg;
   1064       if (g_Clip1.Set())
   1065       {
   1066         qglRasterPos3f (g_Clip1.m_ptClip[0]+2, g_Clip1.m_ptClip[1]+2, g_Clip1.m_ptClip[2]+2);
   1067         strMsg = "1";
   1068         //strMsg.Format("1 (%f, %f, %f)", g_Clip1[0], g_Clip1[1], g_Clip1[2]);
   1069 	      qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
   1070       }
   1071       if (g_Clip2.Set())
   1072       {
   1073         qglRasterPos3f (g_Clip2.m_ptClip[0]+2, g_Clip2.m_ptClip[1]+2, g_Clip2.m_ptClip[2]+2);
   1074         strMsg = "2";
   1075         //strMsg.Format("2 (%f, %f, %f)", g_Clip2[0], g_Clip2[1], g_Clip2[2]);
   1076 	      qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
   1077       }
   1078       if (g_Clip3.Set())
   1079       {
   1080         qglRasterPos3f (g_Clip3.m_ptClip[0]+2, g_Clip3.m_ptClip[1]+2, g_Clip3.m_ptClip[2]+2);
   1081         strMsg = "3";
   1082         //strMsg.Format("3 (%f, %f, %f)", g_Clip3[0], g_Clip3[1], g_Clip3[2]);
   1083 	      qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
   1084       }
   1085       if (g_Clip1.Set() && g_Clip2.Set())
   1086       {
   1087         ProduceSplitLists();
   1088         brush_t* pBrush;
   1089         brush_t* pList = ( (m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
   1090 	      for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
   1091         {
   1092 		      qglColor3f (1,1,0);
   1093 	        face_t *face;
   1094 	        int order;
   1095 	        for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
   1096 	        {
   1097 		        winding_t* w = face->face_winding;
   1098 		        if (!w)
   1099 			        continue;
   1100 		        // draw the polygon
   1101 		        qglBegin(GL_LINE_LOOP);
   1102             for (int i=0 ; i<w->numpoints ; i++)
   1103 		          qglVertex3fv(w->points[i]);
   1104 		        qglEnd();
   1105 	        }
   1106         }
   1107       }
   1108 
   1109     }
   1110 
   1111 
   1112 
   1113     if (PathMode())
   1114     {
   1115       qglPointSize (4);
   1116 		  qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
   1117 		  qglBegin (GL_POINTS);
   1118 
   1119       for (int n = 0; n < g_nPathCount; n++)
   1120         qglVertex3fv(g_PathPoints[n]);
   1121 		  qglEnd ();
   1122 		  qglPointSize (1);
   1123 
   1124       CString strMsg;
   1125       for (n = 0; n < g_nPathCount; n++)
   1126       {
   1127         qglRasterPos3f (g_PathPoints[n].m_ptClip[0]+2, g_PathPoints[n].m_ptClip[1]+2, g_PathPoints[n].m_ptClip[2]+2);
   1128         strMsg.Format("%i", n+1);
   1129 	      qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
   1130       }
   1131 
   1132     }
   1133     if (m_nViewType != XY)
   1134       qglPopMatrix();
   1135 
   1136 		qwglSwapBuffers(dc.m_hDC);
   1137     TRACE("XY Paint\n");
   1138   }
   1139  }
   1140 
   1141 void CXYWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
   1142 {
   1143   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
   1144 }
   1145 
   1146 
   1147 
   1148 // FIXME: the brush_t *pBrush is never used. ( Entity_Create uses selected_brushes )
   1149 void CreateEntityFromName(char* pName, brush_t* pBrush)
   1150 {
   1151 	eclass_t *pecNew;
   1152 	entity_t *petNew;
   1153 	if (stricmp(pName, "worldspawn") == 0)
   1154 	{
   1155 		MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0);
   1156 		return;
   1157 	}
   1158 	
   1159 	pecNew = Eclass_ForName(pName, false);
   1160 	
   1161 	// create it
   1162 	petNew = Entity_Create(pecNew);
   1163 	if (petNew == NULL)
   1164 	{
   1165 		if (!((selected_brushes.next == &selected_brushes)||(selected_brushes.next->next != &selected_brushes)))
   1166 		{
   1167 			brush_t* b = selected_brushes.next;
   1168 			if (b->owner != world_entity && b->owner->eclass->fixedsize && pecNew->fixedsize)
   1169 			{
   1170 				vec3_t mins, maxs;
   1171 				vec3_t origin;
   1172 				for (int i=0 ; i<3 ; i++)
   1173 					origin[i] = b->mins[i] - pecNew->mins[i];
   1174 				
   1175 				VectorAdd (pecNew->mins, origin, mins);
   1176 				VectorAdd (pecNew->maxs, origin, maxs);
   1177 				brush_t* nb = Brush_Create (mins, maxs, &pecNew->texdef);
   1178 				Entity_LinkBrush (b->owner, nb);
   1179 				nb->owner->eclass = pecNew;
   1180 				SetKeyValue (nb->owner, "classname", pName);
   1181 				Brush_Free(b);
   1182 				Brush_Build(nb);
   1183 				Brush_AddToList (nb, &active_brushes);
   1184 				Select_Brush(nb);
   1185 				return;
   1186 			}
   1187 		}
   1188 		MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0);
   1189 		return;
   1190 	}
   1191 	
   1192 	Select_Deselect ();
   1193 	//entity_t* pEntity = world_entity;
   1194 	//if (selected_brushes.next != &selected_brushes)
   1195 	//	pEntity = selected_brushes.next->owner;
   1196 	Select_Brush (petNew->brushes.onext);
   1197 	
   1198 	if (stricmp(pName, "misc_model") == 0)
   1199 	{
   1200 		SetInspectorMode(W_ENTITY);
   1201 		PostMessage(g_qeglobals.d_hwndEntity, WM_COMMAND, IDC_BTN_ASSIGNMODEL, 0);
   1202 	}
   1203 	
   1204 }
   1205 
   1206 
   1207 brush_t* CreateEntityBrush(int x, int y, CXYWnd* pWnd)
   1208 {
   1209 	vec3_t	mins, maxs;
   1210 	int		i;
   1211 	float	temp;
   1212 	brush_t	*n;
   1213 
   1214 	pWnd->SnapToPoint (x, y, mins);
   1215   x += 32;
   1216   y += 32;
   1217 	pWnd->SnapToPoint (x, y, maxs);
   1218 
   1219   int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
   1220 	mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize));
   1221 	maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize));
   1222 
   1223   if (maxs[nDim] <= mins[nDim])
   1224 		maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
   1225 
   1226 	for (i=0 ; i<3 ; i++)
   1227 	{
   1228 		if (mins[i] == maxs[i])
   1229 			maxs[i] += 16;	// don't create a degenerate brush
   1230 		if (mins[i] > maxs[i])
   1231 		{
   1232 			temp = mins[i];
   1233 			mins[i] = maxs[i];
   1234 			maxs[i] = temp;
   1235 		}
   1236 	}
   1237 
   1238 	n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
   1239 	if (!n)
   1240 		return NULL;
   1241 
   1242 	Brush_AddToList (n, &selected_brushes);
   1243 	Entity_LinkBrush (world_entity, n);
   1244 	Brush_Build( n );
   1245   return n;
   1246 }
   1247 
   1248 void CreateRightClickEntity(CXYWnd* pWnd, int x, int y, char* pName)
   1249 {
   1250   CRect rctZ;
   1251   pWnd->GetClientRect(rctZ);
   1252   brush_t* pBrush = (selected_brushes.next == &selected_brushes) ? CreateEntityBrush(x, rctZ.Height() - 1 - y, pWnd) : selected_brushes.next;
   1253   CreateEntityFromName(pName, pBrush);
   1254   //Select_Brush(pBrush);
   1255 }
   1256 
   1257 brush_t* CreateSmartBrush(vec3_t v)
   1258 {
   1259 	vec3_t	mins, maxs;
   1260 	int		i;
   1261 	brush_t	*n;
   1262 
   1263 	for (i=0 ; i<3 ; i++)
   1264 	{
   1265     mins[i] = v[i] - 16;
   1266     maxs[i] = v[i] + 16;
   1267   }
   1268 
   1269 	n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
   1270 	if (!n)
   1271 		return NULL;
   1272 
   1273 	Brush_AddToList(n, &selected_brushes);
   1274 	//Entity_LinkBrush(world_entity, n);
   1275 	Brush_Build(n);
   1276   return n;
   1277 }
   1278 
   1279 
   1280 
   1281 
   1282 CString g_strSmartEntity;
   1283 int g_nSmartX;
   1284 int g_nSmartY;
   1285 bool g_bSmartWaiting;
   1286 void _SmartPointDone(bool b, int n)
   1287 {
   1288   g_bSmartWaiting = false;
   1289 }
   1290 
   1291 void CreateSmartEntity(CXYWnd* pWnd, int x, int y, const char* pName)
   1292 {
   1293   g_nSmartX = x;
   1294   g_nSmartY = y;
   1295   g_strSmartEntity = pName;
   1296   if (g_strSmartEntity.Find("Smart_Train") >= 0)
   1297   {
   1298     ShowInfoDialog("Select the path of the train by left clicking in XY, YZ and/or XZ views. You can move an already dropped point by grabbing and moving it. When you are finished, press ENTER to accept and create the entity and path(s), press ESC to abandon the creation");
   1299     g_bPathMode = true;
   1300     g_nPathLimit = 0;
   1301     g_nPathCount = 0;
   1302     g_bSmartGo = true;
   1303   }
   1304   else
   1305   if (g_strSmartEntity.Find("Smart_Monster...") >= 0)
   1306   {
   1307     g_bPathMode = true;
   1308     g_nPathLimit = 0;
   1309     g_nPathCount = 0;
   1310   }
   1311   else
   1312   if (g_strSmartEntity.Find("Smart_Rotating") >= 0)
   1313   {
   1314     g_bSmartWaiting = true;
   1315     ShowInfoDialog("Left click to specify the rotation origin");
   1316     AcquirePath(1, &_SmartPointDone);
   1317     while (g_bSmartWaiting)
   1318     {
   1319       MSG msg;
   1320       if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
   1321       { 
   1322         TranslateMessage(&msg);
   1323         DispatchMessage(&msg);
   1324       }
   1325     }
   1326     HideInfoDialog();
   1327     CPtrArray array;
   1328     g_bScreenUpdates = false;
   1329     CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
   1330     array.Add(reinterpret_cast<void*>(selected_brushes.next));
   1331     Select_Deselect();
   1332     brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]);
   1333     array.Add(pBrush);
   1334     Select_Deselect();
   1335     Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0)));
   1336     Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1)));
   1337     ConnectEntities();
   1338     g_bScreenUpdates = true;
   1339   }
   1340 }
   1341 
   1342 
   1343 void FinishSmartCreation()
   1344 {
   1345   CPtrArray array;
   1346   HideInfoDialog();
   1347   brush_t* pEntities = NULL;
   1348   if (g_strSmartEntity.Find("Smart_Train") >= 0)
   1349   {
   1350     g_bScreenUpdates = false;
   1351     CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
   1352     array.Add(reinterpret_cast<void*>(selected_brushes.next));
   1353     for (int n = 0; n < g_nPathCount; n++)
   1354     {
   1355       Select_Deselect();
   1356       CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreen.x,g_PathPoints[n].m_ptScreen.y, "path_corner");
   1357       array.Add(reinterpret_cast<void*>(selected_brushes.next));
   1358     }
   1359 
   1360     for (n = 0; n < g_nPathCount; n++)
   1361     {
   1362       Select_Deselect();
   1363       Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n)));
   1364       Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1)));
   1365       ConnectEntities();
   1366     }
   1367     g_bScreenUpdates = true;
   1368 
   1369   }
   1370   g_nPathCount = 0;
   1371   g_bPathMode = false;
   1372   Sys_UpdateWindows(W_ALL);
   1373 }
   1374 
   1375 void CXYWnd::KillPathMode()
   1376 {
   1377   g_bSmartGo = false;
   1378   g_bPathMode = false;
   1379   if (g_pPathFunc)
   1380     g_pPathFunc(false, g_nPathCount);
   1381   g_nPathCount = 0;
   1382   g_pPathFunc = NULL;
   1383   Sys_UpdateWindows(W_ALL);
   1384 }
   1385 
   1386 // gets called for drop down menu messages
   1387 // TIP: it's not always about EntityCreate
   1388 void CXYWnd::OnEntityCreate(unsigned int nID) 
   1389 {
   1390   if (m_mnuDrop.GetSafeHmenu())
   1391   {
   1392     CString strItem;
   1393     m_mnuDrop.GetMenuString(nID, strItem, MF_BYCOMMAND);
   1394 
   1395 		if (strItem.CompareNoCase("Add to...") == 0)
   1396 		{
   1397 			//++timo TODO: fill the menu with current groups?
   1398 			// this one is for adding to existing groups only
   1399 			Sys_Printf("TODO: Add to... in CXYWnd::OnEntityCreate\n");
   1400 		}
   1401 		else if (strItem.CompareNoCase("Remove") == 0)
   1402 		{
   1403 			// remove selected brushes from their current group
   1404 			brush_t *b;
   1405 			for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
   1406 			{
   1407 				
   1408 			}
   1409 		}
   1410 
   1411 		//++timo FIXME: remove when all hooks are in
   1412 		if (strItem.CompareNoCase("Add to...") == 0
   1413 			|| strItem.CompareNoCase("Remove") == 0
   1414 			|| strItem.CompareNoCase("Name...") == 0
   1415 			|| strItem.CompareNoCase("New group...") == 0)
   1416 		{
   1417 			Sys_Printf("TODO: hook drop down group menu\n");
   1418 			return;
   1419 		}
   1420 		
   1421     if (strItem.Find("Smart_") >= 0)
   1422     {
   1423       CreateSmartEntity(this, m_ptDown.x, m_ptDown.y, strItem);
   1424     }
   1425     else
   1426     {
   1427       CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, strItem.GetBuffer(0));
   1428     }
   1429 		
   1430     Sys_UpdateWindows(W_ALL);
   1431     //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
   1432   }
   1433 }
   1434 
   1435 
   1436 void CXYWnd::HandleDrop()
   1437 {
   1438   if (g_PrefsDlg.m_bRightClick == false)
   1439     return;
   1440   if (!m_mnuDrop.GetSafeHmenu()) // first time, load it up
   1441   {
   1442     m_mnuDrop.CreatePopupMenu();
   1443     int nID = ID_ENTITY_START;
   1444 
   1445     CMenu* pChild2 = new CMenu;
   1446     pChild2->CreateMenu();
   1447     pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTCOMPLETETALL, "Select Complete Tall");
   1448     pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTTOUCHING, "Select Touching");
   1449     pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTPARTIALTALL, "Select Partial Tall");
   1450     pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTINSIDE, "Select Inside");
   1451     m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild2->GetSafeHmenu()), "Select");
   1452     m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
   1453 
   1454     CMenu* pChild3 = new CMenu;
   1455     pChild3->CreateMenu();
   1456     pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_ADDTO, "Add to...");
   1457     pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_REMOVE, "Remove");
   1458     pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NAME, "Name...");
   1459     pChild3->AppendMenu(MF_SEPARATOR, nID++, "");
   1460     pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NEWGROUP, "New Group...");
   1461     m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild3->GetSafeHmenu()), "Group");
   1462     m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
   1463 
   1464     m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_UNGROUPENTITY, "Ungroup Entity");
   1465     m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_DETAIL, "Make Detail");
   1466     m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_STRUCTURAL, "Make Structural");
   1467     m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
   1468 
   1469     CMenu* pChild = new CMenu;
   1470     pChild->CreateMenu();
   1471     pChild->AppendMenu(MF_STRING, nID++, "Smart_Train");
   1472     //pChild->AppendMenu(MF_STRING, nID++, "Smart_Rotating");
   1473     m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), "Smart Entities");
   1474     m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
   1475 
   1476     pChild = NULL;
   1477 	  eclass_t	*e;
   1478     CString strActive;
   1479     CString strLast;
   1480     CString strName;
   1481 	  for (e=eclass ; e ; e=e->next)
   1482     {
   1483       strLast = strName;
   1484       strName = e->name;
   1485       int n_ = strName.Find("_");
   1486       if (n_ > 0)
   1487       {
   1488         CString strLeft = strName.Left(n_);
   1489         CString strRight = strName.Right(strName.GetLength() - n_ - 1);
   1490         if (strLeft == strActive) // this is a child
   1491         {
   1492           ASSERT(pChild);
   1493           pChild->AppendMenu(MF_STRING, nID++, strName);
   1494         }
   1495         else
   1496         {
   1497           if (pChild)
   1498           {
   1499             m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive);
   1500             g_ptrMenus.Add(pChild);
   1501             //pChild->DestroyMenu();
   1502             //delete pChild;
   1503             pChild = NULL;
   1504           }
   1505           strActive = strLeft;
   1506           pChild = new CMenu;
   1507           pChild->CreateMenu();
   1508           pChild->AppendMenu(MF_STRING, nID++, strName);
   1509         }
   1510       }
   1511       else
   1512       {
   1513         if (pChild)
   1514         {
   1515           m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive);
   1516           g_ptrMenus.Add(pChild);
   1517           //pChild->DestroyMenu();
   1518           //delete pChild;
   1519           pChild = NULL;
   1520         }
   1521         strActive = "";
   1522         m_mnuDrop.AppendMenu(MF_STRING, nID++, strName);
   1523       }
   1524     }
   1525   }
   1526 
   1527   CPoint ptMouse;
   1528   GetCursorPos(&ptMouse);
   1529   m_mnuDrop.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, this);
   1530 }
   1531 
   1532 void CXYWnd::XY_Init()
   1533 {
   1534 	m_vOrigin[0] = 0;
   1535 	m_vOrigin[1] = 20;
   1536   m_vOrigin[2] = 46;
   1537   m_fScale = 1;
   1538 }
   1539 
   1540 void CXYWnd::SnapToPoint (int x, int y, vec3_t point)
   1541 {
   1542   if (g_PrefsDlg.m_bNoClamp)
   1543   {
   1544     XY_ToPoint(x, y, point);
   1545   }
   1546   else
   1547   {
   1548     XY_ToGridPoint(x, y, point);
   1549   }
   1550 //--  else
   1551 //--    XY_ToPoint(x, y, point);
   1552 //--    //XY_ToPoint(x, y, point);
   1553 }
   1554 
   1555 
   1556 void CXYWnd::XY_ToPoint (int x, int y, vec3_t point)
   1557 {
   1558   float fx = x;
   1559   float fy = y;
   1560   float fw = m_nWidth;
   1561   float fh = m_nHeight;
   1562   if (m_nViewType == XY)
   1563   {
   1564 	  point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
   1565 	  point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
   1566 	  //point[2] = 0;
   1567   }
   1568   else if (m_nViewType == YZ)
   1569   {
   1570     ////point[0] = 0;
   1571 	  //point[1] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
   1572 	  //point[2] = m_vOrigin[1] + (fy - fh / 2 ) / m_fScale;
   1573 	  point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
   1574 	  point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale;
   1575   }
   1576   else
   1577   {
   1578 	  //point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
   1579 	  ////point[1] = 0;
   1580 	  //point[2] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
   1581 	  point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
   1582 	  //point[1] = 0;
   1583 	  point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
   1584   }
   1585 }
   1586 
   1587 
   1588 void CXYWnd::XY_ToGridPoint (int x, int y, vec3_t point)
   1589 {
   1590   if (m_nViewType == XY)
   1591   {
   1592 	  point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
   1593 	  point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
   1594 	  //point[2] = 0;
   1595 	  point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1596 	  point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1597   }
   1598   else if (m_nViewType == YZ)
   1599   {
   1600 	  //point[0] = 0;
   1601 	  //point[1] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
   1602 	  //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
   1603 	  point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
   1604 	  point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
   1605 	  point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1606 	  point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1607   }
   1608   else
   1609   {
   1610 	  //point[1] = 0;
   1611 	  //point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
   1612 	  //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
   1613 	  point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
   1614 	  point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
   1615 	  point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1616 	  point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1617   }
   1618 }
   1619 
   1620 
   1621 void CXYWnd::XY_MouseDown (int x, int y, int buttons)
   1622 {
   1623 
   1624 	vec3_t	point;
   1625 	vec3_t	origin, dir, right, up;
   1626 
   1627 	m_nButtonstate = buttons;
   1628   m_nPressx = x;
   1629 	m_nPressy = y;
   1630 	VectorCopy (vec3_origin, m_vPressdelta);
   1631 
   1632 	XY_ToPoint (x, y, point);
   1633 	
   1634   VectorCopy (point, origin);
   1635 
   1636 	dir[0] = 0; dir[1] = 0; dir[2] = 0;
   1637   if (m_nViewType == XY)
   1638   {
   1639 	  origin[2] = 8192;
   1640     dir[2] = -1;
   1641   	right[0] = 1 / m_fScale; 
   1642     right[1] = 0; 
   1643     right[2] = 0;
   1644 	  up[0] = 0; 
   1645     up[1] = 1 / m_fScale;
   1646     up[2] = 0;
   1647   }
   1648   else if (m_nViewType == YZ)
   1649   {
   1650     origin[0] = 8192;
   1651     dir[0] = -1;
   1652   	right[1] = 1 / m_fScale; 
   1653     right[2] = 0; 
   1654     right[0] = 0;
   1655    	up[0] = 0; 
   1656     up[2] = 1 / m_fScale;
   1657     up[1] = 0;
   1658   }
   1659   else
   1660   {
   1661     origin[1] = 8192;
   1662     dir[1] = -1;
   1663   	right[0] = 1 / m_fScale;
   1664     right[2] = 0; 
   1665     right[1] = 0;
   1666 	  up[0] = 0; 
   1667     up[2] = 1 / m_fScale;
   1668     up[1] = 0;
   1669   }
   1670 
   1671 
   1672 	m_bPress_selection = (selected_brushes.next != &selected_brushes);
   1673 
   1674   GetCursorPos(&m_ptCursor);
   1675 	//Sys_GetCursorPos (&m_ptCursor.x, &m_ptCursor.y);
   1676 
   1677 	// lbutton = manipulate selection
   1678 	// shift-LBUTTON = select
   1679 	if ( (buttons == MK_LBUTTON)
   1680 		|| (buttons == (MK_LBUTTON | MK_SHIFT))
   1681 		|| (buttons == (MK_LBUTTON | MK_CONTROL))
   1682 		|| (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
   1683 	{	
   1684 		if (g_qeglobals.d_select_mode == sel_addpoint) {
   1685 			XY_ToGridPoint(x, y, point);
   1686 			if (g_qeglobals.selectObject) {
   1687 				g_qeglobals.selectObject->addPoint(point[0], point[1], point[2]);
   1688 			}
   1689 			return;
   1690 		}
   1691     Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
   1692 		Drag_Begin (x, y, buttons, right, up,	origin, dir);
   1693 		return;
   1694 	}
   1695 
   1696   int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
   1697 
   1698 	// control mbutton = move camera
   1699 	if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
   1700 	{	
   1701 	  VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
   1702 		Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
   1703 	}
   1704 
   1705 	// mbutton = angle camera
   1706 	if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
   1707       (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
   1708 	{	
   1709 		VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point);
   1710 
   1711     int n1 = (m_nViewType == XY) ? 1 : 2;
   1712     int n2 = (m_nViewType == YZ) ? 1 : 0;
   1713     int nAngle = (m_nViewType == XY) ? YAW : PITCH;
   1714     if (point[n1] || point[n2])
   1715     {
   1716 		  g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
   1717 		  Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
   1718     }
   1719 	}
   1720 
   1721 	// shift mbutton = move z checker
   1722 	if (m_nButtonstate == (MK_SHIFT | nMouseButton))
   1723 	{
   1724     if (RotateMode() || g_bPatchBendMode)
   1725     {
   1726 		  SnapToPoint (x, y, point);
   1727 	    VectorCopyXY(point, g_vRotateOrigin);
   1728       if (g_bPatchBendMode)
   1729       {
   1730         VectorCopy(point, g_vBendOrigin);
   1731       }
   1732 		  Sys_UpdateWindows (W_XY);
   1733       return;
   1734     }
   1735     else
   1736     {
   1737 		  SnapToPoint (x, y, point);
   1738       if (m_nViewType == XY)
   1739       {
   1740 		    z.origin[0] = point[0];
   1741 		    z.origin[1] = point[1];
   1742       }
   1743       else if (m_nViewType == YZ)
   1744       {
   1745 		    z.origin[0] = point[1];
   1746 		    z.origin[1] = point[2];
   1747       }
   1748       else
   1749       {
   1750 		    z.origin[0] = point[0];
   1751 		    z.origin[1] = point[2];
   1752       }
   1753 		  Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
   1754 		  return;
   1755     }
   1756 	}
   1757 }
   1758 
   1759 
   1760 void CXYWnd::XY_MouseUp(int x, int y, int buttons)
   1761 {
   1762 	Drag_MouseUp (buttons);
   1763 	if (!m_bPress_selection)
   1764 		Sys_UpdateWindows (W_ALL);
   1765 	m_nButtonstate = 0;
   1766   while (::ShowCursor(TRUE) < 0)
   1767     ;
   1768 }
   1769 
   1770 qboolean CXYWnd::DragDelta (int x, int y, vec3_t move)
   1771 {
   1772 	vec3_t	xvec, yvec, delta;
   1773 	int		i;
   1774 
   1775 	xvec[0] = 1 / m_fScale;
   1776 	xvec[1] = xvec[2] = 0;
   1777 	yvec[1] = 1 / m_fScale;
   1778 	yvec[0] = yvec[2] = 0;
   1779 
   1780 	for (i=0 ; i<3 ; i++)
   1781 	{
   1782 		delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
   1783     if (!g_PrefsDlg.m_bNoClamp)
   1784     {
   1785 		  delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
   1786     }
   1787 	}
   1788 	VectorSubtract (delta, m_vPressdelta, move);
   1789 	VectorCopy (delta, m_vPressdelta);
   1790 
   1791 	if (move[0] || move[1] || move[2])
   1792 		return true;
   1793 	return false;
   1794 }
   1795 
   1796 
   1797 /*
   1798 ==============
   1799 NewBrushDrag
   1800 ==============
   1801 */
   1802 void CXYWnd::NewBrushDrag (int x, int y)
   1803 {
   1804 	vec3_t	mins, maxs, junk;
   1805 	int		i;
   1806 	float	temp;
   1807 	brush_t	*n;
   1808 
   1809 	if (!DragDelta (x,y, junk))
   1810 		return;
   1811 
   1812   // delete the current selection
   1813 	if (selected_brushes.next != &selected_brushes)
   1814 		Brush_Free (selected_brushes.next);
   1815 	
   1816   SnapToPoint (m_nPressx, m_nPressy, mins);
   1817 
   1818   int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
   1819 
   1820 	mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize));
   1821 	SnapToPoint (x, y, maxs);
   1822 	maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize));
   1823 	if (maxs[nDim] <= mins[nDim])
   1824 		maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
   1825 
   1826 	for (i=0 ; i<3 ; i++)
   1827 	{
   1828 		if (mins[i] == maxs[i])
   1829 			return;	// don't create a degenerate brush
   1830 		if (mins[i] > maxs[i])
   1831 		{
   1832 			temp = mins[i];
   1833 			mins[i] = maxs[i];
   1834 			maxs[i] = temp;
   1835 		}
   1836 	}
   1837 
   1838 	n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
   1839 	if (!n)
   1840 		return;
   1841 
   1842   vec3_t vSize;
   1843   VectorSubtract(maxs, mins, vSize);
   1844   g_strStatus.Format("Size X:: %.1f  Y:: %.1f  Z:: %.1f", vSize[0], vSize[1], vSize[2]);
   1845   g_pParentWnd->SetStatusText(2, g_strStatus);
   1846 
   1847 	Brush_AddToList (n, &selected_brushes);
   1848 
   1849 	Entity_LinkBrush (world_entity, n);
   1850 
   1851 	Brush_Build( n );
   1852 
   1853   //	Sys_UpdateWindows (W_ALL);
   1854 	Sys_UpdateWindows (W_XY| W_CAMERA);
   1855 
   1856 }
   1857 
   1858 /*
   1859 ==============
   1860 XY_MouseMoved
   1861 ==============
   1862 */
   1863 void CXYWnd::XY_MouseMoved (int x, int y, int buttons)
   1864 {
   1865 	vec3_t	point;
   1866 
   1867 
   1868 	if (!m_nButtonstate)
   1869   {
   1870     if (g_bCrossHairs)
   1871     {
   1872       ::ShowCursor(FALSE);
   1873   		Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
   1874       ::ShowCursor(TRUE);
   1875     }
   1876 		return;
   1877   }
   1878 
   1879 	// lbutton without selection = drag new brush
   1880 	//if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_splineedit)
   1881 	if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode == sel_brush)
   1882 	{
   1883 		NewBrushDrag (x, y);
   1884 		return;
   1885 	}
   1886 
   1887 	// lbutton (possibly with control and or shift)
   1888 	// with selection = drag selection
   1889 	if (m_nButtonstate & MK_LBUTTON)
   1890 	{
   1891 		Drag_MouseMoved (x, y, buttons);
   1892 		Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
   1893 		return;
   1894 	}
   1895 
   1896   int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
   1897 	// control mbutton = move camera
   1898 	if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
   1899 	{
   1900 		SnapToPoint (x, y, point);
   1901 	  VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
   1902 		Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
   1903 		return;
   1904 	}
   1905 
   1906 	// shift mbutton = move z checker
   1907 	if (m_nButtonstate == (MK_SHIFT|nMouseButton) )
   1908 	{
   1909     if (RotateMode() || g_bPatchBendMode)
   1910     {
   1911 		  SnapToPoint (x, y, point);
   1912 	    VectorCopyXY(point, g_vRotateOrigin);
   1913       if (g_bPatchBendMode)
   1914       {
   1915         VectorCopy(point, g_vBendOrigin);
   1916       }
   1917 		  Sys_UpdateWindows (W_XY);
   1918       return;
   1919     }
   1920     else
   1921     {
   1922 		  SnapToPoint (x, y, point);
   1923       if (m_nViewType == XY)
   1924       {
   1925 		    z.origin[0] = point[0];
   1926 		    z.origin[1] = point[1];
   1927       }
   1928       else if (m_nViewType == YZ)
   1929       {
   1930 		    z.origin[0] = point[1];
   1931 		    z.origin[1] = point[2];
   1932       }
   1933       else
   1934       {
   1935 		    z.origin[0] = point[0];
   1936 		    z.origin[1] = point[2];
   1937       }
   1938     }
   1939 		Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
   1940 		return;
   1941 	}
   1942 
   1943 	// mbutton = angle camera
   1944 	if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
   1945       (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
   1946 	{	
   1947 		SnapToPoint (x, y, point);
   1948 		VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point);
   1949 
   1950     int n1 = (m_nViewType == XY) ? 1 : 2;
   1951     int n2 = (m_nViewType == YZ) ? 1 : 0;
   1952     int nAngle = (m_nViewType == XY) ? YAW : PITCH;
   1953     if (point[n1] || point[n2])
   1954     {
   1955 		  g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
   1956 		  Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
   1957     }
   1958 		return;
   1959 	}
   1960 
   1961 
   1962 	// rbutton = drag xy origin
   1963 	if (m_nButtonstate == MK_RBUTTON)
   1964 	{
   1965 		Sys_GetCursorPos (&x, &y);
   1966 		if (x != m_ptCursor.x || y != m_ptCursor.y)
   1967 		{
   1968       int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   1969       int nDim2 = (m_nViewType == XY) ? 1 : 2;
   1970 			m_vOrigin[nDim1] -= (x - m_ptCursor.x) / m_fScale;
   1971 			m_vOrigin[nDim2] += (y - m_ptCursor.y) / m_fScale;
   1972 	    SetCursorPos (m_ptCursor.x, m_ptCursor.y);
   1973       ::ShowCursor(FALSE);
   1974       //XY_Draw();
   1975       //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
   1976 			Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
   1977       //::ShowCursor(TRUE);
   1978 		}
   1979 		return;
   1980 	}
   1981 
   1982 }
   1983 
   1984 
   1985 /*
   1986 ============================================================================
   1987 
   1988 DRAWING
   1989 
   1990 ============================================================================
   1991 */
   1992 
   1993 
   1994 /*
   1995 ==============
   1996 XY_DrawGrid
   1997 ==============
   1998 */
   1999 void CXYWnd::XY_DrawGrid()
   2000 {
   2001 	float	x, y, xb, xe, yb, ye;
   2002 	int		w, h;
   2003 	char	text[32];
   2004 
   2005 	qglDisable(GL_TEXTURE_2D);
   2006 	qglDisable(GL_TEXTURE_1D);
   2007 	qglDisable(GL_DEPTH_TEST);
   2008 	qglDisable(GL_BLEND);
   2009 
   2010 	w = m_nWidth / 2 / m_fScale;
   2011 	h = m_nHeight / 2 / m_fScale;
   2012 
   2013 
   2014   int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   2015   int nDim2 = (m_nViewType == XY) ? 1 : 2;
   2016   //int nDim1 = 0;
   2017   //int nDim2 = 1;
   2018 
   2019 
   2020 	xb = m_vOrigin[nDim1] - w;
   2021 	if (xb < region_mins[nDim1])
   2022 		xb = region_mins[nDim1];
   2023 	xb = 64 * floor (xb/64);
   2024 
   2025 	xe = m_vOrigin[nDim1] + w;
   2026 	if (xe > region_maxs[nDim1])
   2027 		xe = region_maxs[nDim1];
   2028 	xe = 64 * ceil (xe/64);
   2029 
   2030 	yb = m_vOrigin[nDim2] - h;
   2031 	if (yb < region_mins[nDim2])
   2032 		yb = region_mins[nDim2];
   2033 	yb = 64 * floor (yb/64);
   2034 
   2035 	ye = m_vOrigin[nDim2] + h;
   2036 	if (ye > region_maxs[nDim2])
   2037 		ye = region_maxs[nDim2];
   2038 	ye = 64 * ceil (ye/64);
   2039 
   2040 	// draw major blocks
   2041 
   2042 	qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]);
   2043 
   2044 	int stepSize = 64 * 0.1 / m_fScale;
   2045 	if (stepSize < 64) {
   2046 		stepSize = 64;
   2047 	} else {
   2048 		int i;
   2049 		for (i = 1; i < stepSize; i <<= 1) {
   2050 		}
   2051 		stepSize = i;
   2052 	}
   2053 
   2054 	if ( g_qeglobals.d_showgrid )
   2055 	{
   2056 		
   2057 		qglBegin (GL_LINES);
   2058 		
   2059 		for (x=xb ; x<=xe ; x+=stepSize)
   2060 		{
   2061 			qglVertex2f (x, yb);
   2062 			qglVertex2f (x, ye);
   2063 		}
   2064 		for (y=yb ; y<=ye ; y+=stepSize)
   2065 		{
   2066 			qglVertex2f (xb, y);
   2067 			qglVertex2f (xe, y);
   2068 		}
   2069 		
   2070 		qglEnd ();
   2071 		
   2072 	}
   2073 
   2074 	// draw minor blocks
   2075 	if ( m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4 && 
   2076        g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR] != g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK])
   2077 	{
   2078 		qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
   2079 
   2080 		qglBegin (GL_LINES);
   2081 		for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
   2082 		{
   2083 			if ( ! ((int)x & 63) )
   2084 				continue;
   2085 			qglVertex2f (x, yb);
   2086 			qglVertex2f (x, ye);
   2087 		}
   2088 		for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
   2089 		{
   2090 			if ( ! ((int)y & 63) )
   2091 				continue;
   2092 			qglVertex2f (xb, y);
   2093 			qglVertex2f (xe, y);
   2094 		}
   2095 		qglEnd ();
   2096 	}
   2097 
   2098 	// draw coordinate text if needed
   2099 
   2100 	if ( g_qeglobals.d_savedinfo.show_coordinates)
   2101 	{
   2102 		//glColor4f(0, 0, 0, 0);
   2103 		qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
   2104 
   2105 		for (x=xb ; x<xe ; x+=stepSize)
   2106 		{
   2107 			qglRasterPos2f (x, m_vOrigin[nDim2] + h - 6 / m_fScale);
   2108 			sprintf (text, "%i",(int)x);
   2109 			qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
   2110 		}
   2111 		for (y=yb ; y<ye ; y+=stepSize)
   2112 		{
   2113 			qglRasterPos2f (m_vOrigin[nDim1] - w + 1, y);
   2114 			sprintf (text, "%i",(int)y);
   2115 			qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
   2116 		}
   2117 
   2118 
   2119     if (Active())
   2120 		  qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
   2121 
   2122     qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
   2123 
   2124     char cView[20];
   2125     if (m_nViewType == XY)
   2126       strcpy(cView, "XY Top");
   2127     else 
   2128     if (m_nViewType == XZ)
   2129       strcpy(cView, "XZ Front");
   2130     else
   2131       strcpy(cView, "YZ Side");
   2132 
   2133 		qglCallLists (strlen(cView), GL_UNSIGNED_BYTE, cView);
   2134     
   2135 
   2136   }
   2137 
   2138 
   2139 /*
   2140   if (true)
   2141   {
   2142 		qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
   2143 		qglBegin (GL_LINES);
   2144   	qglVertex2f (x, yb);
   2145 		qglVertex2f (x, ye);
   2146     qglEnd();
   2147   }
   2148   */
   2149 
   2150 }
   2151 
   2152 /*
   2153 ==============
   2154 XY_DrawBlockGrid
   2155 ==============
   2156 */
   2157 void CXYWnd::XY_DrawBlockGrid()
   2158 {
   2159 	float	x, y, xb, xe, yb, ye;
   2160 	int		w, h;
   2161 	char	text[32];
   2162 
   2163 	qglDisable(GL_TEXTURE_2D);
   2164 	qglDisable(GL_TEXTURE_1D);
   2165 	qglDisable(GL_DEPTH_TEST);
   2166 	qglDisable(GL_BLEND);
   2167 
   2168 	w = m_nWidth / 2 / m_fScale;
   2169 	h = m_nHeight / 2 / m_fScale;
   2170 
   2171   int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   2172   int nDim2 = (m_nViewType == XY) ? 1 : 2;
   2173 
   2174   xb = m_vOrigin[nDim1] - w;
   2175 	if (xb < region_mins[nDim1])
   2176 		xb = region_mins[nDim1];
   2177 	xb = 1024 * floor (xb/1024);
   2178 
   2179 	xe = m_vOrigin[nDim1] + w;
   2180 	if (xe > region_maxs[nDim1])
   2181 		xe = region_maxs[nDim1];
   2182 	xe = 1024 * ceil (xe/1024);
   2183 
   2184 	yb = m_vOrigin[nDim2] - h;
   2185 	if (yb < region_mins[nDim2])
   2186 		yb = region_mins[nDim2];
   2187 	yb = 1024 * floor (yb/1024);
   2188 
   2189 	ye = m_vOrigin[nDim2] + h;
   2190 	if (ye > region_maxs[nDim2])
   2191 		ye = region_maxs[nDim2];
   2192 	ye = 1024 * ceil (ye/1024);
   2193 
   2194 	// draw major blocks
   2195 
   2196   qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
   2197 	qglLineWidth (2);
   2198 
   2199 	qglBegin (GL_LINES);
   2200 	
   2201 	for (x=xb ; x<=xe ; x+=1024)
   2202 	{
   2203 		qglVertex2f (x, yb);
   2204 		qglVertex2f (x, ye);
   2205 	}
   2206 	for (y=yb ; y<=ye ; y+=1024)
   2207 	{
   2208 		qglVertex2f (xb, y);
   2209 		qglVertex2f (xe, y);
   2210 	}
   2211 	
   2212 	qglEnd ();
   2213 	qglLineWidth (1);
   2214 
   2215 	// draw coordinate text if needed
   2216 
   2217 	for (x=xb ; x<xe ; x+=1024)
   2218 		for (y=yb ; y<ye ; y+=1024)
   2219 		{
   2220 			qglRasterPos2f (x+512, y+512);
   2221 			sprintf (text, "%i,%i",(int)floor(x/1024), (int)floor(y/1024) );
   2222 			qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
   2223 		}
   2224 
   2225 	qglColor4f(0, 0, 0, 0);
   2226 }
   2227 
   2228 void CXYWnd::DrawRotateIcon()
   2229 {
   2230 	float	x, y;
   2231 
   2232   if (m_nViewType == XY)
   2233   {
   2234     x = g_vRotateOrigin[0];
   2235     y = g_vRotateOrigin[1];
   2236   }
   2237   else if (m_nViewType == YZ)
   2238   {
   2239     x = g_vRotateOrigin[1];
   2240     y = g_vRotateOrigin[2];
   2241   }
   2242   else
   2243   {
   2244     x = g_vRotateOrigin[0];
   2245     y = g_vRotateOrigin[2];
   2246   }
   2247 
   2248 	qglEnable (GL_BLEND);
   2249 	qglDisable (GL_TEXTURE_2D);
   2250 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   2251 	qglDisable (GL_CULL_FACE);
   2252 	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   2253 	qglColor4f (0.8, 0.1, 0.9, 0.25);
   2254 
   2255   qglBegin(GL_QUADS);
   2256 	qglVertex3f (x-4,y-4,0);
   2257 	qglVertex3f (x+4,y-4,0);
   2258 	qglVertex3f (x+4,y+4,0);
   2259 	qglVertex3f (x-4,y+4,0);
   2260 	qglEnd ();
   2261 	qglDisable (GL_BLEND);
   2262 
   2263 	qglColor4f (1.0, 0.2, 1.0, 1);
   2264 	qglBegin(GL_POINTS);
   2265 	qglVertex3f (x,y,0);
   2266 	qglEnd ();
   2267 
   2268 #if 0
   2269 	qglBegin(GL_LINES);
   2270 	qglVertex3f (x-6,y+6,0);
   2271 	qglVertex3f (x+6,y+6,0);
   2272 	qglVertex3f (x-6,y-6,0);
   2273 	qglVertex3f (x+6,y-6,0);
   2274 	qglEnd ();
   2275 #endif
   2276 
   2277 }
   2278 
   2279 void CXYWnd::DrawCameraIcon()
   2280 {
   2281 	float	x, y, a;
   2282 
   2283   if (m_nViewType == XY)
   2284   {
   2285     x = g_pParentWnd->GetCamera()->Camera().origin[0];
   2286 		y = g_pParentWnd->GetCamera()->Camera().origin[1];
   2287 	  a = g_pParentWnd->GetCamera()->Camera().angles[YAW]/180*Q_PI;
   2288   }
   2289   else if (m_nViewType == YZ)
   2290   {
   2291 	  x = g_pParentWnd->GetCamera()->Camera().origin[1];
   2292 		y = g_pParentWnd->GetCamera()->Camera().origin[2];
   2293 	  a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI;
   2294   }
   2295   else
   2296   {
   2297 	  x = g_pParentWnd->GetCamera()->Camera().origin[0];
   2298 		y = g_pParentWnd->GetCamera()->Camera().origin[2];
   2299 	  a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI;
   2300   }
   2301 
   2302 	qglColor3f (0.0, 0.0, 1.0);
   2303 	qglBegin(GL_LINE_STRIP);
   2304 	qglVertex3f (x-16,y,0);
   2305 	qglVertex3f (x,y+8,0);
   2306 	qglVertex3f (x+16,y,0);
   2307 	qglVertex3f (x,y-8,0);
   2308 	qglVertex3f (x-16,y,0);
   2309 	qglVertex3f (x+16,y,0);
   2310 	qglEnd ();
   2311 	
   2312 	qglBegin(GL_LINE_STRIP);
   2313 	qglVertex3f (x+48*cos(a+Q_PI/4), y+48*sin(a+Q_PI/4), 0);
   2314 	qglVertex3f (x, y, 0);
   2315 	qglVertex3f (x+48*cos(a-Q_PI/4), y+48*sin(a-Q_PI/4), 0);
   2316 	qglEnd ();
   2317 
   2318 #if 0
   2319   char text[128];
   2320 	qglRasterPos2f (x+64, y+64);
   2321 	sprintf (text, "%f",g_pParentWnd->GetCamera()->Camera().angles[YAW]);
   2322 	qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
   2323 #endif
   2324 
   2325 }
   2326 
   2327 void CXYWnd::DrawZIcon (void)
   2328 {
   2329   if (m_nViewType == XY)
   2330   {
   2331 	  float x = z.origin[0];
   2332 	  float y = z.origin[1];
   2333 	  qglEnable (GL_BLEND);
   2334 	  qglDisable (GL_TEXTURE_2D);
   2335 	  qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   2336 	  qglDisable (GL_CULL_FACE);
   2337 	  qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   2338 	  qglColor4f (0.0, 0.0, 1.0, 0.25);
   2339 	  qglBegin(GL_QUADS);
   2340 	  qglVertex3f (x-8,y-8,0);
   2341 	  qglVertex3f (x+8,y-8,0);
   2342 	  qglVertex3f (x+8,y+8,0);
   2343 	  qglVertex3f (x-8,y+8,0);
   2344 	  qglEnd ();
   2345 	  qglDisable (GL_BLEND);
   2346 
   2347 	  qglColor4f (0.0, 0.0, 1.0, 1);
   2348 
   2349 	  qglBegin(GL_LINE_LOOP);
   2350 	  qglVertex3f (x-8,y-8,0);
   2351 	  qglVertex3f (x+8,y-8,0);
   2352 	  qglVertex3f (x+8,y+8,0);
   2353 	  qglVertex3f (x-8,y+8,0);
   2354 	  qglEnd ();
   2355 
   2356     qglBegin(GL_LINE_STRIP);
   2357 	  qglVertex3f (x-4,y+4,0);
   2358 	  qglVertex3f (x+4,y+4,0);
   2359 	  qglVertex3f (x-4,y-4,0);
   2360 	  qglVertex3f (x+4,y-4,0);
   2361 	  qglEnd ();
   2362   }
   2363 }
   2364 
   2365 
   2366 /*
   2367 ==================
   2368 FilterBrush
   2369 ==================
   2370 */
   2371 BOOL FilterBrush(brush_t *pb)
   2372 {
   2373 	if (!pb->owner)
   2374 		return FALSE;		// during construction
   2375 
   2376   if (pb->hiddenBrush)
   2377   {
   2378     return TRUE;
   2379   }
   2380 
   2381 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
   2382   {
   2383     // filter out the brush only if all faces are caulk
   2384     // if not don't hide the whole brush, proceed on a per-face basis (Cam_Draw)
   2385     //++timo TODO: set this as a preference .. show caulk: hide any brush with caulk // don't draw caulk faces
   2386     face_t *f;
   2387     f=pb->brush_faces;
   2388     while (f)
   2389     {
   2390       if (!strstr(f->texdef.name, "caulk"))
   2391         break;
   2392       f = f->next;
   2393     }
   2394     if (!f)
   2395       return TRUE;
   2396 
   2397 #if 0
   2398     if (strstr(pb->brush_faces->texdef.name, "caulk"))
   2399       return TRUE;
   2400 #endif
   2401 
   2402     //++timo FIXME: .. same deal here?
   2403     if (strstr(pb->brush_faces->texdef.name, "donotenter"))
   2404       return TRUE;
   2405   }
   2406 
   2407 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT)
   2408   {
   2409     if (strstr(pb->brush_faces->texdef.name, "hint"))
   2410       return TRUE;
   2411   }
   2412 
   2413 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
   2414 	{
   2415     if (strstr(pb->brush_faces->texdef.name, "clip"))
   2416       return TRUE;
   2417 
   2418     if (strstr(pb->brush_faces->texdef.name, "skip"))
   2419       return TRUE;
   2420 
   2421 		//if (!strncmp(pb->brush_faces->texdef.name, "clip", 4))
   2422 		//	return TRUE;
   2423 	}
   2424 
   2425 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER)
   2426 	{
   2427 		for (face_t* f = pb->brush_faces ; f ; f=f->next)
   2428     {
   2429       if (f->texdef.contents & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))
   2430         return TRUE;
   2431     }
   2432 	}
   2433 
   2434 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL)
   2435 	{
   2436 		if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL)
   2437 			return TRUE;
   2438 	}
   2439 
   2440 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CURVES)
   2441 	{
   2442 		if (pb->patchBrush)
   2443 			return TRUE;
   2444 	}
   2445 
   2446 	if( g_qeglobals.d_savedinfo.exclude & EXCLUDE_TERRAIN )
   2447 	{
   2448 		if( pb->terrainBrush )
   2449 		{
   2450 			return TRUE;
   2451 		}
   2452 	}
   2453 
   2454 	if (pb->owner == world_entity)
   2455 	{
   2456 		if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD)
   2457 			return TRUE;
   2458 		return FALSE;
   2459 	}
   2460 	else 
   2461   {
   2462     if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT)
   2463     {
   2464 		  return (strncmp(pb->owner->eclass->name, "func_group", 10));
   2465     }
   2466   }
   2467 
   2468 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS)
   2469 	{
   2470     return (pb->owner->eclass->nShowFlags & ECLASS_LIGHT);
   2471 		//if (!strncmp(pb->owner->eclass->name, "light", 5))
   2472 		//	return TRUE;
   2473 	}
   2474 
   2475 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
   2476 	{
   2477     return (pb->owner->eclass->nShowFlags & ECLASS_PATH);
   2478 		//if (!strncmp(pb->owner->eclass->name, "path", 4))
   2479 		//	return TRUE;
   2480 	}
   2481 
   2482 	return FALSE;
   2483 }
   2484 
   2485 /*
   2486 =============================================================
   2487 
   2488   PATH LINES
   2489 
   2490 =============================================================
   2491 */
   2492 
   2493 /*
   2494 ==================
   2495 DrawPathLines
   2496 
   2497 Draws connections between entities.
   2498 Needs to consider all entities, not just ones on screen,
   2499 because the lines can be visible when neither end is.
   2500 Called for both camera view and xy view.
   2501 ==================
   2502 */
   2503 void DrawPathLines (void)
   2504 {
   2505 	int		i, j, k;
   2506 	vec3_t	mid, mid1;
   2507 	entity_t *se, *te;
   2508 	brush_t	*sb, *tb;
   2509 	char	*psz;
   2510 	vec3_t	dir, s1, s2;
   2511 	vec_t	len, f;
   2512 	int		arrows;
   2513 	int			num_entities;
   2514 	char		*ent_target[MAX_MAP_ENTITIES];
   2515 	entity_t	*ent_entity[MAX_MAP_ENTITIES];
   2516 
   2517 	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
   2518     return;
   2519 
   2520 	num_entities = 0;
   2521 	for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
   2522 	{
   2523 		ent_target[num_entities] = ValueForKey (te, "target");
   2524 		if (ent_target[num_entities][0])
   2525 		{
   2526 			ent_entity[num_entities] = te;
   2527 			num_entities++;
   2528 		}
   2529 	}
   2530 
   2531 	for (se = entities.next ; se != &entities ; se = se->next)
   2532 	{
   2533 		psz = ValueForKey(se, "targetname");
   2534 	
   2535 		if (psz == NULL || psz[0] == '\0')
   2536 			continue;
   2537 		
   2538 		sb = se->brushes.onext;
   2539 		if (sb == &se->brushes)
   2540 			continue;
   2541 
   2542 		for (k=0 ; k<num_entities ; k++)
   2543 		{
   2544 		if (strcmp (ent_target[k], psz))
   2545 				continue;
   2546 
   2547 			te = ent_entity[k];
   2548 			tb = te->brushes.onext;
   2549 			if (tb == &te->brushes)
   2550 				continue;
   2551 
   2552 			for (i=0 ; i<3 ; i++)
   2553 				mid[i] = (sb->mins[i] + sb->maxs[i])*0.5; 
   2554 
   2555 			for (i=0 ; i<3 ; i++)
   2556 				mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5; 
   2557 
   2558 			VectorSubtract (mid1, mid, dir);
   2559 			len = VectorNormalize (dir);
   2560 			s1[0] = -dir[1]*8 + dir[0]*8;
   2561 			s2[0] = dir[1]*8 + dir[0]*8;
   2562 			s1[1] = dir[0]*8 + dir[1]*8;
   2563 			s2[1] = -dir[0]*8 + dir[1]*8;
   2564 
   2565 			qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
   2566 
   2567 			qglBegin(GL_LINES);
   2568 			qglVertex3fv(mid);
   2569 			qglVertex3fv(mid1);
   2570 
   2571 			arrows = (int)(len / 256) + 1;
   2572 
   2573 			for (i=0 ; i<arrows ; i++)
   2574 			{
   2575 				f = len * (i + 0.5) / arrows;
   2576 
   2577 				for (j=0 ; j<3 ; j++)
   2578 					mid1[j] = mid[j] + f*dir[j];
   2579 				qglVertex3fv (mid1);
   2580 				qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
   2581 				qglVertex3fv (mid1);
   2582 				qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
   2583 			}
   2584 
   2585 			qglEnd();
   2586 		}
   2587 	}
   2588 
   2589 	return;
   2590 }
   2591 
   2592 //=============================================================
   2593 
   2594 // can be greatly simplified but per usual i am in a hurry 
   2595 // which is not an excuse, just a fact
   2596 void CXYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
   2597 {
   2598 
   2599   vec3_t vSize;
   2600   VectorSubtract(vMaxBounds, vMinBounds, vSize);
   2601 
   2602   qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65, 
   2603             g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
   2604             g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
   2605 
   2606   if (m_nViewType == XY)
   2607   {
   2608 		qglBegin (GL_LINES);
   2609 
   2610     qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f  / m_fScale, 0.0f);
   2611     qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
   2612 
   2613     qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f  / m_fScale, 0.0f);
   2614     qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f  / m_fScale, 0.0f);
   2615 
   2616     qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f  / m_fScale, 0.0f);
   2617     qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
   2618   
   2619 
   2620     qglVertex3f(vMaxBounds[nDim1] + 6.0f  / m_fScale, vMinBounds[nDim2], 0.0f);
   2621     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, vMinBounds[nDim2], 0.0f);
   2622 
   2623     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, vMinBounds[nDim2], 0.0f);
   2624     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, vMaxBounds[nDim2], 0.0f);
   2625   
   2626     qglVertex3f(vMaxBounds[nDim1] + 6.0f  / m_fScale, vMaxBounds[nDim2], 0.0f);
   2627     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, vMaxBounds[nDim2], 0.0f);
   2628 
   2629     qglEnd();
   2630 
   2631     qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]),  vMinBounds[nDim2] - 20.0  / m_fScale, 0.0f);
   2632     g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
   2633 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2634     
   2635     qglRasterPos3f (vMaxBounds[nDim1] + 16.0  / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
   2636     g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
   2637 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2638 
   2639     qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
   2640     g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
   2641 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2642 
   2643   }
   2644   else
   2645   if (m_nViewType == XZ)
   2646   {
   2647 		qglBegin (GL_LINES);
   2648 
   2649     qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f  / m_fScale);
   2650     qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
   2651 
   2652     qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f  / m_fScale);
   2653     qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f  / m_fScale);
   2654 
   2655     qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f  / m_fScale);
   2656     qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
   2657   
   2658 
   2659     qglVertex3f(vMaxBounds[nDim1] + 6.0f  / m_fScale, 0,vMinBounds[nDim2]);
   2660     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, 0,vMinBounds[nDim2]);
   2661 
   2662     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, 0,vMinBounds[nDim2]);
   2663     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, 0,vMaxBounds[nDim2]);
   2664   
   2665     qglVertex3f(vMaxBounds[nDim1] + 6.0f  / m_fScale, 0,vMaxBounds[nDim2]);
   2666     qglVertex3f(vMaxBounds[nDim1] + 10.0f  / m_fScale, 0,vMaxBounds[nDim2]);
   2667 
   2668     qglEnd();
   2669 
   2670     qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0  / m_fScale);
   2671     g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
   2672 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2673     
   2674     qglRasterPos3f (vMaxBounds[nDim1] + 16.0  / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
   2675     g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
   2676 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2677 
   2678     qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
   2679     g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
   2680 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2681 
   2682   }
   2683   else
   2684   {
   2685 		qglBegin (GL_LINES);
   2686 
   2687     qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f  / m_fScale);
   2688     qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
   2689 
   2690     qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f  / m_fScale);
   2691     qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f  / m_fScale);
   2692 
   2693     qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f  / m_fScale);
   2694     qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
   2695   
   2696 
   2697     qglVertex3f(0, vMaxBounds[nDim1] + 6.0f  / m_fScale, vMinBounds[nDim2]);
   2698     qglVertex3f(0, vMaxBounds[nDim1] + 10.0f  / m_fScale, vMinBounds[nDim2]);
   2699 
   2700     qglVertex3f(0, vMaxBounds[nDim1] + 10.0f  / m_fScale, vMinBounds[nDim2]);
   2701     qglVertex3f(0, vMaxBounds[nDim1] + 10.0f  / m_fScale, vMaxBounds[nDim2]);
   2702   
   2703     qglVertex3f(0, vMaxBounds[nDim1] + 6.0f  / m_fScale, vMaxBounds[nDim2]);
   2704     qglVertex3f(0, vMaxBounds[nDim1] + 10.0f  / m_fScale, vMaxBounds[nDim2]);
   2705 
   2706     qglEnd();
   2707 
   2708     qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]),  vMinBounds[nDim2] - 20.0  / m_fScale);
   2709     g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
   2710 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2711     
   2712     qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0  / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
   2713     g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
   2714 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2715 
   2716     qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
   2717     g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
   2718 	  qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
   2719 
   2720   }
   2721 }
   2722 
   2723 
   2724 
   2725 /*
   2726 ==============
   2727 XY_Draw
   2728 ==============
   2729 */
   2730 long g_lCount = 0;
   2731 long g_lTotal = 0;
   2732 extern void DrawBrushEntityName (brush_t *b);
   2733 
   2734 void CXYWnd::XY_Draw()
   2735 {
   2736   brush_t	*brush;
   2737 	float	w, h;
   2738 	entity_t	*e;
   2739 	double	start, end;
   2740 	double	start2, end2;
   2741 	vec3_t	mins, maxs;
   2742 	int		drawn, culled;
   2743 	int		i;
   2744 
   2745 	if (!active_brushes.next)
   2746 		return;	// not valid yet
   2747 
   2748 	if (m_bTiming)
   2749 		start = Sys_DoubleTime();
   2750 	//
   2751 	// clear
   2752 	//
   2753 	m_bDirty = false;
   2754 
   2755 	qglViewport(0, 0, m_nWidth, m_nHeight);
   2756 	qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
   2757 		            g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
   2758 		            g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
   2759 
   2760   qglClear(GL_COLOR_BUFFER_BIT);
   2761 
   2762 	//
   2763 	// set up viewpoint
   2764 	//
   2765 	qglMatrixMode(GL_PROJECTION);
   2766   qglLoadIdentity ();
   2767 
   2768 	w = m_nWidth / 2 / m_fScale;
   2769 	h = m_nHeight / 2/ m_fScale;
   2770   int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   2771   int nDim2 = (m_nViewType == XY) ? 1 : 2;
   2772 	mins[0] = m_vOrigin[nDim1] - w;
   2773 	maxs[0] = m_vOrigin[nDim1] + w;
   2774 	mins[1] = m_vOrigin[nDim2] - h;
   2775 	maxs[1] = m_vOrigin[nDim2] + h;
   2776 
   2777 
   2778 	qglOrtho (mins[0], maxs[0], mins[1], maxs[1], -8192, 8192);
   2779   //glRotatef
   2780 	//
   2781 	// now draw the grid
   2782 	//
   2783 	XY_DrawGrid ();
   2784 
   2785 	//
   2786 	// draw stuff
   2787 	//
   2788   qglShadeModel (GL_FLAT);
   2789 	qglDisable(GL_TEXTURE_2D);
   2790 	qglDisable(GL_TEXTURE_1D);
   2791 	qglDisable(GL_DEPTH_TEST);
   2792 	qglDisable(GL_BLEND);
   2793 	qglColor3f(0, 0, 0);
   2794 
   2795   //glEnable (GL_LINE_SMOOTH);
   2796 
   2797 	drawn = culled = 0;
   2798 
   2799   if (m_nViewType != XY)
   2800   {
   2801     qglPushMatrix();
   2802     if (m_nViewType == YZ)
   2803       qglRotatef (-90,  0, 1, 0);	    // put Z going up
   2804     //else
   2805       qglRotatef (-90,  1, 0, 0);	    // put Z going up
   2806   }
   2807 
   2808 	e = world_entity;
   2809 	
   2810   if (m_bTiming)
   2811 		start2 = Sys_DoubleTime();
   2812 
   2813 	for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
   2814 	{
   2815 		if (brush->mins[nDim1] > maxs[0] || 
   2816         brush->mins[nDim2] > maxs[1] || 
   2817         brush->maxs[nDim1] < mins[0] || 
   2818         brush->maxs[nDim2] < mins[1])
   2819 		{
   2820 		  culled++;
   2821 		  continue;		// off screen
   2822 		}
   2823 
   2824 	 	if (FilterBrush (brush))
   2825 	 		continue;
   2826 
   2827     drawn++;
   2828 
   2829     if (brush->owner != e && brush->owner)
   2830 		{
   2831 
   2832 			qglColor3fv(brush->owner->eclass->color);
   2833 		}
   2834     else
   2835     {
   2836 		  qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
   2837     }
   2838 
   2839     Brush_DrawXY(brush, m_nViewType);
   2840 	}
   2841   
   2842   
   2843   if (m_bTiming)
   2844 		end2 = Sys_DoubleTime();
   2845 
   2846 
   2847   DrawPathLines ();
   2848 
   2849 	//
   2850 	// draw pointfile
   2851 	//
   2852 	if ( g_qeglobals.d_pointfile_display_list)
   2853 		qglCallList (g_qeglobals.d_pointfile_display_list);
   2854 
   2855 
   2856   if (!(m_nViewType == XY))
   2857     qglPopMatrix();
   2858 
   2859   //
   2860 	// draw block grid
   2861 	//
   2862 	if ( g_qeglobals.show_blocks)
   2863 		XY_DrawBlockGrid ();
   2864 
   2865 	//
   2866 	// now draw selected brushes
   2867 	//
   2868   if (m_nViewType != XY)
   2869   {
   2870     qglPushMatrix();
   2871     if (m_nViewType == YZ)
   2872       qglRotatef (-90,  0, 1, 0);	    // put Z going up
   2873     //else
   2874       qglRotatef (-90,  1, 0, 0);	    // put Z going up
   2875   }
   2876 
   2877 
   2878   qglPushMatrix();
   2879 	qglTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
   2880 
   2881   if (RotateMode())
   2882     qglColor3f(0.8, 0.1, 0.9);
   2883   else
   2884   if (ScaleMode())
   2885     qglColor3f(0.1, 0.8, 0.1);
   2886   else
   2887     qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
   2888 
   2889 
   2890   if (g_PrefsDlg.m_bNoStipple == FALSE)
   2891   {
   2892     qglEnable (GL_LINE_STIPPLE);
   2893 	  qglLineStipple (3, 0xaaaa);
   2894   }
   2895 	qglLineWidth (2);
   2896 
   2897   vec3_t vMinBounds;
   2898   vec3_t vMaxBounds;
   2899   vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = 9999.9f;
   2900   vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = -9999.9f;
   2901 
   2902   int nSaveDrawn = drawn;
   2903   bool bFixedSize = false;
   2904 	for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
   2905 	{
   2906 		drawn++;
   2907 		Brush_DrawXY(brush, m_nViewType);
   2908 
   2909     if (!bFixedSize)
   2910     {
   2911       if (brush->owner->eclass->fixedsize)
   2912         bFixedSize = true;
   2913       if (g_PrefsDlg.m_bSizePaint)
   2914       {
   2915         for (i = 0; i < 3; i ++)
   2916         {
   2917           if (brush->mins[i] < vMinBounds[i])
   2918             vMinBounds[i] = brush->mins[i];
   2919           if (brush->maxs[i] > vMaxBounds[i])
   2920             vMaxBounds[i] = brush->maxs[i];
   2921         }
   2922       }
   2923     }
   2924 	}
   2925 
   2926   if (g_PrefsDlg.m_bNoStipple == FALSE)
   2927   {
   2928 	  qglDisable (GL_LINE_STIPPLE);
   2929   }
   2930 	qglLineWidth (1);
   2931 
   2932   if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
   2933     PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
   2934 
   2935 
   2936 	// edge / vertex flags
   2937 
   2938 	if (g_qeglobals.d_select_mode == sel_vertex)
   2939 	{
   2940 		qglPointSize (4);
   2941 		qglColor3f (0,1,0);
   2942 		qglBegin (GL_POINTS);
   2943 		for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
   2944 			qglVertex3fv (g_qeglobals.d_points[i]);
   2945 		qglEnd ();
   2946 		qglPointSize (1);
   2947 	}
   2948 	else if (g_qeglobals.d_select_mode == sel_edge)
   2949 	{
   2950 		float	*v1, *v2;
   2951 
   2952 		qglPointSize (4);
   2953 		qglColor3f (0,0,1);
   2954 		qglBegin (GL_POINTS);
   2955 		for (i=0 ; i<g_qeglobals.d_numedges ; i++)
   2956 		{
   2957 			v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
   2958 			v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
   2959 			qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
   2960 		}
   2961 		qglEnd ();
   2962 		qglPointSize (1);
   2963 	}
   2964 
   2965 
   2966 	g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_editpoint || g_qeglobals.d_select_mode == sel_addpoint));
   2967 
   2968   qglPopMatrix();
   2969 
   2970 	qglTranslatef (-g_qeglobals.d_select_translate[0], -g_qeglobals.d_select_translate[1], -g_qeglobals.d_select_translate[2]);
   2971 
   2972 
   2973   if (!(m_nViewType == XY))
   2974     qglPopMatrix();
   2975 
   2976   // area selection hack
   2977   if (g_qeglobals.d_select_mode == sel_area)
   2978   {
   2979 	  qglEnable (GL_BLEND);
   2980 	  qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   2981 	  qglColor4f(0.0, 0.0, 1.0, 0.25);
   2982     qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
   2983 	  qglDisable (GL_BLEND);
   2984   }
   2985 
   2986 
   2987   //
   2988 	// now draw camera point
   2989 	//
   2990 	DrawCameraIcon ();
   2991 	DrawZIcon ();
   2992 
   2993   if (RotateMode())
   2994   {
   2995     DrawRotateIcon();
   2996   }
   2997 
   2998   // plugin entities
   2999   //++timo TODO: use an object for the 2D view
   3000   DrawPluginEntities( (VIEWTYPE)m_nViewType );
   3001 
   3002   qglFinish();
   3003 	//QE_CheckOpenGLForErrors();
   3004 
   3005   if (m_bTiming)
   3006 	{
   3007 		end = Sys_DoubleTime ();
   3008     i = (int)(1000*(end-start));
   3009     int i3 = (int)(1000*(end2-start2));
   3010     g_lCount++;
   3011     g_lTotal += i;
   3012     int i2 = g_lTotal / g_lCount;
   3013 		Sys_Printf ("xy: %i ab: %i  avg: %i\n", i, i3, i2);
   3014 	}
   3015 }
   3016 
   3017 /*
   3018 ==============
   3019 XY_Overlay
   3020 ==============
   3021 */
   3022 void CXYWnd::XY_Overlay()
   3023 {
   3024 	int	w, h;
   3025 	int	r[4];
   3026 	static	vec3_t	lastz;
   3027 	static	vec3_t	lastcamera;
   3028 
   3029 
   3030 	qglViewport(0, 0, m_nWidth, m_nHeight);
   3031 
   3032 	//
   3033 	// set up viewpoint
   3034 	//
   3035 	qglMatrixMode(GL_PROJECTION);
   3036   qglLoadIdentity ();
   3037 
   3038 	w = m_nWidth / 2 / m_fScale;
   3039 	h = m_nHeight / 2 / m_fScale;
   3040 
   3041   qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w	, m_vOrigin[1] - h, m_vOrigin[1] + h, -8000, 8000);
   3042 	//
   3043 	// erase the old camera and z checker positions
   3044 	// if the entire xy hasn't been redrawn
   3045 	//
   3046 	if (m_bDirty)
   3047 	{
   3048 		qglReadBuffer (GL_BACK);
   3049 		qglDrawBuffer (GL_FRONT);
   3050 
   3051 		qglRasterPos2f (lastz[0]-9, lastz[1]-9);
   3052 		qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
   3053 		qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
   3054 
   3055 		qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
   3056 		qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
   3057 		qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
   3058 	}
   3059 	m_bDirty = true;
   3060 
   3061 	//
   3062 	// save off underneath where we are about to draw
   3063 	//
   3064 	VectorCopy (z.origin, lastz);
   3065 	VectorCopy (g_pParentWnd->GetCamera()->Camera().origin, lastcamera);
   3066 
   3067 	qglReadBuffer (GL_FRONT);
   3068 	qglDrawBuffer (GL_BACK);
   3069 
   3070 	qglRasterPos2f (lastz[0]-9, lastz[1]-9);
   3071 	qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
   3072 	qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
   3073 
   3074 	qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
   3075 	qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
   3076 	qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
   3077 
   3078 	//
   3079 	// draw the new icons
   3080 	//
   3081 	qglDrawBuffer (GL_FRONT);
   3082 
   3083   qglShadeModel (GL_FLAT);
   3084 	qglDisable(GL_TEXTURE_2D);
   3085 	qglDisable(GL_TEXTURE_1D);
   3086 	qglDisable(GL_DEPTH_TEST);
   3087 	qglDisable(GL_BLEND);
   3088 	qglColor3f(0, 0, 0);
   3089 
   3090 	DrawCameraIcon ();
   3091 	DrawZIcon ();
   3092 
   3093 	qglDrawBuffer (GL_BACK);
   3094   qglFinish();
   3095 }
   3096 
   3097 
   3098 vec3_t& CXYWnd::GetOrigin()
   3099 {
   3100   return m_vOrigin;
   3101 }
   3102 
   3103 void CXYWnd::SetOrigin(vec3_t org)
   3104 {
   3105 	m_vOrigin[0] = org[0];
   3106 	m_vOrigin[1] = org[1];
   3107 	m_vOrigin[2] = org[2];
   3108 }
   3109 
   3110 void CXYWnd::OnSize(UINT nType, int cx, int cy) 
   3111 {
   3112 	CWnd::OnSize(nType, cx, cy);
   3113   CRect rect;
   3114   GetClientRect(rect);
   3115   m_nWidth = rect.Width();
   3116   m_nHeight = rect.Height();
   3117 }
   3118 
   3119 brush_t hold_brushes;
   3120 void CXYWnd::Clip()
   3121 {
   3122   if (ClipMode())
   3123   {
   3124     hold_brushes.next = &hold_brushes;
   3125     ProduceSplitLists();
   3126     //brush_t* pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
   3127     brush_t* pList;
   3128 	if (g_PrefsDlg.m_bSwitchClip)
   3129 		pList = ( (m_nViewType == XZ) ? g_bSwitch: !g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
   3130 	else
   3131 		pList = ( (m_nViewType == XZ) ? !g_bSwitch: g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
   3132 
   3133     
   3134 	if (pList->next != pList)
   3135     {
   3136       Brush_CopyList(pList, &hold_brushes);
   3137       CleanList(&g_brFrontSplits);
   3138       CleanList(&g_brBackSplits);
   3139       Select_Delete();
   3140       Brush_CopyList(&hold_brushes, &selected_brushes);
   3141       if (RogueClipMode())
   3142         RetainClipMode(false);
   3143       else
   3144         RetainClipMode(true);
   3145       Sys_UpdateWindows(W_ALL);
   3146     }
   3147   }
   3148   else if (PathMode())
   3149   {
   3150     FinishSmartCreation();
   3151     if (g_pPathFunc)
   3152       g_pPathFunc(true, g_nPathCount);
   3153     g_pPathFunc = NULL;
   3154     g_nPathCount = 0;
   3155     g_bPathMode = false;
   3156   }
   3157 }
   3158 
   3159 void CXYWnd::SplitClip()
   3160 {
   3161 	ProduceSplitLists();
   3162 	if ((g_brFrontSplits.next != &g_brFrontSplits) &&
   3163 		(g_brBackSplits.next != &g_brBackSplits))
   3164 	{
   3165 		Select_Delete();
   3166 		Brush_CopyList(&g_brFrontSplits, &selected_brushes);
   3167 		Brush_CopyList(&g_brBackSplits, &selected_brushes);
   3168 		CleanList(&g_brFrontSplits);
   3169 		CleanList(&g_brBackSplits);
   3170 		if (RogueClipMode())
   3171 			RetainClipMode(false);
   3172 		else
   3173 			RetainClipMode(true);
   3174 	}
   3175 }
   3176 
   3177 void CXYWnd::FlipClip()
   3178 {
   3179   g_bSwitch = !g_bSwitch;
   3180   Sys_UpdateWindows(XY | W_CAMERA_IFON);
   3181 }
   3182 
   3183 
   3184 // makes sure the selected brush or camera is in view
   3185 void CXYWnd::PositionView()
   3186 {
   3187   int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   3188   int nDim2 = (m_nViewType == XY) ? 1 : 2;
   3189   brush_t* b = selected_brushes.next;
   3190   if (b && b->next != b)
   3191   {
   3192 	  m_vOrigin[nDim1] = b->mins[nDim1];
   3193 	  m_vOrigin[nDim2] = b->mins[nDim2];
   3194   }
   3195   else
   3196   {
   3197 	  m_vOrigin[nDim1] = g_pParentWnd->GetCamera()->Camera().origin[nDim1];
   3198 	  m_vOrigin[nDim2] = g_pParentWnd->GetCamera()->Camera().origin[nDim2];
   3199   }
   3200 }
   3201 
   3202 void CXYWnd::VectorCopyXY(vec3_t in, vec3_t out)
   3203 {
   3204   if (m_nViewType == XY)
   3205   {
   3206 	  out[0] = in[0];
   3207 	  out[1] = in[1];
   3208   }
   3209   else
   3210   if (m_nViewType == XZ)
   3211   {
   3212 	  out[0] = in[0];
   3213 	  out[2] = in[2];
   3214   }
   3215   else
   3216   {
   3217 	  out[1] = in[1];
   3218 	  out[2] = in[2];
   3219   }
   3220 }
   3221 
   3222 
   3223 void CXYWnd::OnDestroy() 
   3224 {
   3225 	QEW_StopGL( GetSafeHwnd(), s_hglrcXY, s_hdcXY );
   3226 	CWnd::OnDestroy();
   3227   // delete this;
   3228 }
   3229 
   3230 void CXYWnd::SetViewType(int n) 
   3231 { 
   3232   m_nViewType = n; 
   3233   if (g_pParentWnd->CurrentStyle() == QR_QE4)
   3234   {
   3235     CString str = "YZ Side";
   3236     if (m_nViewType == XY)
   3237       str = "XY Top";
   3238     else if (m_nViewType == XZ)
   3239       str = "XZ Front";
   3240     SetWindowText(str);
   3241   }
   3242 };
   3243 
   3244 void CXYWnd::Redraw(unsigned int nBits)
   3245 {
   3246   m_nUpdateBits = nBits;
   3247   RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
   3248   m_nUpdateBits = W_XY;
   3249 }
   3250 
   3251 bool CXYWnd::RotateMode()
   3252 {
   3253   return g_bRotateMode;
   3254 }
   3255 
   3256 bool CXYWnd::ScaleMode()
   3257 {
   3258   return g_bScaleMode;
   3259 }
   3260 
   3261 bool CXYWnd::SetRotateMode(bool bMode)
   3262 {
   3263   if (bMode && selected_brushes.next != &selected_brushes)
   3264   {
   3265     g_bRotateMode = true;
   3266     Select_GetTrueMid(g_vRotateOrigin);
   3267     g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0;
   3268   }
   3269   else 
   3270   {
   3271     if (bMode)
   3272       Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n");
   3273     g_bRotateMode = false;
   3274   }
   3275   RedrawWindow();
   3276   return g_bRotateMode;
   3277 }
   3278 
   3279 void CXYWnd::SetScaleMode(bool bMode)
   3280 {
   3281   g_bScaleMode = bMode;
   3282   RedrawWindow();
   3283 }
   3284 
   3285 
   3286 
   3287 
   3288 // xy - z
   3289 // xz - y
   3290 // yz - x
   3291 
   3292 void CXYWnd::OnSelectMouserotate() 
   3293 {
   3294 	// TODO: Add your command handler code here
   3295 	
   3296 }
   3297 
   3298 void CleanCopyEntities()
   3299 {
   3300 	entity_t* pe = g_enClipboard.next;
   3301   while (pe != NULL && pe != &g_enClipboard)
   3302   {
   3303     entity_t* next = pe->next;
   3304     epair_t* enext = NULL;
   3305 	  for (epair_t* ep = pe->epairs ; ep ; ep=enext)
   3306     {
   3307 		  enext = ep->next;
   3308       free (ep->key);
   3309       free (ep->value);
   3310 		  free (ep);
   3311     }
   3312 	  free (pe);
   3313     pe = next;
   3314   }
   3315   g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
   3316 }
   3317 
   3318 entity_t	*Entity_CopyClone (entity_t *e)
   3319 {
   3320 	entity_t	*n;
   3321 	epair_t		*ep, *np;
   3322 
   3323 	n = (entity_t*)qmalloc(sizeof(*n));
   3324 	n->brushes.onext = n->brushes.oprev = &n->brushes;
   3325 	n->eclass = e->eclass;
   3326 
   3327 	// add the entity to the entity list
   3328 	n->next = g_enClipboard.next;
   3329 	g_enClipboard.next = n;
   3330 	n->next->prev = n;
   3331 	n->prev = &g_enClipboard;
   3332 
   3333 	for (ep = e->epairs ; ep ; ep=ep->next)
   3334 	{
   3335 		np = (epair_t*)qmalloc(sizeof(*np));
   3336 		np->key = copystring(ep->key);
   3337 		np->value = copystring(ep->value);
   3338 		np->next = n->epairs;
   3339 		n->epairs = np;
   3340 	}
   3341 	return n;
   3342 }
   3343 
   3344 bool OnList(entity_t* pFind, CPtrArray* pList)
   3345 {
   3346   int nSize = pList->GetSize();
   3347   while (nSize-- > 0)
   3348   {
   3349     entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize));
   3350     if (pEntity == pFind)
   3351       return true;
   3352   }
   3353   return false;
   3354 }
   3355 
   3356 void CXYWnd::Copy()
   3357 {
   3358 #if 1
   3359   CWaitCursor WaitCursor; 
   3360   g_Clipboard.SetLength(0);
   3361   g_PatchClipboard.SetLength(0);
   3362   
   3363   Map_SaveSelected(&g_Clipboard, &g_PatchClipboard);
   3364   bool bClipped = false;
   3365   UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
   3366   if (nClipboard > 0)
   3367   {
   3368     if (OpenClipboard())
   3369     {
   3370       ::EmptyClipboard();
   3371   		long lSize = g_Clipboard.GetLength();
   3372       HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, lSize + sizeof(long));
   3373       if (h != NULL)
   3374       {
   3375         unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h));
   3376 				memcpy(cp, &lSize, sizeof(long));
   3377 				cp += sizeof(long);
   3378         g_Clipboard.SeekToBegin();
   3379         g_Clipboard.Read(cp, lSize);
   3380         ::GlobalUnlock(h);
   3381         ::SetClipboardData(nClipboard, h);
   3382         ::CloseClipboard();
   3383         bClipped = true;
   3384       }
   3385     }
   3386   }
   3387 
   3388   if (!bClipped)
   3389   {
   3390     Sys_Printf("Unable to register Windows clipboard formats, copy/paste between editors will not be possible");
   3391   }
   3392 
   3393 /*
   3394   CString strOut;
   3395   ::GetTempPath(1024, strOut.GetBuffer(1024));
   3396   strOut.ReleaseBuffer();
   3397   AddSlash(strOut);
   3398   strOut += "RadiantClipboard.$$$";
   3399   Map_SaveSelected(strOut.GetBuffer(0));
   3400 */
   3401 
   3402 #else
   3403   CPtrArray holdArray;
   3404   CleanList(&g_brClipboard);
   3405   CleanCopyEntities();
   3406 	for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
   3407   {
   3408 		if (pBrush->owner == world_entity)
   3409     {
   3410       brush_t* pClone = Brush_Clone(pBrush);
   3411       pClone->owner = NULL;
   3412   	  Brush_AddToList (pClone, &g_brClipboard);
   3413     }
   3414     else
   3415     {
   3416       if (!OnList(pBrush->owner, &holdArray))
   3417       {
   3418         entity_t* e = pBrush->owner;
   3419         holdArray.Add(reinterpret_cast<void*>(e));
   3420         entity_t* pEClone = Entity_CopyClone(e);
   3421 			  for (brush_t* pEB = e->brushes.onext ; pEB != &e->brushes ; pEB=pEB->onext)
   3422 			  {
   3423           brush_t* pClone = Brush_Clone(pEB);
   3424 	        //Brush_AddToList (pClone, &g_brClipboard);
   3425           Entity_LinkBrush(pEClone, pClone);
   3426           Brush_Build(pClone);
   3427 			  }
   3428       }
   3429     }
   3430   }
   3431 #endif
   3432 }
   3433 
   3434 void CXYWnd::Undo()
   3435 {
   3436 /*
   3437   if (g_brUndo.next != &g_brUndo)
   3438   {
   3439     g_bScreenUpdates = false; 
   3440     Select_Delete();
   3441 	  for (brush_t* pBrush = g_brUndo.next ; pBrush != NULL && pBrush != &g_brUndo ; pBrush=pBrush->next)
   3442     {
   3443       brush_t* pClone = Brush_Clone(pBrush);
   3444     	Brush_AddToList (pClone, &active_brushes);
   3445 			Entity_LinkBrush (pBrush->pUndoOwner, pClone);
   3446       Brush_Build(pClone);
   3447       Select_Brush(pClone);
   3448     }
   3449     CleanList(&g_brUndo);
   3450     g_bScreenUpdates = true; 
   3451     Sys_UpdateWindows(W_ALL);
   3452   }
   3453   else Sys_Printf("Nothing to undo.../n");
   3454 */
   3455 }
   3456 
   3457 void CXYWnd::UndoClear()
   3458 {
   3459 /*  
   3460   CleanList(&g_brUndo);
   3461 */
   3462 }
   3463 
   3464 void CXYWnd::UndoCopy()
   3465 {
   3466 /*
   3467   CleanList(&g_brUndo);
   3468 	for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
   3469   {
   3470     brush_t* pClone = Brush_Clone(pBrush);
   3471     pClone->pUndoOwner = pBrush->owner;
   3472 	  Brush_AddToList (pClone, &g_brUndo);
   3473   }
   3474 */
   3475 }
   3476 
   3477 bool CXYWnd::UndoAvailable()
   3478 {
   3479   return (g_brUndo.next != &g_brUndo);
   3480 }
   3481 
   3482 
   3483 
   3484 void CXYWnd::Paste()
   3485 {
   3486 #if 1
   3487 
   3488   CWaitCursor WaitCursor; 
   3489   bool bPasted = false;
   3490   UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
   3491   if (nClipboard > 0 && OpenClipboard() && ::IsClipboardFormatAvailable(nClipboard))
   3492   {
   3493     HANDLE h = ::GetClipboardData(nClipboard);
   3494     if (h)
   3495     {
   3496       g_Clipboard.SetLength(0);
   3497 			unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h));
   3498 			long lSize = 0;
   3499 			memcpy(&lSize, cp, sizeof(long));
   3500 			cp += sizeof(long);
   3501       g_Clipboard.Write(cp, lSize);
   3502     }
   3503     ::GlobalUnlock(h);
   3504     ::CloseClipboard();
   3505   }
   3506 
   3507   if (g_Clipboard.GetLength() > 0)
   3508   {
   3509     g_Clipboard.SeekToBegin();
   3510     int nLen = g_Clipboard.GetLength();
   3511     char* pBuffer = new char[nLen+1];
   3512 	  memset( pBuffer, 0, sizeof(pBuffer) );
   3513     g_Clipboard.Read(pBuffer, nLen);
   3514     pBuffer[nLen] = '\0';
   3515     Map_ImportBuffer(pBuffer);
   3516     delete []pBuffer;
   3517   }
   3518 
   3519 #if 0
   3520   if (g_PatchClipboard.GetLength() > 0)
   3521   {
   3522     g_PatchClipboard.SeekToBegin();
   3523     int nLen = g_PatchClipboard.GetLength();
   3524     char* pBuffer = new char[nLen+1];
   3525     g_PatchClipboard.Read(pBuffer, nLen);
   3526     pBuffer[nLen] = '\0';
   3527     Patch_ReadBuffer(pBuffer, true);
   3528     delete []pBuffer;
   3529   }
   3530 #endif
   3531 
   3532 #else
   3533   if (g_brClipboard.next != &g_brClipboard || g_enClipboard.next != &g_enClipboard)
   3534   {
   3535     Select_Deselect();
   3536 
   3537 	  for (brush_t* pBrush = g_brClipboard.next ; pBrush != NULL && pBrush != &g_brClipboard ; pBrush=pBrush->next)
   3538     {
   3539       brush_t* pClone = Brush_Clone(pBrush);
   3540 	    //pClone->owner = pBrush->owner;
   3541       if (pClone->owner == NULL)
   3542 			  Entity_LinkBrush (world_entity, pClone);
   3543     	
   3544       Brush_AddToList (pClone, &selected_brushes);
   3545       Brush_Build(pClone);
   3546     }
   3547 
   3548     for (entity_t* pEntity = g_enClipboard.next; pEntity != NULL && pEntity != &g_enClipboard; pEntity = pEntity->next)
   3549     {
   3550       entity_t* pEClone = Entity_Clone(pEntity);
   3551 			for (brush_t* pEB = pEntity->brushes.onext ; pEB != &pEntity->brushes ; pEB=pEB->onext)
   3552 			{
   3553         brush_t* pClone = Brush_Clone(pEB);
   3554 	      Brush_AddToList (pClone, &selected_brushes);
   3555         Entity_LinkBrush(pEClone, pClone);
   3556         Brush_Build(pClone);
   3557         if (pClone->owner && pClone->owner != world_entity)
   3558         {
   3559 			    UpdateEntitySel(pClone->owner->eclass);
   3560         }
   3561 			}
   3562     }
   3563 
   3564     Sys_UpdateWindows(W_ALL);
   3565   }
   3566   else Sys_Printf("Nothing to paste.../n");
   3567 #endif
   3568 }
   3569 
   3570 
   3571 vec3_t& CXYWnd::Rotation()
   3572 {
   3573   return g_vRotation;
   3574 }
   3575 
   3576 vec3_t& CXYWnd::RotateOrigin()
   3577 {
   3578   return g_vRotateOrigin;
   3579 }
   3580 
   3581 
   3582 void CXYWnd::OnTimer(UINT nIDEvent) 
   3583 {
   3584   int nDim1 = (m_nViewType == YZ) ? 1 : 0;
   3585   int nDim2 = (m_nViewType == XY) ? 1 : 2;
   3586 	m_vOrigin[nDim1] += m_ptDragAdj.x / m_fScale;
   3587 	m_vOrigin[nDim2] -= m_ptDragAdj.y / m_fScale;
   3588   Sys_UpdateWindows(W_XY | W_CAMERA);
   3589   //int nH = (m_ptDrag.y == 0) ? -1 : m_ptDrag.y;
   3590   m_ptDrag += m_ptDragAdj;
   3591   m_ptDragTotal += m_ptDragAdj;
   3592   XY_MouseMoved (m_ptDrag.x, m_nHeight - 1 - m_ptDrag.y , m_nScrollFlags);
   3593 	//m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale;
   3594 	//m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale;
   3595 }
   3596 
   3597 void CXYWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
   3598 {
   3599   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
   3600   //CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
   3601 }
   3602 
   3603 void CXYWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
   3604 {
   3605 	CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
   3606 }
   3607 
   3608 void CXYWnd::OnKillFocus(CWnd* pNewWnd) 
   3609 {
   3610 	CWnd::OnKillFocus(pNewWnd);
   3611 	SendMessage(WM_NCACTIVATE, FALSE , 0 );
   3612 }
   3613 
   3614 void CXYWnd::OnSetFocus(CWnd* pOldWnd) 
   3615 {
   3616 	CWnd::OnSetFocus(pOldWnd);
   3617 	SendMessage(WM_NCACTIVATE, TRUE , 0 );
   3618 }
   3619 
   3620 void CXYWnd::OnClose() 
   3621 {
   3622 	CWnd::OnClose();
   3623 }
   3624 
   3625 // should be static as should be the rotate scale stuff
   3626 bool CXYWnd::AreaSelectOK()
   3627 {
   3628   return RotateMode() ? false : ScaleMode() ? false : true;
   3629 }