/*
 *  Arcanum Editor - ROM area editor
 *  Copyright (C) 1999  Lucas Wall <kthulhu@usa.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *  If you make changes to the source and want to make the public you can
 *  mail the diferences to me <kthulhu@usa.net> and I'll add them to the
 *  main distribution. Of course your name will be added to the program with
 *  information about the changes you made.
 *
 *
 *  Packed on Thu Aug 19 03:02:29 1999
 *
 */


/*
 * File: arcaedView.cpp
 *
 * Changes:
 *
 * 19/08/99 Lucas Wall <kthulhu@usa.net>
 *          First source release. Its quite messy and has no
 *          comments. I never planed to release the source code... :-)
 *
 */


// arcaedView.cpp : implementation of the CArcaedView class
//

#include "stdafx.h"
#include "arcaed.h"

#include "arcaedDoc.h"
#include "arcaedView.h"
#include "AreaData.h"
#include "RoomList.h"
#include "ObjList.h"
#include "MobList.h"
#include "MobprogList.h"
#include "MainFrm.h"

#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CArcaedView

IMPLEMENT_DYNCREATE(CArcaedView, CScrollView)

BEGIN_MESSAGE_MAP(CArcaedView, CScrollView)
	//{{AFX_MSG_MAP(CArcaedView)
	ON_COMMAND(ID_AREA_DATOSGENERALES, OnAreaDatosgenerales)
	ON_COMMAND(ID_CUARTOS_LISTA, OnCuartosLista)
	ON_COMMAND(ID_MAPA_SUBIRNIVEL, OnMapaSubirnivel)
	ON_COMMAND(ID_MAPA_BAJARNIVEL, OnMapaBajarnivel)
	ON_WM_LBUTTONDOWN()
	ON_UPDATE_COMMAND_UI(ID_MAPA_BAJARNIVEL, OnUpdateMapaBajarnivel)
	ON_UPDATE_COMMAND_UI(ID_MAPA_SUBIRNIVEL, OnUpdateMapaSubirnivel)
	ON_WM_LBUTTONDBLCLK()
	ON_COMMAND(ID_CUARTOS_EDITAR, OnCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_EDITAR, OnUpdateCuartosEditar)
	ON_COMMAND(ID_CUARTOS_NUEVO, OnCuartosNuevo)
	ON_COMMAND(ID_CUARTOS_BORRAR, OnCuartosBorrar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_BORRAR, OnUpdateCuartosBorrar)
	ON_COMMAND(ID_CUARTOS_CREARABAJO, OnCuartosCrearabajo)
	ON_COMMAND(ID_CUARTOS_CREARARRIBA, OnCuartosCreararriba)
	ON_COMMAND(ID_CUARTOS_CREARESTE, OnCuartosCreareste)
	ON_COMMAND(ID_CUARTOS_CREARNORTE, OnCuartosCrearnorte)
	ON_COMMAND(ID_CUARTOS_CREAROESTE, OnCuartosCrearoeste)
	ON_COMMAND(ID_CUARTOS_CREARSUR, OnCuartosCrearsur)
	ON_COMMAND(ID_OBJETOS_LISTA, OnObjetosLista)
	ON_COMMAND(ID_MOBS_LISTA, OnMobsLista)
	ON_COMMAND(ID_MOBS_MOBPROGS, OnMobsMobprogs)
	ON_UPDATE_COMMAND_UI(ID_ZOOMIN, OnUpdateZoomin)
	ON_UPDATE_COMMAND_UI(ID_ZOOMOUT, OnUpdateZoomout)
	ON_COMMAND(ID_ZOOMIN, OnZoomin)
	ON_COMMAND(ID_ZOOMOUT, OnZoomout)
	ON_UPDATE_COMMAND_UI(ID_VER_BARRADEESTADODEMAPA, OnUpdateVerBarradeestadodemapa)
	ON_COMMAND(ID_VER_BARRADEESTADODEMAPA, OnVerBarradeestadodemapa)
	ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar)
	ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREARNORTE, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREARABAJO, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREARARRIBA, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREARESTE, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREAROESTE, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_CUARTOS_CREARSUR, OnUpdateCuartosEditar)
	ON_UPDATE_COMMAND_UI(ID_MOBS_MOBPROGS, OnUpdateMobsMobprogs)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CArcaedView construction/destruction

CArcaedView::CArcaedView()
{
	m_curroom = -1;
	m_curnivel = 0;
	m_roomsx = m_roomsy = 0;

	CSize sizeTotal;
	// TODO: calculate the total size of this view
	sizeTotal.cx = sizeTotal.cy = 100;
	SetScrollSizes(MM_TEXT, sizeTotal);
}

CArcaedView::~CArcaedView()
{
}

BOOL CArcaedView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CArcaedView drawing

void CArcaedView::OnDraw(CDC* pDC)
{
	CArcaedDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CChildFrame *wparent;
	int maxx, maxy;
	CString temp;
	char buf[1000];

	wparent = (CChildFrame*) GetParent();
	if ( m_curroom == -1 )
	{
		temp.LoadString( IDS_STATUSBAR1 );
		sprintf( buf, temp, m_curnivel );
	}
	else
	{
		temp.LoadString( IDS_STATUSBAR2 );
		sprintf( buf, temp, m_curnivel,
			pDoc->m_rooms[m_curroom]->m_vnum,
			pDoc->m_rooms[m_curroom]->m_name );
	}
	wparent->m_StatusBar.SetPaneText( 0, buf );

	DrawMap( pDC, m_curnivel - 1, -1, maxx, maxy, pDoc->m_size, 
		-pDoc->m_size/3, -pDoc->m_size/3, TRUE );
	DrawMap( pDC, m_curnivel, m_curroom, maxx, maxy, pDoc->m_size, 0, 0 );
	GetMapSize( maxx, maxy );
	SetScrollSizes( MM_TEXT, CSize( maxx+pDoc->m_size*3, maxy+pDoc->m_size*3 ) );

}

void CArcaedView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();
	CSize sizeTotal;
	// TODO: calculate the total size of this view
	sizeTotal.cx = sizeTotal.cy = 100;
	SetScrollSizes(MM_TEXT, sizeTotal);
}

/////////////////////////////////////////////////////////////////////////////
// CArcaedView printing

BOOL CArcaedView::OnPreparePrinting(CPrintInfo* pInfo)
{
	int sizex, sizey;
	CChildFrame *wparent;

	CArcaedDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	wparent = (CChildFrame*) GetParent();
	if ( pInfo->m_bPreview )
		wparent->m_StatusBar.ShowWindow( SW_HIDE );

	pInfo->SetMinPage( 1 );
	pInfo->SetMaxPage( pDoc->m_map_maxlevel - pDoc->m_map_minlevel + 1 );

	pDoc->AdjustMap( 10 );
	GetMapSize( sizex, sizey );
	m_roomsx = sizex / 30 + 1;
	m_roomsy = sizey / 30 + 1;

	return DoPreparePrinting(pInfo);
}

void CArcaedView::OnBeginPrinting(CDC* pDC, CPrintInfo* /*pInfo*/)
{
	m_prfont = new CFont();
	m_prfont->CreateFont( -90, 0, 0, 0, FW_NORMAL, FALSE,
		FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
		NULL );
}

void CArcaedView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
	CChildFrame *wparent;

	wparent = (CChildFrame*) GetParent();
	if ( pInfo->m_bPreview )
		wparent->m_StatusBar.ShowWindow( SW_SHOW );

	delete m_prfont;
}

void CArcaedView::OnPrint(CDC* pDC, CPrintInfo* pInfo) 
{
	int maxx, maxy, roomsize;
	int sizex, sizey, textx, texty;
	char buf[1000];
	CString temp;

	textx = pInfo->m_rectDraw.left + 100;
	texty = pInfo->m_rectDraw.top + 100;
	m_oldfont = pDC->SelectObject( m_prfont );
	temp.LoadString( IDS_PRINT1 );
	sprintf( buf, temp, GetDocument()->GetTitle(), 
		pInfo->m_nCurPage + GetDocument()->m_map_minlevel - 1 );
	pDC->TextOut( textx, texty, buf, strlen( buf ) );
	texty += 100;
	pDC->SelectObject( m_oldfont );
	pInfo->m_rectDraw.top = texty + 100;
	
	sizex = ( pInfo->m_rectDraw.right - pInfo->m_rectDraw.left ) / ( 3 * m_roomsx );
	sizey = ( pInfo->m_rectDraw.bottom - pInfo->m_rectDraw.top ) / ( 3 * m_roomsy );
	if ( sizey < sizex ) roomsize = sizey;
		else roomsize = sizex;
	if ( roomsize > 100 ) roomsize = 100;

	GetDocument()->AdjustMap( roomsize );
	DrawMap( pDC, pInfo->m_nCurPage + GetDocument()->m_map_minlevel - 1, 
		0, maxx, maxy, roomsize, pInfo->m_rectDraw.left, pInfo->m_rectDraw.top );
	GetDocument()->AdjustMap( GetDocument()->m_size );
}

/////////////////////////////////////////////////////////////////////////////
// CArcaedView diagnostics

#ifdef _DEBUG
void CArcaedView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CArcaedView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CArcaedDoc* CArcaedView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CArcaedDoc)));
	return (CArcaedDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CArcaedView message handlers

void CArcaedView::OnAreaDatosgenerales() 
{
	CAreaData dlg;
	CNumStrData *data;
	int i;
	
	dlg.m_Autores = GetDocument()->m_builders;
	dlg.m_Creditos = GetDocument()->m_credits;
	dlg.m_MaxNivel = GetDocument()->m_nivelmax;
	dlg.m_MinNivel = GetDocument()->m_nivelmin;
	dlg.m_MaxVnum = GetDocument()->m_maxvnum;
	dlg.m_MinVnum = GetDocument()->m_minvnum;
	dlg.m_Nombre = GetDocument()->m_name;
	dlg.m_Seguridad = GetDocument()->m_security;
	for ( i = 0; i < GetDocument()->m_recu.GetSize(); i++ )
	{
		data = new CNumStrData();
		*data = *GetDocument()->m_recu[i];
		dlg.m_recu.Add( data );
	}

	if ( dlg.DoModal() == IDOK )
	{
		GetDocument()->m_builders = dlg.m_Autores;
		GetDocument()->m_credits = dlg.m_Creditos;
		GetDocument()->m_nivelmax = dlg.m_MaxNivel;
		GetDocument()->m_nivelmin = dlg.m_MinNivel;
		GetDocument()->m_maxvnum = dlg.m_MaxVnum;
		GetDocument()->m_minvnum = dlg.m_MinVnum;
		GetDocument()->m_name = dlg.m_Nombre;
		GetDocument()->m_security = dlg.m_Seguridad;
		GetDocument()->m_recu.RemoveAll();
		for ( i = 0; i < dlg.m_recu.GetSize(); i++ )
		{
			data = new CNumStrData();
			*data = *dlg.m_recu[i];
			GetDocument()->m_recu.Add( data );
		}

		GetDocument()->SetModifiedFlag();
		GetDocument()->UpdateAllViews( this );
	}

}

void CArcaedView::OnCuartosLista() 
{
	CRoomList dlg;

	dlg.m_roomlist = &GetDocument()->m_rooms;
	if ( dlg.DoModal() == IDOK )
	{
		if ( dlg.m_curroom != NULL )
		{
			if ( GetDocument()->EditRoom( dlg.m_curroom ) == IDOK )
			{
				GetDocument()->AdjustMap( GetDocument()->m_size );
				GetDocument()->UpdateAllViews( NULL );
				GetDocument()->SetModifiedFlag();
			}
		}
	}
}

void CArcaedView::OnMapaSubirnivel() 
{
	m_curnivel++;
	m_curroom = -1;
	Invalidate();
}

void CArcaedView::OnMapaBajarnivel() 
{
	m_curnivel--;
	m_curroom = -1;
	Invalidate();
}

void CArcaedView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	int i, x, y;

	m_curroom = -1;
	x = point.x + GetScrollPosition().x;
	y = point.y + GetScrollPosition().y;
	for ( i = 0; i < GetDocument()->m_rooms.GetSize(); i++ )
	{
		CRoomData *room = GetDocument()->m_rooms[i];
		if ( !room->m_unlinked 
			&& m_curnivel == room->m_nivel
			&& x >= ( room->m_posx-10 )
			&& x <= ( room->m_posx+10 )
			&& y >= ( room->m_posy-10 )
			&& y <= ( room->m_posy+10 ) )
		{
			m_curroom = i;
			break;
		}
	}
	Invalidate( FALSE );

	CScrollView::OnLButtonDown(nFlags, point);
}

void CArcaedView::OnUpdateMapaBajarnivel(CCmdUI* pCmdUI) 
{
	if ( m_curnivel < GetDocument()->m_map_minlevel )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnUpdateMapaSubirnivel(CCmdUI* pCmdUI) 
{
	if ( m_curnivel > GetDocument()->m_map_maxlevel )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	OnCuartosEditar();
	CScrollView::OnLButtonDblClk(nFlags, point);
}

void CArcaedView::OnCuartosEditar() 
{
	if ( m_curroom != -1 ) 
	{
		if ( GetDocument()->EditRoom( GetDocument()->m_rooms[m_curroom] ) == IDOK )
		{
			GetDocument()->AdjustMap( GetDocument()->m_size );
			GetDocument()->UpdateAllViews( NULL );
			GetDocument()->SetModifiedFlag();
		}
	}
}

void CArcaedView::OnUpdateCuartosEditar(CCmdUI* pCmdUI) 
{
	if ( m_curroom == -1 )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnCuartosNuevo() 
{
	CRoomData *room;
	CString text, tit;

	room = new CRoomData();
	room->m_vnum = GetDocument()->FindFreeRoomVnum();

	if ( room->m_vnum == -1 )
	{
		text.LoadString( IDS_SINVNUM );
		tit.LoadString( IDS_ERROR );
		MessageBox( text, tit, MB_ICONERROR );
		delete room;
		return;
	}

	if ( GetDocument()->EditRoom( room ) == IDOK )
	{
		m_curroom = GetDocument()->m_rooms.Add( room );
		GetDocument()->AdjustMap( GetDocument()->m_size );
		GetDocument()->UpdateAllViews( NULL );
		GetDocument()->SetModifiedFlag();
	}
	else
		delete room;

}

void CArcaedView::OnCuartosBorrar() 
{
	int i, dir;
	CString text, tit;

	if ( m_curroom < 0 || m_curroom >= GetDocument()->m_rooms.GetSize() )
		return;

	text.LoadString( IDS_DELROOM );
	tit.LoadString( IDS_WARNING );
	if ( MessageBox( text, tit, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2 ) != IDYES ) 
		return;

	for ( i = 0; i < GetDocument()->m_rooms.GetSize(); i++ )
		for ( dir = 0; dir < 6; dir ++ )
		{
			if ( GetDocument()->m_rooms[m_curroom]->m_vnum == 
				GetDocument()->m_rooms[i]->m_exits[dir].m_vnum )
			{
				GetDocument()->m_rooms[i]->m_exits[dir].m_description = "";
				GetDocument()->m_rooms[i]->m_exits[dir].m_flags = 0;
				GetDocument()->m_rooms[i]->m_exits[dir].m_key = 0;
				GetDocument()->m_rooms[i]->m_exits[dir].m_keyword = "";
				GetDocument()->m_rooms[i]->m_exits[dir].m_vnum = 0;
			}
		}

	GetDocument()->m_rooms.RemoveAt( m_curroom );
	GetDocument()->AdjustMap( GetDocument()->m_size );
	m_curroom = -1;
	Invalidate();
	GetDocument()->UpdateAllViews( this );
	GetDocument()->SetModifiedFlag();

}

void CArcaedView::OnUpdateCuartosBorrar(CCmdUI* pCmdUI) 
{
	if ( m_curroom == -1 )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnCuartosCrearabajo() 
{
	CrearCuarto( 5 );
}

void CArcaedView::OnCuartosCreararriba() 
{
	CrearCuarto( 4 );
}

void CArcaedView::OnCuartosCreareste() 
{
	CrearCuarto( 1 );
}

void CArcaedView::OnCuartosCrearnorte() 
{
	CrearCuarto( 0 );
}

void CArcaedView::OnCuartosCrearoeste() 
{
	CrearCuarto( 3 );
}

void CArcaedView::OnCuartosCrearsur() 
{
	CrearCuarto( 2 );
}

int CArcaedView::CrearCuarto( int dir )
{
	CRoomData *room, *curroom;
	CString text, tit;

	if ( m_curroom == -1 ) return FALSE;

	curroom = GetDocument()->m_rooms[m_curroom];

	if ( curroom->m_exits[dir].m_vnum > 0 )
	{
		text.LoadString( IDS_ISEXIT );
		tit.LoadString( IDS_ERROR );
		MessageBox( text, tit, MB_ICONERROR );
		return FALSE;
	}

	room = new CRoomData();
	room->m_vnum = GetDocument()->FindFreeRoomVnum();

	switch ( dir )
	{
	case 0: room->m_exits[2].m_vnum = curroom->m_vnum; break;
	case 1: room->m_exits[3].m_vnum = curroom->m_vnum; break;
	case 2: room->m_exits[0].m_vnum = curroom->m_vnum; break;
	case 3: room->m_exits[1].m_vnum = curroom->m_vnum; break;
	case 4: room->m_exits[5].m_vnum = curroom->m_vnum; break;
	case 5: room->m_exits[4].m_vnum = curroom->m_vnum; break;
	}

	if ( room->m_vnum == -1 )
	{
		text.LoadString( IDS_SINVNUM );
		tit.LoadString( IDS_ERROR );
		MessageBox( text, tit, MB_ICONERROR );
		delete room;
		return FALSE;
	}

	if ( GetDocument()->EditRoom( room ) == IDOK )
	{
		m_curroom = GetDocument()->m_rooms.Add( room );
		curroom->m_exits[dir].m_vnum = room->m_vnum;
		GetDocument()->AdjustMap( GetDocument()->m_size );
		GetDocument()->UpdateAllViews( NULL );
		GetDocument()->SetModifiedFlag();
	}
	else
		delete room;


	return TRUE;
}

void CArcaedView::OnObjetosLista() 
{
	CObjList dlg;

	dlg.m_list = &GetDocument()->m_objs;
	dlg.m_doc = GetDocument();
	dlg.DoModal();
}

void CArcaedView::OnMobsLista() 
{
	CMobList dlg;

	dlg.m_list = &GetDocument()->m_mobs;
	dlg.m_doc = GetDocument();
	dlg.DoModal();
}

void CArcaedView::OnMobsMobprogs() 
{
	CMobProgList dlg;
	dlg.m_doc = GetDocument();
	dlg.m_mobprogs = &GetDocument()->m_mobprogs;
	dlg.DoModal();
}

void CArcaedView::DrawMap(CDC * pDC, int nivel, int select, 
	int &maxx, int &maxy, int size, int movex, int movey, 
	int gray )
{
	CArcaedDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CRoomData *room;
	CPen *oldpen, *newpen, *pendoor, *penlocked, *pengray;
	POINT trig[3];
	int sector, startx, starty, endx, endy, incx, incy;
	int i, rsize, dir, didx;
	int destx, desty, adir;
	RECT rect;
	CBrush *bnormroom, *bselroom, *bsel2room;
	CBrush *brnorm, *brdoor, *brlocked, *brgray;
	CRgn *rgn;

	bselroom = new CBrush( RGB( 0, 0, 0 ) );
	bsel2room = new CBrush( RGB( 255, 255, 255 ) );
	newpen = new CPen( PS_SOLID, size/10, RGB( 0, 180, 0 ) );
	pendoor = new CPen( PS_SOLID, size/10, RGB( 200, 200, 0 ) );
	penlocked = new CPen( PS_SOLID, size/10, RGB( 200, 0, 0 ) );
	pengray = new CPen( PS_SOLID, size/10, RGB( 210, 210, 210 ) );
	oldpen = pDC->SelectObject( pengray );

	brnorm = new CBrush();
	brdoor = new CBrush();
	brlocked = new CBrush();
	brgray = new CBrush();
	brnorm->CreateSolidBrush( RGB( 0, 180, 0 ) );
	brdoor->CreateSolidBrush( RGB( 200, 200, 0 ) );
	brlocked->CreateSolidBrush( RGB( 200, 0, 0 ) );
	brgray->CreateSolidBrush( RGB( 210, 210, 210 ) );

	int asize = (int) sqrt( pow( size, 2 ) / 12 );

	maxx = maxy = 0;
	for ( i = 0; i < pDoc->m_rooms.GetSize(); i++ )
	{
		room = pDoc->m_rooms[i];
		if ( !room->m_unlinked 
			&& room->m_nivel == nivel )
		{
			if ( i == select && !gray )
			{
				rsize = size - 2;
  				rect.top = room->m_posy - size;
				rect.bottom = room->m_posy + size;
				rect.left = room->m_posx - size;
				rect.right = room->m_posx + size;
				pDC->FillRect( &rect, bselroom );
  				rect.top = room->m_posy - size + 1; 
				rect.bottom = room->m_posy + size - 1;
				rect.left = room->m_posx - size + 1;
				rect.right = room->m_posx + size - 1;
				pDC->FillRect( &rect, bsel2room );
			}
			else rsize = size;

			if ( !gray )
			{
				for ( sector = 0; sector < tables.m_sector_colors.GetSize(); sector++ )
					if ( room->m_sector_type == tables.m_sector_colors[sector]->m_num )
						break;
				if ( sector >= tables.m_sector_colors.GetSize() )
					sector = 0;
				bnormroom = new CBrush( RGB( 
					tables.m_sector_colors[sector]->m_r,
					tables.m_sector_colors[sector]->m_g,
					tables.m_sector_colors[sector]->m_b ) );
				rect.top = room->m_posy - rsize + movey;
				rect.bottom = room->m_posy + rsize + movey;
				rect.left = room->m_posx - rsize + movex;
				rect.right = room->m_posx + rsize + movex;
				pDC->FillRect( &rect, bnormroom );
				delete bnormroom;
			}
			else
			{
				pDC->MoveTo( room->m_posx - rsize + movex, room->m_posy - rsize + movey );
				pDC->LineTo( room->m_posx + rsize + movex, room->m_posy - rsize + movey );
				pDC->LineTo( room->m_posx + rsize + movex, room->m_posy + rsize + movey );
				pDC->LineTo( room->m_posx - rsize + movex, room->m_posy + rsize + movey );
				pDC->LineTo( room->m_posx - rsize + movex, room->m_posy - rsize + movey );
			}

			for ( dir = 0; dir < 6; dir++ )
			{
				if ( !room->m_exits[dir].m_vnum ) continue;
				didx = pDoc->FindRoom( room->m_exits[dir].m_vnum );
				if ( didx == -1 
					|| pDoc->m_rooms[didx]->m_unlinked )
					continue;

				adir = dir;
				startx = room->m_posx;
				starty = room->m_posy;
				destx = pDoc->m_rooms[didx]->m_posx;
				desty = pDoc->m_rooms[didx]->m_posy;

				if ( gray )
					pDC->SelectObject( pengray );
				else if ( IS_SET( room->m_exits[dir].m_flags, tables.m_locked ) )
					pDC->SelectObject( penlocked );
				else if ( IS_SET( room->m_exits[dir].m_flags, tables.m_isdoor ) )
					pDC->SelectObject( pendoor );
				else
					pDC->SelectObject( newpen );

				if ( dir < 4 
					&& room->m_vnum != pDoc->m_rooms[didx]->m_vnum )
				{
					incx = incy = 0;

					if ( pDoc->m_rooms[didx]->m_nivel != nivel ) 
					{
						destx = room->m_posx;
						desty = room->m_posy;
						switch ( dir )
						{
						case 0: desty -= size * 7 / 2; break;
						case 1: destx += size * 7 / 2; break;
						case 2: desty += size * 7 / 2; break;
						case 3: destx -= size * 7 / 2; break;
						}
					}

					endx = destx;
					endy = desty;

					switch ( dir )
					{
					case 0: starty -= size + asize; endy += size + asize; incy = -asize; break;
					case 1: startx += size + asize; endx -= size + asize; incx = +asize; break;
					case 2: starty += size + asize; endy -= size + asize; incy = +asize; break;
					case 3: startx -= size + asize; endx += size + asize; incx = -asize; break;
					}

					pDC->MoveTo( startx + movex, starty + movey );
					pDC->LineTo( startx + incx + movex, starty + incy + movey );
					pDC->LineTo( endx - incx + movex, endy - incy + movey );
					pDC->LineTo( endx + movex, endy + movey );
				}
				else if ( dir < 4 )
				{
					switch ( dir )
					{
					case 0: 
						adir = 2; 
						starty -= size * 5 / 2 + asize + size / 10;
						startx -= size / 2;
						endx = startx + size;
						endy = starty + size * 3 / 2;
						break;
					case 1: 
						adir = 3; 
						startx += size + asize + size / 10;
						starty -= size / 2;
						endy = starty + size;
						endx = startx + size * 3 / 2;
						break;
					case 2: 
						adir = 0; 
						starty += size + asize + size / 10; 
						startx -= size / 2;
						endx = startx + size;
						endy = starty + size * 3 / 2;
						break;
					case 3: 
						adir = 1; 
						startx -= size * 5 / 2 + asize + size / 10; 
						starty -= size / 2;
						endy = starty + size;
						endx = startx + size * 3 / 2;
						break;
					}

					pDC->Ellipse( startx + movex, starty + movey, 
						endx + movex, endy + movey );
				}

				switch ( adir )
				{
				case 0:
					trig[0].x = destx - size / 3;
					trig[1].x = destx;
					trig[2].x = destx + size / 3;
					trig[0].y = desty + size * 4 / 3;
					trig[1].y = desty + size;
					trig[2].y = desty + size * 4 / 3;
					break;
				case 1:
					trig[0].x = destx - size * 4 / 3;
					trig[1].x = destx - size;
					trig[2].x = destx - size * 4 / 3;
					trig[0].y = desty - size / 3;
					trig[1].y = desty;
					trig[2].y = desty + size/3;
					break;
				case 2:
					trig[0].x = destx - size / 3;
					trig[1].x = destx;
					trig[2].x = destx + size / 3;
					trig[0].y = desty - size * 4 / 3;
					trig[1].y = desty - size;
					trig[2].y = desty - size * 4 / 3;
					break;
				case 3:
					trig[0].x = destx + size * 4 / 3;
					trig[1].x = destx + size;
					trig[2].x = destx + size * 4 / 3;
					trig[0].y = desty + size / 3;
					trig[1].y = desty;
					trig[2].y = desty - size / 3;
					break;
				case 4:
					trig[0].x = room->m_posx + size * 6 / 5;
					trig[1].x = room->m_posx + size * 17 / 10;
					trig[2].x = room->m_posx + size * 29 / 20;
					trig[0].y = room->m_posy - size / 2;
					trig[1].y = room->m_posy - size / 2;
					trig[2].y = room->m_posy - size;
					break;
				case 5:
					trig[0].x = room->m_posx + size * 6 / 5;
					trig[1].x = room->m_posx + size * 17 / 10;
					trig[2].x = room->m_posx + size * 29 / 20;
					trig[0].y = room->m_posy + size / 2;
					trig[1].y = room->m_posy + size / 2;
					trig[2].y = room->m_posy + size;
					break;
				}

				for ( int kk = 0; kk < 3; kk++ )
				{
					trig[kk].x += movex;
					trig[kk].y += movey;
				}
				endx += movex;
				endy += movey;

				rgn = new CRgn();
				if ( pDoc->m_rooms[didx]->m_nivel != nivel 
					&& dir < 4) 
					rgn->CreateEllipticRgn( endx - asize * 3 / 2, 
						endy - asize * 3 / 2, endx + asize * 3 / 2, 
						endy + asize * 3 / 2 );
				else
					rgn->CreatePolygonRgn( trig, 3, ALTERNATE );

				if ( gray )
					pDC->FillRgn( rgn, brgray );
				else if ( IS_SET( room->m_exits[dir].m_flags, tables.m_locked ) )
					pDC->FillRgn( rgn, brlocked );
				else if ( IS_SET( room->m_exits[dir].m_flags, tables.m_isdoor ) )
					pDC->FillRgn( rgn, brdoor );
				else
					pDC->FillRgn( rgn, brnorm );
				delete rgn;
			}

			if ( room->m_posx + size > maxx )
				maxx = room->m_posx + size;
			if ( room->m_posy + size > maxy )
				maxy = room->m_posy + size;
		}
	}

	pDC->SelectObject( oldpen );

	delete bselroom;
	delete bsel2room;
	delete newpen;
	delete pendoor;
	delete penlocked;
	delete brnorm;
	delete brdoor;
	delete brlocked;
	delete pengray;
	delete brgray;
}

void CArcaedView::GetMapSize(int &roomsx, int &roomsy)
{
	int maxx, maxy;
	int i, nivel;
	CArcaedDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	roomsx = roomsy = 0;
	for ( nivel = pDoc->m_map_minlevel; nivel <= pDoc->m_map_maxlevel; nivel++ )
	{

		maxx = maxy = 0;
		for ( i = 0; i < pDoc->m_rooms.GetSize(); i++ )
		{
			if ( pDoc->m_rooms[i]->m_nivel == nivel )
			{
				if ( pDoc->m_rooms[i]->m_posx > maxx ) 
					maxx = pDoc->m_rooms[i]->m_posx;
				if ( pDoc->m_rooms[i]->m_posy > maxy ) 
					maxy = pDoc->m_rooms[i]->m_posy;
			}
		}

		if ( maxx > roomsx ) roomsx = maxx;
		if ( maxy > roomsy ) roomsy = maxy;

	}

	roomsx += pDoc->m_size;
	roomsy += pDoc->m_size;

}

void CArcaedView::OnUpdateZoomin(CCmdUI* pCmdUI) 
{
	if ( GetDocument()->m_size >= 100 )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnUpdateZoomout(CCmdUI* pCmdUI) 
{
	if ( GetDocument()->m_size <= 3 )
		pCmdUI->Enable( FALSE );
	else
		pCmdUI->Enable( TRUE );
}

void CArcaedView::OnZoomin() 
{
	GetDocument()->m_size *= 2;
	GetDocument()->AdjustMap( GetDocument()->m_size );
	Invalidate();
}

void CArcaedView::OnZoomout() 
{
	GetDocument()->m_size /= 2;
	GetDocument()->AdjustMap( GetDocument()->m_size );
	Invalidate();
}

void CArcaedView::OnUpdateVerBarradeestadodemapa(CCmdUI* pCmdUI) 
{
	CChildFrame *wparent;

	wparent = (CChildFrame*) GetParent();
	if ( wparent->m_StatusBar.IsWindowVisible() )
		pCmdUI->SetCheck( TRUE );
	else
		pCmdUI->SetCheck( FALSE );
}

void CArcaedView::OnVerBarradeestadodemapa() 
{
	CChildFrame *wparent;

	wparent = (CChildFrame*) GetParent();
	if ( wparent->m_StatusBar.IsWindowVisible() )
		wparent->m_StatusBar.ShowWindow( SW_HIDE );
	else
		wparent->m_StatusBar.ShowWindow( SW_SHOW );
	wparent->RecalcLayout();
}

void CArcaedView::OnUpdateViewStatusBar(CCmdUI* pCmdUI) 
{
	CMainFrame *wparent;

	wparent = (CMainFrame*)((CChildFrame*) GetParent())->GetMDIFrame();
	if ( wparent->m_wndStatusBar.IsWindowVisible() )
		pCmdUI->SetCheck( TRUE );
	else
		pCmdUI->SetCheck( FALSE );
}

void CArcaedView::OnViewStatusBar() 
{
	CMainFrame *wparent;

	wparent = (CMainFrame*)((CChildFrame*) GetParent())->GetMDIFrame();
	if ( wparent->m_wndStatusBar.IsWindowVisible() )
		wparent->m_wndStatusBar.ShowWindow( SW_HIDE );
	else
		wparent->m_wndStatusBar.ShowWindow( SW_SHOW );
	wparent->RecalcLayout();
}

void CArcaedView::OnUpdateMobsMobprogs(CCmdUI* pCmdUI) 
{
	if ( tables.m_mobprog ) pCmdUI->Enable( TRUE );
		else pCmdUI->Enable( FALSE );
}