#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS

#include"common.h"
#include"resource.h"

extern HWND hMainWindow;
extern Data main_data;
extern int GridInterval;

namespace Automatic
{
	extern int ClockInLabel;
}

namespace Interface
{
	extern vector2D AlignedMouseCoordinates;
	extern vector2D FirstAlignedMouseCoordinates;	//始点
	extern bool Mouse_Drag;	//ドラッグ中ならtrue
	extern POINT Scroll_Coordinates;
	extern RECT ClientRect;
}

namespace Edit
{
	extern vector2D coordinates1;
	extern vector2D coordinates2;
}

namespace Place
{
	extern Direction NewDirection;
	extern char NewLabelName[SIZE_OF_LABEL_NAME];
	extern Operation NewGateOperation;
	extern unsigned int NewGateIn;
	extern Module NewModule;
}

extern vector2D AlignAngle(vector2D center,vector2D end);

namespace Drawing
{
	extern HDC hDcOne,hDcAnd,hDcOr;
	extern HFONT hFontH,hFontV;
}

extern Data copy_data;

POINT Offset;


void DrawGrid(HDC hdc)
{
	LONG i;
	HPEN hPen,hOldPen;


	hPen=CreatePen(PS_SOLID,0,RGB(192,192,192));
	hOldPen=(HPEN)SelectObject(hdc,hPen);

	for(i=Offset.x;i>0;i-=GridInterval)
	{
		MoveToEx(hdc,i,0,NULL);
		LineTo(hdc,i,Interface::ClientRect.bottom);
	}
	for(i=Offset.x+GridInterval;i<Interface::ClientRect.right;i+=GridInterval)
	{
		MoveToEx(hdc,i,0,NULL);
		LineTo(hdc,i,Interface::ClientRect.bottom);
	}
	for(i=Offset.y;i>0;i-=GridInterval)
	{
		MoveToEx(hdc,0,i,NULL);
		LineTo(hdc,Interface::ClientRect.right,i);
	}
	for(i=Offset.y+GridInterval;i<Interface::ClientRect.bottom;i+=GridInterval)
	{
		MoveToEx(hdc,0,i,NULL);
		LineTo(hdc,Interface::ClientRect.right,i);
	}
	SelectObject(hdc,hOldPen);
	DeleteObject(hPen);
}

void DrawGateRight(HDC hdc,vector2D p,int nIn,HDC hDcGateClass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[DOWN]*nIn;
	p2=v.toPOINT();
	Rectangle(hdc,p1.x,p1.y,p2.x,p2.y);
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[LEFT]*3+DirectionVector[UP]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.y+=GridInterval*2,p2.y+=GridInterval*2)
		MoveToEx(hdc,p1.x,p1.y,NULL),LineTo(hdc,p2.x,p2.y);
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	StretchBlt(hdc,p1.x+1,p1.y+1,GridInterval*2-2,GridInterval*2-2,hDcGateClass,0,0,38,38,SRCCOPY);
}

void DrawGateDown(HDC hdc,vector2D p,int nIn,HDC hDcGateClass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[UP]*2+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*nIn;
	p2=v.toPOINT();
	Rectangle(hdc,p1.x,p1.y,p2.x,p2.y);
	v=p+DirectionVector[UP]*2+DirectionVector[RIGHT]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[UP]*3+DirectionVector[RIGHT]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.x-=GridInterval*2,p2.x-=GridInterval*2)
		MoveToEx(hdc,p1.x,p1.y,NULL),LineTo(hdc,p2.x,p2.y);
	v=p+DirectionVector[UP]*2+DirectionVector[RIGHT]*(nIn-2);
	p1=v.toPOINT();
	StretchBlt(hdc,p1.x+1,p1.y+1,GridInterval*2-2,GridInterval*2-2,hDcGateClass,0,0,38,38,SRCCOPY);
}

void DrawGateLeft(HDC hdc,vector2D p,int nIn,HDC hDcGateClass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*2+DirectionVector[DOWN]*nIn;
	p2=v.toPOINT();
	Rectangle(hdc,p1.x,p1.y,p2.x,p2.y);
	v=p+DirectionVector[RIGHT]*2+DirectionVector[DOWN]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*3+DirectionVector[DOWN]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.y-=GridInterval*2,p2.y-=GridInterval*2)
		MoveToEx(hdc,p1.x,p1.y,NULL),LineTo(hdc,p2.x,p2.y);
	v=p+DirectionVector[DOWN]*(nIn-2);
	p1=v.toPOINT();
	StretchBlt(hdc,p1.x+1,p1.y+1,GridInterval*2-2,GridInterval*2-2,hDcGateClass,0,0,38,38,SRCCOPY);
}

void DrawGateUp(HDC hdc,vector2D p,int nIn,HDC hDcGateClass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*nIn+DirectionVector[DOWN]*2;
	p2=v.toPOINT();
	Rectangle(hdc,p1.x,p1.y,p2.x,p2.y);
	v=p+DirectionVector[DOWN]*2+DirectionVector[LEFT]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[DOWN]*3+DirectionVector[LEFT]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.x+=GridInterval*2,p2.x+=GridInterval*2)
		MoveToEx(hdc,p1.x,p1.y,NULL),LineTo(hdc,p2.x,p2.y);
	v=p+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	StretchBlt(hdc,p1.x+1,p1.y+1,GridInterval*2-2,GridInterval*2-2,hDcGateClass,0,0,38,38,SRCCOPY);
}

void Draw_Gate(HDC hdc,vector2D p,Direction d,int nIn,HDC hDcGateClass)
{
	POINT pnt;

	pnt=p.toPOINT();

	switch(d)
	{
	case RIGHT:
		DrawGateRight(hdc,p,nIn,hDcGateClass);
		MoveToEx(hdc,pnt.x,pnt.y,NULL);
		pnt.x+=GridInterval;
		LineTo(hdc,pnt.x,pnt.y);
		break;
	case DOWN:
		DrawGateDown(hdc,p,nIn,hDcGateClass);
		MoveToEx(hdc,pnt.x,pnt.y,NULL);
		pnt.y+=GridInterval;
		LineTo(hdc,pnt.x,pnt.y);
		break;
	case LEFT:
		DrawGateLeft(hdc,p,nIn,hDcGateClass);
		MoveToEx(hdc,pnt.x,pnt.y,NULL);
		pnt.x-=GridInterval;
		LineTo(hdc,pnt.x,pnt.y);
		break;
	case UP:
		DrawGateUp(hdc,p,nIn,hDcGateClass);
		MoveToEx(hdc,pnt.x,pnt.y,NULL);
		pnt.y-=GridInterval;
		LineTo(hdc,pnt.x,pnt.y);
		break;
	}
}

void Draw_Gate_With_Not(HDC hdc,vector2D p,Direction d,int nIn,HDC hDcGateClass)
{
	POINT pnt;
	pnt=p.toPOINT();

	Draw_Gate(hdc,p,d,nIn,hDcGateClass);

	switch(d)
	{
	case RIGHT:
		Ellipse(hdc,pnt.x,pnt.y-GridInterval/4,pnt.x+GridInterval/2,pnt.y+GridInterval/4);
		break;
	case DOWN:
		Ellipse(hdc,pnt.x-GridInterval/4,pnt.y,pnt.x+GridInterval/4,pnt.y+GridInterval/2);
		break;
	case LEFT:
		Ellipse(hdc,pnt.x-GridInterval/2,pnt.y-GridInterval/4,pnt.x,pnt.y+GridInterval/4);
		break;
	case UP:
		Ellipse(hdc,pnt.x-GridInterval/4,pnt.y-GridInterval/2,pnt.x+GridInterval/4,pnt.y);
		break;
	}
}

void ClassifyOperationAndDraw(HDC hdc,Operation op,vector2D v,Direction d,int nIn)
{
	switch(op)
	{
	case NOT:
		Draw_Gate_With_Not(hdc,v,d,nIn,Drawing::hDcOne);
		break;
	case OR:
		Draw_Gate(hdc,v,d,nIn,Drawing::hDcOr);
		break;
	case AND:
		Draw_Gate(hdc,v,d,nIn,Drawing::hDcAnd);
		break;
	case NOR:
		Draw_Gate_With_Not(hdc,v,d,nIn,Drawing::hDcOr);
		break;
	case NAND:
		Draw_Gate_With_Not(hdc,v,d,nIn,Drawing::hDcAnd);
		break;
	}
}

//ゲートの描画
void Data::DrawGate(HDC hdc)
{
	HPEN hPen=CreatePen(PS_SOLID,1,RGB(255,0,0));
	for(unsigned int i=0;i<gate.size();i++)
	{
		Gate g=gate[i];
		ClassifyOperationAndDraw(hdc,g.operation(),GetNodeCoordinate(g.NodeOutIndex())-DirectionVector[g.direction()],g.direction(),g.nIn());
	}
	DeleteObject(hPen);
}

//ゲートのテンプレートの描画
void DrawTemplate(HDC hdc)
{
	HPEN hPen,hOldPen;
	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);	//正しい処理か確認
	ClassifyOperationAndDraw(hdc,Place::NewGateOperation,Interface::AlignedMouseCoordinates,Place::NewDirection,Place::NewGateIn);
	SelectObject(hdc,hOldPen);	//正しい処理か確認
	DeleteObject(hPen);
}

//モジュールの描画
void Data::DrawModule(HDC hdc)
{
	vector2D v;
	POINT pnt;

	POINT upper_left_point;
	POINT lower_right_point;


	for(unsigned int i=0;i<module.size();i++)
	{
		Module mdl=module[i];

		v=mdl.Center()+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin())+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		upper_left_point=v.toPOINT();
		v=mdl.Center()+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin())+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		lower_right_point=v.toPOINT();
		Rectangle(hdc,upper_left_point.x,upper_left_point.y,lower_right_point.x,lower_right_point.y);

		v=mdl.Center()+DirectionVector[UP]*(mdl.GetLeftSize()-1)+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		pnt=v.toPOINT();
		SelectObject(hdc,Drawing::hFontH);
		for(int i=0;i<mdl.GetLeftSize();i++,pnt.y+=GridInterval*2)
		{
			switch(mdl.GetLeft(i).GetDeviceClass())
			{
				int len;
			case module_in:
				len=strlen(mdl.GetInput(mdl.GetLeft(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+1,pnt.y-GridInterval+1,mdl.GetInput(mdl.GetLeft(i).GetDeviceIndex()).name(),len);
				break;
			case module_out:
				len=strlen(mdl.GetOutput(mdl.GetLeft(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+1,pnt.y-GridInterval+1,mdl.GetOutput(mdl.GetLeft(i).GetDeviceIndex()).name(),len);
				break;
			}
		}

		v=mdl.Center()+DirectionVector[RIGHT]*(mdl.GetUpSize()-1)+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin());
		pnt=v.toPOINT();
		SelectObject(hdc,Drawing::hFontV);
		for(int i=0;i<mdl.GetUpSize();i++,pnt.x-=GridInterval*2)
		{
			switch(mdl.GetUp(i).GetDeviceClass())
			{
				int len;
			case module_in:
				len=strlen(mdl.GetInput(mdl.GetUp(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+GridInterval-1,pnt.y+1,mdl.GetInput(mdl.GetUp(i).GetDeviceIndex()).name(),len);
				break;
			case module_out:
				len=strlen(mdl.GetOutput(mdl.GetUp(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+GridInterval-1,pnt.y+1,mdl.GetOutput(mdl.GetUp(i).GetDeviceIndex()).name(),len);
				break;
			}
		}

		v=mdl.Center()+DirectionVector[DOWN]*(mdl.GetRightSize()-1)+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		pnt=v.toPOINT();
		SelectObject(hdc,Drawing::hFontH);
		for(int i=0;i<mdl.GetRightSize();i++,pnt.y-=GridInterval*2)
		{
			switch(mdl.GetRight(i).GetDeviceClass())
			{
				int len;
			case module_in:
				len=strlen(mdl.GetInput(mdl.GetRight(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x-GridInterval*len-1,pnt.y-GridInterval+1,mdl.GetInput(mdl.GetRight(i).GetDeviceIndex()).name(),len);
				break;
			case module_out:
				len=strlen(mdl.GetOutput(mdl.GetRight(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x-GridInterval*len-1,pnt.y-GridInterval+1,mdl.GetOutput(mdl.GetRight(i).GetDeviceIndex()).name(),len);
				break;
			}
		}

		v=mdl.Center()+DirectionVector[LEFT]*(mdl.GetDownSize()-1)+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin());
		pnt=v.toPOINT();
		SelectObject(hdc,Drawing::hFontV);
		for(int i=0;i<mdl.GetDownSize();i++,pnt.x+=GridInterval*2)
		{
			switch(mdl.GetDown(i).GetDeviceClass())
			{
				int len;
			case module_in:
				len=strlen(mdl.GetInput(mdl.GetDown(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+GridInterval-1,pnt.y-GridInterval*len-1,mdl.GetInput(mdl.GetDown(i).GetDeviceIndex()).name(),len);
				break;
			case module_out:
				len=strlen(mdl.GetOutput(mdl.GetDown(i).GetDeviceIndex()).name());
				TextOut(hdc,pnt.x+GridInterval-1,pnt.y-GridInterval*len-1,mdl.GetOutput(mdl.GetDown(i).GetDeviceIndex()).name(),len);
				break;
			}
		}

		v=mdl.Center()+DirectionVector[UP]*(mdl.GetLeftSize()-1)+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetLeftSize();i++,pnt.y+=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x-GridInterval,pnt.y);

		v=mdl.Center()+DirectionVector[RIGHT]*(mdl.GetUpSize()-1)+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetUpSize();i++,pnt.x-=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x,pnt.y-GridInterval);

		v=mdl.Center()+DirectionVector[DOWN]*(mdl.GetRightSize()-1)+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetRightSize();i++,pnt.y-=GridInterval*2)MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x+GridInterval,pnt.y);

		v=mdl.Center()+DirectionVector[LEFT]*(mdl.GetDownSize()-1)+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetDownSize();i++,pnt.x+=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x,pnt.y+GridInterval);
	}
}

void DrawModuleTemplate(HDC hdc,Module *pMdl)
{
	HPEN hPen,hOldPen;

	vector2D v;
	POINT pnt;

	POINT upper_left_point;
	POINT lower_right_point;

	SetTextColor(hdc,RGB(127,127,127));

	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);	//正しい処理か確認

	v=Interface::AlignedMouseCoordinates+DirectionVector[UP]*(pMdl->InternalHalfHeight()+pMdl->UpMargin())+DirectionVector[LEFT]*(pMdl->InternalHalfWidth()+pMdl->LeftMargin());
	upper_left_point=v.toPOINT();
	v=Interface::AlignedMouseCoordinates+DirectionVector[DOWN]*(pMdl->InternalHalfHeight()+pMdl->DownMargin())+DirectionVector[RIGHT]*(pMdl->InternalHalfWidth()+pMdl->RightMargin());
	lower_right_point=v.toPOINT();
	Rectangle(hdc,upper_left_point.x,upper_left_point.y,lower_right_point.x,lower_right_point.y);


	v=Interface::AlignedMouseCoordinates+DirectionVector[UP]*(pMdl->GetLeftSize()-1)+DirectionVector[LEFT]*(pMdl->InternalHalfWidth()+pMdl->LeftMargin());
	pnt=v.toPOINT();
	SelectObject(hdc,Drawing::hFontH);
	for(int i=0;i<pMdl->GetLeftSize();i++,pnt.y+=GridInterval*2)
	{
		switch(pMdl->GetLeft(i).GetDeviceClass())
		{
			int len;
		case module_in:
			len=strlen(pMdl->GetInput(pMdl->GetLeft(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+1,pnt.y-GridInterval+1,pMdl->GetInput(pMdl->GetLeft(i).GetDeviceIndex()).name(),len);
			break;
		case module_out:
			len=strlen(pMdl->GetOutput(pMdl->GetLeft(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+1,pnt.y-GridInterval+1,pMdl->GetOutput(pMdl->GetLeft(i).GetDeviceIndex()).name(),len);
			break;
		}
	}

	v=Interface::AlignedMouseCoordinates+DirectionVector[RIGHT]*(pMdl->GetUpSize()-1)+DirectionVector[UP]*(pMdl->InternalHalfHeight()+pMdl->UpMargin());
	pnt=v.toPOINT();
	SelectObject(hdc,Drawing::hFontV);
	for(int i=0;i<pMdl->GetUpSize();i++,pnt.x-=GridInterval*2)
	{
		switch(pMdl->GetUp(i).GetDeviceClass())
		{
			int len;
		case module_in:
			len=strlen(pMdl->GetInput(pMdl->GetUp(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+GridInterval-1,pnt.y+1,pMdl->GetInput(pMdl->GetUp(i).GetDeviceIndex()).name(),len);
			break;
		case module_out:
			len=strlen(pMdl->GetOutput(pMdl->GetUp(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+GridInterval-1,pnt.y+1,pMdl->GetOutput(pMdl->GetUp(i).GetDeviceIndex()).name(),len);
			break;
		}
	}

	v=Interface::AlignedMouseCoordinates+DirectionVector[DOWN]*(pMdl->GetRightSize()-1)+DirectionVector[RIGHT]*(pMdl->InternalHalfWidth()+pMdl->RightMargin());
	pnt=v.toPOINT();
	SelectObject(hdc,Drawing::hFontH);
	for(int i=0;i<pMdl->GetRightSize();i++,pnt.y-=GridInterval*2)
	{
		switch(pMdl->GetRight(i).GetDeviceClass())
		{
			int len;
		case module_in:
			len=strlen(pMdl->GetInput(pMdl->GetRight(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x-GridInterval*len-1,pnt.y-GridInterval+1,pMdl->GetInput(pMdl->GetRight(i).GetDeviceIndex()).name(),len);
			break;
		case module_out:
			len=strlen(pMdl->GetOutput(pMdl->GetRight(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x-GridInterval*len-1,pnt.y-GridInterval+1,pMdl->GetOutput(pMdl->GetRight(i).GetDeviceIndex()).name(),len);
			break;
		}
	}

	v=Interface::AlignedMouseCoordinates+DirectionVector[LEFT]*(pMdl->GetDownSize()-1)+DirectionVector[DOWN]*(pMdl->InternalHalfHeight()+pMdl->DownMargin());
	pnt=v.toPOINT();
	SelectObject(hdc,Drawing::hFontV);
	for(int i=0;i<pMdl->GetDownSize();i++,pnt.x+=GridInterval*2)
	{
		switch(pMdl->GetDown(i).GetDeviceClass())
		{
			int len;
		case module_in:
			len=strlen(pMdl->GetInput(pMdl->GetDown(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+GridInterval-1,pnt.y-GridInterval*len-1,pMdl->GetInput(pMdl->GetDown(i).GetDeviceIndex()).name(),len);
			break;
		case module_out:
			len=strlen(pMdl->GetOutput(pMdl->GetDown(i).GetDeviceIndex()).name());
			TextOut(hdc,pnt.x+GridInterval-1,pnt.y-GridInterval*len-1,pMdl->GetOutput(pMdl->GetDown(i).GetDeviceIndex()).name(),len);
			break;
		}
	}

	v=Interface::AlignedMouseCoordinates+DirectionVector[UP]*(pMdl->GetLeftSize()-1)+DirectionVector[LEFT]*(pMdl->InternalHalfWidth()+pMdl->LeftMargin());
	pnt=v.toPOINT();
	for(int i=0;i<pMdl->GetLeftSize();i++,pnt.y+=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x-GridInterval,pnt.y);

	v=Interface::AlignedMouseCoordinates+DirectionVector[RIGHT]*(pMdl->GetUpSize()-1)+DirectionVector[UP]*(pMdl->InternalHalfHeight()+pMdl->UpMargin());
	pnt=v.toPOINT();
	for(int i=0;i<pMdl->GetUpSize();i++,pnt.x-=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x,pnt.y-GridInterval);

	v=Interface::AlignedMouseCoordinates+DirectionVector[DOWN]*(pMdl->GetRightSize()-1)+DirectionVector[RIGHT]*(pMdl->InternalHalfWidth()+pMdl->RightMargin());
	pnt=v.toPOINT();
	for(int i=0;i<pMdl->GetRightSize();i++,pnt.y-=GridInterval*2)MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x+GridInterval,pnt.y);

	v=Interface::AlignedMouseCoordinates+DirectionVector[LEFT]*(pMdl->GetDownSize()-1)+DirectionVector[DOWN]*(pMdl->InternalHalfHeight()+pMdl->DownMargin());
	pnt=v.toPOINT();
	for(int i=0;i<pMdl->GetDownSize();i++,pnt.x+=GridInterval*2)	MoveToEx(hdc,pnt.x,pnt.y,NULL),LineTo(hdc,pnt.x,pnt.y+GridInterval);
	
	SelectObject(hdc,hOldPen);	//正しい処理か確認
	DeleteObject(hPen);
}

POINT CalculateOffset()
{
	POINT a;
	a.x=(Interface::ClientRect.right-Interface::ClientRect.left)/2+Interface::Scroll_Coordinates.x;
	a.y=(Interface::ClientRect.bottom-Interface::ClientRect.top)/2+Interface::Scroll_Coordinates.y;
	return a;
}

void Data::DrawNode(HDC hdc)
{
	HPEN hGreenPen,hRedPen,hOldPen;
	Node n;
	vector2D v;
	hGreenPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
	hRedPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
	hOldPen=(HPEN)SelectObject(hdc,hGreenPen);
	for(unsigned int i=0;i<node_data.size();i++)
	{
		if(!node_data[i].isAllRight())
		{
			POINT p1,p2;
			if(node_data[i].isShort())SelectObject(hdc,hRedPen);
			n=node(i);
			p1=n.position().toPOINT();
			for(int j=0;j<8;j++)
			{
				MoveToEx(hdc,p1.x,p1.y,NULL);
				if(n.isBranchExist((Direction)j))
				{
					v=DirectionVector[j];
					p2=v.MulGridInterval();
					p2.x=p1.x+p2.x/3;
					p2.y=p1.y+p2.y/3;
					LineTo(hdc,p2.x,p2.y);
				}
			}
			if(node_data[i].isShort())SelectObject(hdc,hGreenPen);
		}
	}
	SelectObject(hdc,hOldPen);
	DeleteObject(hRedPen);
	DeleteObject(hGreenPen);
	for(unsigned int i=0;i<node_data.size();i++)
	{
		POINT p1;
		n=node(i);
		p1=n.position().toPOINT();
		if(node_data[i].nBranch()>=3)
		{
			SetPixelV(hdc,p1.x,p1.y,RGB(0,0,0));
			MoveToEx(hdc,p1.x-1,p1.y-1,NULL),LineTo(hdc,p1.x+1,p1.y-1);
			MoveToEx(hdc,p1.x+1,p1.y-1,NULL),LineTo(hdc,p1.x+1,p1.y+1);
			MoveToEx(hdc,p1.x+1,p1.y+1,NULL),LineTo(hdc,p1.x-1,p1.y+1);
			MoveToEx(hdc,p1.x-1,p1.y+1,NULL),LineTo(hdc,p1.x-1,p1.y-1);
		}
	}
}

void Data::DrawConductor(HDC hdc)
{
	HPEN hBluePen,hOldPen;
	POINT p;
	hBluePen=CreatePen(PS_SOLID,1,RGB(0,0,255));
	for(unsigned int i=0;i<conductor.size();i++)
	{
		if(conductor[i].isMultipath())
			hOldPen=(HPEN)SelectObject(hdc,hBluePen);

		p=GetNodeCoordinate(conductor[i].nodeindex0()).toPOINT();
		MoveToEx(hdc,p.x,p.y,NULL);
		p=GetNodeCoordinate(conductor[i].nodeindex1()).toPOINT();
		LineTo(hdc,p.x,p.y);

		if(conductor[i].isMultipath())
			SelectObject(hdc,hOldPen);	//正しい処理か確認
	}
	DeleteObject(hBluePen);
}

void DrawConductorTemplate(HDC hdc)
{
	HPEN hPen,hOldPen;
	POINT p;
	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);	//正しい処理か確認

	p=Interface::FirstAlignedMouseCoordinates.toPOINT();
	MoveToEx(hdc,p.x,p.y,NULL);
	p=AlignAngle(Interface::FirstAlignedMouseCoordinates,Interface::AlignedMouseCoordinates).toPOINT();
	LineTo(hdc,p.x,p.y);

	SelectObject(hdc,hOldPen);	//正しい処理か確認
	DeleteObject(hPen);
}

void Data::DrawInputLabel(HDC hdc)
{
	POINT p1,p2;
	vector2D v;
	Direction d;
	SetTextColor(hdc,0);
	for(unsigned int i=0;i<input.size();i++)
	{
		int len;
		len=lstrlen(input[i].name());
		d=input[i].direction();
		p1=(GetNodeCoordinate(input[i].nodeindex())-DirectionVector[input[i].direction()]).toPOINT();
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[d];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x,p1.y+p2.y);
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[(d+3)%8];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[(d+5)%8];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);
		switch(d)
		{
		case RIGHT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p1.x-GridInterval*(len+2),p1.y-GridInterval,input[i].name(),len);
			break;
		case DOWN:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p1.x+GridInterval,p1.y-GridInterval*(len+2),input[i].name(),len);
			break;
		case LEFT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p1.x+GridInterval*2,p1.y-GridInterval,input[i].name(),len);
			break;
		case UP:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p1.x+GridInterval,p1.y+GridInterval*2,input[i].name(),len);
			break;
		}
	}
}

void Data::DrawInputState(HDC hdc)
{
	POINT p;
	Direction d;
	for(unsigned int i=0;i<input.size();i++)
	{
		bool state=input[i].GetState();
		char *str;
		d=input[i].direction();
		p=(GetNodeCoordinate(input[i].nodeindex())-DirectionVector[input[i].direction()]).toPOINT();
		if(state)
			SetTextColor(hdc,RGB(255,0,0));
		else
			SetTextColor(hdc,RGB(0,0,255));
		str=state ? "1" : "0";
		switch(d)
		{
		case RIGHT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p.x-GridInterval*2,p.y-GridInterval,str,1);
			break;
		case DOWN:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p.x+GridInterval,p.y-GridInterval*2,str,1);
			break;
		case LEFT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p.x+GridInterval,p.y-GridInterval,str,1);
			break;
		case UP:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p.x+GridInterval,p.y+GridInterval,str,1);
			break;
		}
	}
	SetTextColor(hdc,RGB(0,0,0));
}

void DrawInputTemplate(HDC hdc)
{
	HPEN hPen,hOldPen;
	POINT p1,p2;
	vector2D v;
	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);

	p1=Interface::AlignedMouseCoordinates.toPOINT();
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[Place::NewDirection];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x,p1.y+p2.y);
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[(Place::NewDirection+3)%8];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[(Place::NewDirection+5)%8];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);

	SelectObject(hdc,hOldPen);
	DeleteObject(hPen);
}

void Data::DrawOutputLabel(HDC hdc)
{
	POINT p1,p2;
	vector2D v;
	Direction d;
	SetTextColor(hdc,0);
	for(unsigned int i=0;i<output.size();i++)
	{
		int len;
		len=lstrlen(output[i].name());
		d=output[i].direction();
		p1=(GetNodeCoordinate(output[i].nodeindex())-DirectionVector[output[i].direction()]).toPOINT();
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[d];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x,p1.y+p2.y);
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[(d+1)%8];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);
		MoveToEx(hdc,p1.x,p1.y,NULL);
		v=DirectionVector[(d+7)%8];
		p2=v.MulGridInterval();
		LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);

		switch(d)
		{
		case RIGHT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p1.x-GridInterval*(len+1),p1.y-GridInterval,output[i].name(),len);
			break;
		case DOWN:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p1.x+GridInterval,p1.y-GridInterval*(len+1),output[i].name(),len);
			break;
		case LEFT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p1.x+GridInterval*3/2,p1.y-GridInterval,output[i].name(),len);
			break;
		case UP:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p1.x+GridInterval,p1.y+GridInterval*3/2,output[i].name(),len);
			break;
		}
	}
}

void Data::DrawOutputState(HDC hdc)
{
	char *str;
	POINT p;
	for(unsigned int i=0;i<output.size();i++)
	{
		bool state=false;
		p=(GetNodeCoordinate(output[i].nodeindex())-DirectionVector[output[i].direction()]).toPOINT();
		str="";
		switch(output[i].GetSourceDevClass())
		{
		case label_input:
			state=input[output[i].GetSourceDevIndex()].GetState();
			str=state ? "1" : "0";
			break;
		case gate_out:
			state=gate[output[i].GetSourceDevIndex()].GetState();
			str=state ? "1" : "0";
			break;
		case module_out:
			//ここでエラー
			state=module[output[i].GetSourceDevIndex()].GetState(output[i].GetSourceDevSubIndex());
			str=state ? "1" : "0";
			break;
		}
		if(state)
			SetTextColor(hdc,RGB(255,0,0));
		else
			SetTextColor(hdc,RGB(0,0,255));

		switch(output[i].direction())
		{
		case RIGHT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p.x-GridInterval,p.y-GridInterval,str,1);
			break;
		case DOWN:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p.x+GridInterval,p.y-GridInterval,str,1);
			break;
		case LEFT:
			SelectObject(hdc,Drawing::hFontH);
			TextOut(hdc,p.x+GridInterval/2,p.y-GridInterval,str,1);
			break;
		case UP:
			SelectObject(hdc,Drawing::hFontV);
			TextOut(hdc,p.x+GridInterval,p.y+GridInterval/2,str,1);
			break;
		}
	}
	SetTextColor(hdc,RGB(0,0,0));
}

void DrawOutputTemplate(HDC hdc)
{
	HPEN hPen,hOldPen;
	POINT p1,p2;
	vector2D v;
	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);

	p1=Interface::AlignedMouseCoordinates.toPOINT();
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[ReverseDirection(Place::NewDirection)];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x,p1.y+p2.y);
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[(ReverseDirection(Place::NewDirection)+1)%8];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);
	MoveToEx(hdc,p1.x,p1.y,NULL);
	v=DirectionVector[(ReverseDirection(Place::NewDirection)+7)%8];
	p2=v.MulGridInterval();
	LineTo(hdc,p1.x+p2.x/2,p1.y+p2.y/2);

	SelectObject(hdc,hOldPen);
	DeleteObject(hPen);
}

void Data::DrawNote(HDC hdc)
{
	for(unsigned int i=0;i<note.size();i++)
	{
		int len;
		POINT p;
		len=lstrlen(note[i].name());
		p=note[i].position().toPOINT();
		Ellipse(hdc,p.x-2,p.y-2,p.x+2,p.y+2);
		SelectObject(hdc,Drawing::hFontH);
		TextOut(hdc,p.x+GridInterval/2,p.y-GridInterval/2,note[i].name(),len);
	}
}

void DrawNoteTemplate(HDC hdc)
{
	HPEN hPen,hOldPen;
	POINT p;

	hPen=CreatePen(PS_SOLID,1,RGB(127,127,127));
	hOldPen=(HPEN)SelectObject(hdc,hPen);

	p=Interface::AlignedMouseCoordinates.toPOINT();
	Ellipse(hdc,p.x-2,p.y-2,p.x+2,p.y+2);

	SelectObject(hdc,hOldPen);
	DeleteObject(hPen);
}

void Data::DrawPasteTemplate(HDC hdc)
{
	vector2D MouseCoordinates=Interface::AlignedMouseCoordinates;
	for(unsigned int i=0;i<note.size();i++)
	{
		vector2D pos;
		pos=note[i].position();
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		DrawNoteTemplate(hdc);
	}
	for(unsigned int i=0;i<input.size();i++)
	{
		vector2D pos;
		pos=node_data[input[i].nodeindex()].position()-DirectionVector[input[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = input[i].direction();
		strcpy_s(Place::NewLabelName,input[i].name());
		DrawInputTemplate(hdc);
	}
	for(unsigned int i=0;i<output.size();i++)
	{
		vector2D pos;
		pos=node_data[output[i].nodeindex()].position()-DirectionVector[output[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = ReverseDirection(output[i].direction());
		strcpy_s(Place::NewLabelName,output[i].name());
		DrawOutputTemplate(hdc);
	}
	for(unsigned int i=0;i<gate.size();i++)
	{
		Interface::AlignedMouseCoordinates=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[gate[i].ReverseDirection()]+MouseCoordinates;
		Place::NewDirection=gate[i].direction();
		Place::NewGateOperation=gate[i].operation();
		Place::NewGateIn=gate[i].nIn();
		DrawTemplate(hdc);
	}
	for(unsigned int i=0;i<conductor.size();i++)
	{
		Interface::FirstAlignedMouseCoordinates=node_data[conductor[i].nodeindex0()].position()+MouseCoordinates;
		Interface::AlignedMouseCoordinates=node_data[conductor[i].nodeindex1()].position()+MouseCoordinates;
		DrawConductorTemplate(hdc);
	}
	for(unsigned int i=0;i<module.size();i++)
	{
		Interface::AlignedMouseCoordinates=module[i].Center()+MouseCoordinates;
		DrawModuleTemplate(hdc,&module[i]);
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
}

void Data::Draw(HDC hdc)
{
	DrawModule(hdc);
	DrawGate(hdc);
	DrawConductor(hdc);
	DrawInputLabel(hdc);
	DrawInputState(hdc);
	DrawOutputLabel(hdc);
	DrawOutputState(hdc);
	DrawNode(hdc);
	DrawNote(hdc);
}


//指定された範囲を描画
void DrawRange(HDC hdc,vector2D v1,vector2D v2)
{
	HPEN hPen,hOldPen;
	POINT p1,p2;
	hPen=CreatePen(PS_SOLID,1,RGB(255,255,0));
	hOldPen=(HPEN)SelectObject(hdc,hPen);	//正しい処理か確認

	p1=v1.toPOINT();
	p2=v2.toPOINT();

	MoveToEx(hdc,p1.x,p1.y,NULL);
	LineTo(hdc,p2.x,p1.y);
	LineTo(hdc,p2.x,p2.y);
	LineTo(hdc,p1.x,p2.y);
	LineTo(hdc,p1.x,p1.y);

	SelectObject(hdc,hOldPen);	//正しい処理か確認
	DeleteObject(hPen);
}

//描画
void Proc_Paint(State state)
{
	PAINTSTRUCT ps;
	HDC hdc,hDrawDC;
	HBITMAP hDrawBmp;

	hdc=BeginPaint(hMainWindow,&ps);
	Offset=CalculateOffset();
	hDrawDC=CreateCompatibleDC(hdc);
	hDrawBmp=CreateCompatibleBitmap(hdc,Interface::ClientRect.right,Interface::ClientRect.bottom);
	SelectObject(hDrawDC,hDrawBmp);
	SetDCBrushColor(hDrawDC,RGB(255,255,255));
	Rectangle(hDrawDC,Interface::ClientRect.left,Interface::ClientRect.top,Interface::ClientRect.right,Interface::ClientRect.bottom);
	DrawGrid(hDrawDC);
	main_data.Draw(hDrawDC);
	if(state==range && Interface::Mouse_Drag) DrawRange(hDrawDC,Interface::FirstAlignedMouseCoordinates,Interface::AlignedMouseCoordinates);
	if(state==range_selected) DrawRange(hDrawDC,Edit::coordinates1,Edit::coordinates2);
	if(state==placegate) DrawTemplate(hDrawDC);
	if(state==placemodule) DrawModuleTemplate(hDrawDC,&Place::NewModule);
	if(state==placewire && Interface::Mouse_Drag) DrawConductorTemplate(hDrawDC);
	if(state==placein) DrawInputTemplate(hDrawDC);
	if(state==placeout) DrawOutputTemplate(hDrawDC);
	if(state==note) DrawNoteTemplate(hDrawDC);
	if(state==paste) copy_data.DrawPasteTemplate(hDrawDC);
	BitBlt(hdc, 0, 0,Interface::ClientRect.right,Interface::ClientRect.bottom,hDrawDC, 0, 0, SRCCOPY );
	DeleteObject(hDrawBmp);
	DeleteDC(hDrawDC);
	EndPaint(hMainWindow,&ps);
}