--- a
+++ b/Polygon.cpp
@@ -0,0 +1,351 @@
+// Polygon.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "chitem.h"
+#include "Polygon.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPolygon dialog
+
+CPolygon::CPolygon(CWnd* pParent /*=NULL*/)
+	: CDialog(CPolygon::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(CPolygon)
+	m_open = FALSE;
+	m_insertpoint = FALSE;
+	m_movepolygon = FALSE;
+	//}}AFX_DATA_INIT
+  m_vertexnum=-1;
+  m_changed=0;
+	m_graphics = false;
+  m_polynum=0;
+}
+
+void CPolygon::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CPolygon)
+	DDX_Control(pDX, IDC_VERTEXPICKER, m_vertexpicker);
+	DDX_Check(pDX, IDC_OPEN, m_open);
+	DDX_Check(pDX, IDC_INSERT, m_insertpoint);
+	DDX_Check(pDX, IDC_MOVE, m_movepolygon);
+	//}}AFX_DATA_MAP
+  DDX_Text(pDX, IDC_MINX, bbox[BBMINX]);
+  DDX_Text(pDX, IDC_MINY, bbox[BBMINY]);
+  DDX_Text(pDX, IDC_MAXX, bbox[BBMAXX]);
+  DDX_Text(pDX, IDC_MAXY, bbox[BBMAXY]);
+  if(m_vertexnum>=0)
+  {
+    DDX_Text(pDX, IDC_POSX, (short &) m_polygon[m_vertexnum].x);
+    DDX_Text(pDX, IDC_POSY, (short &) m_polygon[m_vertexnum].y);
+  }
+}
+
+void CPolygon::SetPolygon(int type, int index, short *cv, short *bb)
+{
+  m_preview.SetMapType(type, (LPBYTE) &the_area.vertexheaderlist); 
+  m_polynum=index;
+  pos=the_area.vertexheaderlist.FindIndex(index);
+  countvertex=cv;
+  bbox=bb;
+  m_polygon=(area_vertex *) the_area.vertexheaderlist.GetAt(pos);
+}
+
+static int vertexboxids[]={IDC_POSX, IDC_POSY,IDC_REVERSE, IDC_ORDER,
+0};
+
+void CPolygon::RefreshPolygon()
+{
+  CString tmpstr;
+  CButton *cb;
+  int i;  
+
+  if(!m_vertexpicker) return;
+  m_vertexpicker.ResetContent();
+  for(i=0;i<*countvertex;i++)
+  {
+    tmpstr.Format("%d  [%d.%d]",i+1, m_polygon[i].x,m_polygon[i].y);
+    m_vertexpicker.AddString(tmpstr);
+  }
+
+  if(m_vertexnum<0) m_vertexnum=0;
+  m_vertexnum=m_vertexpicker.SetCurSel(m_vertexnum);
+  i=0;
+  while(vertexboxids[i])
+  {
+    GetDlgItem(vertexboxids[i])->EnableWindow(m_vertexnum>=0);
+    i++;
+  }
+
+  cb = (CButton *) GetDlgItem(IDC_OPEN);
+  if(m_open) cb->SetWindowText("Draw open");
+  else cb->SetWindowText("Draw closed");
+  the_mos.m_drawclosed=!m_open;
+  
+  if(m_preview.m_bm)
+  {
+    DeleteObject(m_preview.m_bm);
+    m_preview.m_bm=0;
+  }
+  m_preview.m_clipx=m_polygon[m_vertexnum].x/the_mos.mosheader.dwBlockSize-m_preview.m_maxextentx/2;
+  m_preview.m_clipy=m_polygon[m_vertexnum].y/the_mos.mosheader.dwBlockSize-m_preview.m_maxextenty/2;
+  if(m_graphics)
+  {
+    m_preview.m_polygon=m_polygon;
+    m_preview.m_vertexcount=*countvertex;
+    m_preview.m_actvertex=m_vertexnum;
+    m_preview.RedrawContent();
+  }
+  m_preview.ShowWindow(m_graphics);
+}
+
+void CPolygon::RefreshVertex()
+{
+  area_vertex *newvertices;
+  CPoint point;
+  int i;
+
+  if(!m_preview) return;
+  m_changed=1;
+  point=m_preview.GetPoint(GP_POINT);
+  if(m_insertpoint)
+  {
+    m_vertexnum++;
+    newvertices=new area_vertex[(*countvertex)+1];
+    if(!newvertices)
+    {
+      MessageBox("Out of memory", "Area editor",MB_ICONSTOP|MB_OK);
+      return;
+    }
+    memcpy(newvertices, m_polygon, sizeof(area_vertex)*m_vertexnum);
+    memcpy(newvertices+m_vertexnum+1, m_polygon+m_vertexnum, sizeof(area_vertex)*((*countvertex)-m_vertexnum) );
+    the_area.vertexheaderlist.SetAt(pos,newvertices); //this will also free up the old wedvertex
+    (*countvertex)++;
+    m_polygon=newvertices;
+  }
+  else
+  {
+    if(m_vertexnum<0) return;
+    if(m_movepolygon)
+    {
+      point.x-=m_polygon[m_vertexnum].x;
+      point.y-=m_polygon[m_vertexnum].y;
+      if(CanMove(point, m_polygon, *countvertex) )
+      {
+        MessageBox("The polygon would reach over the map boundaries","Area editor",MB_ICONWARNING|MB_OK);
+      }
+      for(i=0;i<(*countvertex);i++)
+      {
+        m_polygon[i].x=(unsigned short) (m_polygon[i].x+point.x);
+        m_polygon[i].y=(unsigned short) (m_polygon[i].y+point.y);
+      }
+      UpdateData(UD_DISPLAY);
+      OnRecalcbox();
+      return;
+    }
+  }
+  m_polygon[m_vertexnum].x=(short) point.x;
+  m_polygon[m_vertexnum].y=(short) point.y;
+  UpdateData(UD_DISPLAY);
+  OnRecalcbox();
+}
+
+BEGIN_MESSAGE_MAP(CPolygon, CDialog)
+	//{{AFX_MSG_MAP(CPolygon)
+	ON_LBN_SELCHANGE(IDC_VERTEXPICKER, OnSelchangeVertexpicker)
+	ON_LBN_DBLCLK(IDC_VERTEXPICKER, OnDblclkVertexpicker)
+	ON_LBN_KILLFOCUS(IDC_VERTEXPICKER, OnKillfocusVertexpicker)
+	ON_BN_CLICKED(IDC_PREVIEW, OnPreview)
+	ON_BN_CLICKED(IDC_RECALCBOX, OnRecalcbox)
+	ON_BN_CLICKED(IDC_INSERT, OnInsert)
+	ON_BN_CLICKED(IDC_ORDER, OnOrder)
+	ON_BN_CLICKED(IDC_REVERSE, OnReverse)
+	ON_BN_CLICKED(IDC_SHIFT, OnShift)
+	ON_BN_CLICKED(IDC_MOVE, OnMove)
+	ON_BN_CLICKED(IDC_OPEN, OnOpen)
+	ON_EN_KILLFOCUS(IDC_POSX, OnKillfocusPosx)
+	ON_EN_KILLFOCUS(IDC_POSY, OnKillfocusPosy)
+	//}}AFX_MSG_MAP
+ON_COMMAND(ID_REFRESH, RefreshVertex)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPolygon message handlers
+
+BOOL CPolygon::OnInitDialog() 
+{
+  CRect rect;
+
+	CDialog::OnInitDialog();
+  if( SetupSelectPoint() )
+  {
+    return FALSE;
+  }
+
+  m_preview.m_value=-1;
+  m_preview.InitView(IW_SHOWALL|IW_SHOWGRID|IW_SETVERTEX|IW_ENABLEFILL, &the_mos); //initview must be before create
+  m_preview.Create(IDD_IMAGEVIEW,this);
+  GetWindowRect(rect);
+  m_preview.SetWindowPos(0,rect.right,rect.top,0,0,SWP_NOZORDER|SWP_HIDEWINDOW|SWP_NOSIZE);
+  RefreshPolygon();
+  //tooltips
+  {
+    m_tooltip.Create(this,TTS_NOPREFIX);
+    m_tooltip.SetMaxTipWidth(200);
+    m_tooltip.SetTipBkColor(RGB(240,224,160));
+    
+    m_tooltip.AddTool(GetDlgItem(IDOK), IDS_CANCEL);
+  }
+  UpdateData(UD_DISPLAY);
+  return TRUE;
+}
+
+void CPolygon::OnSelchangeVertexpicker() 
+{
+	m_vertexnum=m_vertexpicker.GetCurSel();
+  if(m_vertexnum>=0)
+  {
+    RefreshPolygon();
+  }
+	UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnDblclkVertexpicker() 
+{
+  area_vertex *newvertices;
+  
+  m_changed=1;
+  m_vertexnum=m_vertexpicker.GetCurSel();
+  if(m_vertexnum<0) return;
+  newvertices=new area_vertex[--(*countvertex)];
+  if(!newvertices)
+  {
+    MessageBox("Out of memory", "Area editor",MB_ICONSTOP|MB_OK);
+    (*countvertex)++;
+    return;
+  }
+  memcpy(newvertices, m_polygon, sizeof(area_vertex)*m_vertexnum);
+  memcpy(newvertices+m_vertexnum, m_polygon+m_vertexnum+1, sizeof(area_vertex)*((*countvertex)-m_vertexnum) );
+  the_area.vertexheaderlist.SetAt(pos,newvertices); //this will also free up the old wedvertex
+  m_polygon=newvertices;
+  RefreshPolygon();
+}
+
+void CPolygon::OnKillfocusVertexpicker() 
+{
+	m_vertexnum=m_vertexpicker.GetCurSel();
+	UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnPreview() 
+{
+  m_graphics=!m_graphics;
+  RefreshPolygon();
+}
+
+void CPolygon::OnRecalcbox() 
+{
+	RecalcBox((int) (*countvertex),m_polynum,(POINTS &) (bbox[BBMINX]),(POINTS &) (bbox[BBMAXX]) );
+  RefreshPolygon();
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnInsert() 
+{
+  UpdateData(UD_RETRIEVE);
+  if(m_insertpoint)
+  {
+    m_movepolygon=FALSE;
+  }
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnMove() 
+{
+  UpdateData(UD_RETRIEVE);
+  if(m_movepolygon)
+  {
+    m_insertpoint=FALSE;
+  }
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnOrder() 
+{
+  if(VertexOrder(m_polygon, *countvertex))
+  {
+    m_changed=1;
+  }
+  RefreshPolygon();
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnReverse() 
+{
+  int i;
+  area_vertex tmp;
+
+  m_changed=1;
+	for(i=0;i<(*countvertex)/2;i++)
+  {
+    tmp=m_polygon[i];
+    m_polygon[i]=m_polygon[(*countvertex)-i-1];
+    m_polygon[(*countvertex)-i-1]=tmp;
+  }
+  RefreshPolygon();
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnShift() 
+{
+  area_vertex *tmp;
+  int i;
+
+  m_changed=1;
+  tmp=new area_vertex[*countvertex];
+  if(!tmp)
+  {
+    return;
+  }
+  for(i=0;i<*countvertex;i++)
+  {
+    tmp[i]=m_polygon[(i+1)%(*countvertex)];
+  }
+  memcpy(m_polygon,tmp,(*countvertex)*sizeof(area_vertex) );
+  delete [] tmp;
+  RefreshPolygon();
+  UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnOpen() 
+{
+  UpdateData(UD_RETRIEVE);
+  RefreshPolygon(); //redraws preview
+}
+
+void CPolygon::OnKillfocusPosx() 
+{
+  UpdateData(UD_RETRIEVE);
+  RefreshPolygon();
+	UpdateData(UD_DISPLAY);
+}
+
+void CPolygon::OnKillfocusPosy() 
+{
+  UpdateData(UD_RETRIEVE);
+  RefreshPolygon();
+	UpdateData(UD_DISPLAY);
+}
+
+BOOL CPolygon::PreTranslateMessage(MSG* pMsg) 
+{
+	m_tooltip.RelayEvent(pMsg);	
+	return CDialog::PreTranslateMessage(pMsg);
+}