#include "RuntimeData.h"
#include "LinkageProgram.h"
#include "InterLink.h"
#include "DevMask.h"
#include "Runtime.h"


extern "C"{
	#include "user_norflash.h"
	#include "user_eeprom.h"
	#include "uart_key_drv.h"
	#include "HW_config.h"
}

#define dWdClr		clSkyBlue
#define dWdDisabelClr	clNearWhite

#define dWWidth	24
#define dWHeigh	24
#define dRoundR	7

#define dAddrSdRam_LinkageInput		(dAddrSdRam_Commom + 0xF0000)

static const int GridX [5] = {4, 202, 400, 598, 796};
static const int GridTop 	[12] = {143, 173, 202, 231, 260, 	294, 323, 352, 381, 410, 439, 468};
static const int GridBottom 	[12] = {172, 201, 230, 259, 288, 	322, 351, 380, 409, 438, 467, 470};

//static const unsigned int clInput = clShallowGreen;
//static const unsigned int clOutput = clShallowRed;

const char NumText[10][4] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

static const int xCount = 10;
static const int xEntry = 214;
static const int xActiveBy = 300;
static const int xMask = 450;
static const int xSave = 560;
static const int xDelete = 640;
static const int xNew = 720;
static const int xSelfActive = 560;

static const int xEntryState = xEntry;
static const int xOperatState = 450;

void TLinkageProgram::Init()
{
	IsShow = 0;
	IsPermission =0;
	PermissionCmd =0;
	EnterMethod =0;
	
	ItemsIndex =0;
	EditIndex =0;
	OnEditing =0;
	IsInputSymbol = 0;
	IsViewList = 0;
	IsNew = 0;
	
	ActX =0;
	Inx =0;
	eX =0;
	eY =0;
	eWhat = 0;
	
	ShouldBeClear = 0;
	ShouldBeLoad = 0;
	
	CurrentPath0 = 0;
	IsWhowingTip = 0;
	
}

void TLinkageProgram::RenderBackGround(void)
{
	RectFillRender(ContentGeometry.Left, ContentGeometry.Top, ContentGeometry.Right, ContentGeometry.Bottom, ContentColor);
}

void TLinkageProgram::RenderBackGround(unsigned int aClr)
{
	RectFillRender(ContentGeometry.Left, ContentGeometry.Top, ContentGeometry.Right, ContentGeometry.Bottom, aClr);
}

void TLinkageProgram::RenderContent(void)
{
	#define FixColColor	clMedGray
	#define OddColor		clNearMoneyGreen
	unsigned int x,y, y2, clr;
}

void TLinkageProgram::DrawFixText()
{
	if(LanguageEnCn==0){
		if(EnterMethod){
			TextRender_string24(Lv.Caption.Left + 10, Lv.Caption.Top +4, clNearWhite, CaptionColor, "联动->编程查询->编程输入  ");
		}else{
			TextRender_string24(Lv.Caption.Left + 10, Lv.Caption.Top +4, clNearWhite, CaptionColor, "联动->编程输入  ");
		}	
		TextRender_string24(Lv.Grid.Left[0] + 60, Lv.Grid.Top[0] +6, clNearWhite, "/");
		TextRender_string24(Lv.Grid.Left[0] + 150, Lv.Grid.Top[0] +6, clNearWhite, "序号:");
		TextRender_string24(Lv.Grid.Left[0] + xActiveBy, Lv.Grid.Top[0] +6, clNearWhite, "执行:");
		TextRender_string24(Lv.Grid.Left[0] + xMask + 28, Lv.Grid.Top[0] +6, clNearWhite, "屏蔽");
		TextRender_string24(Lv.Grid.Left[0] + xSelfActive + 28, Lv.Grid.Top[0] +6, clNearWhite, "强制自动执行");
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xSave, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "保存", 8, ItemColor);
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xDelete, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "删除", 8, ItemColor);
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xNew, 		Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "新建", 8, ItemColor);
	}else{
		if(EnterMethod){
			TextRender_string24(Lv.Caption.Left + 10, Lv.Caption.Top +4, clNearWhite, CaptionColor, "Linkage->Overview->Expression Edit");
		}else{
			TextRender_string24(Lv.Caption.Left + 10, Lv.Caption.Top +4, clNearWhite, CaptionColor, "Linkage->Expression Edit");
		}	
		TextRender_string24(Lv.Grid.Left[0] + 60, Lv.Grid.Top[0] +6, clNearWhite, "/");
		TextRender_string24(Lv.Grid.Left[0] + 150, Lv.Grid.Top[0] +6, clNearWhite, "Index");
		TextRender_string24(Lv.Grid.Left[0] + xActiveBy, Lv.Grid.Top[0] +6, clNearWhite, "Mode");
		TextRender_string24(Lv.Grid.Left[0] + xMask + 28, Lv.Grid.Top[0] +6, clNearWhite, "Mask");
		TextRender_string24(Lv.Grid.Left[0] + xSelfActive + 28, Lv.Grid.Top[0] +6, clNearWhite, "Force Auto Run");
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xSave, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "Save", 8, ItemColor);
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xDelete, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "Del ", 8, ItemColor);
		TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xNew, 		Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, "New ", 8, ItemColor);
	}
}

void TLinkageProgram::DrawSelf(void)
{
	RenderBackGround();
	RectFillRender(Lv.Caption.Left, Lv.Caption.Top, Lv.Caption.Right, Lv.Caption.Bottom, CaptionColor);

	for(int i=0; i<Lv.Grid.UsingCount; i++)RectFillRender(Lv.Grid.Left[i], Lv.Grid.Top[i], Lv.Grid.Right[i], Lv.Grid.Bottom[i], ItemColor);
	DrawFixText();
	EEntry.Init(Lv.Grid.Left[0] + xEntry, Lv.Grid.Top[0] +4, 60, 30, 0,0, 1, clNearWhite);
	EEntry.SetMaxLen(4);
	EEntry.SetInputMaskEn();
	EEntry.Str.FromStr("----");
	EEntry.Pst = 3;
	EEntry.IsShowCursor = 1;
	EEntry.Show();

	TextDigitRender4_24(Lv.Grid.Left[0] + 72, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, dLINKAGE_MAX_COUNT);

}

void TLinkageProgram::DrawCaption(void)
{	

}

void TLinkageProgram::DrawCaption2(void)
{

}

void TLinkageProgram::Show()
{
	IsShow = 1;
	DrawSelf();
	TrySearchStartPort();
	DrawTip();
}

void TLinkageProgram::RenderGridBack()
{
	RectFillRender(Lv.Grid.Left[2], Lv.Grid.Top[2], Lv.Grid.Right[2], Lv.Grid.Bottom[2], ItemColor);
}

void TLinkageProgram::DrawGridLine()
{
	int x, y;
	if(LanguageEnCn==0){
		TextRender_string24(GridX[0] + 10, GridTop[0] +4, clNearWhite, "输入:");
		TextRender_string24(GridX[0] + 10, GridTop[5] +4, clNearWhite, "输出:");
	}else{
		TextRender_string24(GridX[0] + 10, GridTop[0] +4, clNearWhite, "Input");
		TextRender_string24(GridX[0] + 10, GridTop[5] +4, clNearWhite, "Output");
	}
	
	VertLineRender	(GridX[0],	GridTop[0], 	 GridBottom[4] - GridTop[0] +1,	clNearBlack);
	VertLineRender	(GridX[4],	GridTop[0], 	 GridBottom[4] - GridTop[0] +1,	clNearBlack);
	for(x=1; x<4; x++){		
		VertLineRender	(GridX[x],	GridTop[1], 	 GridBottom[4] - GridTop[1] +1,	clNearBlack);	
	}
	VertLineRender	(GridX[0],	GridTop[5], 	 GridBottom[9] - GridTop[5] +1,	clNearBlack);
	VertLineRender	(GridX[4],	GridTop[5], 	 GridBottom[9] - GridTop[5] +1,	clNearBlack);
	
	for(x=1; x<4; x++){		
		VertLineRender	(GridX[x],	GridTop[6], 	 GridBottom[9] - GridTop[6] +1,	clNearBlack);	
	}
	
	for(y=0; y<10; y++){		
		HorizLineRender	(GridX[0],	GridTop[y], 	 GridX[4] - GridX[0] +1,	clNearBlack);						
	}
	HorizLineRender	(GridX[0],	GridBottom[4]+1, 	 GridX[4] - GridX[0] +1,	clNearBlack);
	HorizLineRender	(GridX[0],	GridBottom[9]+1, 	 GridX[4] - GridX[0] +1,	clNearBlack);
}

void TLinkageProgram::FullRedraw(int Prm)
{
	if(Prm == 0){
		if(IsWhowingTip){
			DrawSelf();
		}else{
			if(ActX == 0){
				
			}else
			if(ActX == 1){
				RenderGridBack();
				DrawGridLine();
				
			}else{
				CheckEWhatWhoActive();
				ShowItemEdit();
			}
		}
	}else
	if(Prm == 1){
		RectFillRender(GuiRedrawDataList[1][0], GuiRedrawDataList[1][1], GuiRedrawDataList[1][2], GuiRedrawDataList[1][3], Color);	
		if(IsWhowingTip){
			DrawTip();
		}else{
			//DrawInputList();
			//EditML.ReDraw();
			//DrawTip();
		}
		int aEntry = EditingLinkageIndex;
		int aEnterMode = EnterMethod;
		Init();
		EnterMethod = aEnterMode;
		Show();
		InitPanel();
		Skip2Entry(aEntry+1);
	}
}

void TLinkageProgram::DelayUs(unsigned int aUs)
{
	volatile unsigned int mTick;
	volatile unsigned int Tick;
	for(Tick=0; Tick<aUs; Tick++){
		for(mTick=0; mTick<160; mTick++);
		sys_error_led_task();
	}	
}

void TLinkageProgram::DelayMs(unsigned int aMs)
{
	volatile unsigned int mTick;
	volatile unsigned int Tick;
	for(Tick=0; Tick<aMs; Tick++){
		for(mTick=0; mTick<160000; mTick++);
		sys_error_led_task();
	}
}

void TLinkageProgram::WaitChipIdle(unsigned int aCnt)
{
	volatile unsigned int Sta;
	do{
		DelayMs(aCnt);
		Sta = nor_get_busy_state(dFlashLinkageExpChipX);
	}while(Sta);
}

void TLinkageProgram::PaintExp()
{

}

void TLinkageProgram::ClearSelected(void)
{
	//EditML.Selected = 0;
	char *tText;
	if(IsViewList)return;
	switch(Inx){
		case 0:
			EEntry.Selected = 0;
			EEntry.Show();
			break;
		case 1:
			if(DoStop){
				if(LanguageEnCn==0)tText="停止"; else tText="Stop";
				TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clNearWhite, tText, 6, ItemColor);
			}else{
				if(LanguageEnCn==0)tText="启动"; else tText="Avt ";
				TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clNearWhite, tText, 6, ItemColor);
			}
			break;
		case 2:
			TRoundSquare::sSelected(Lv.Grid.Left[0] +xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, ItemColor);
			break;
		case 3:
			TRoundSquare::sSelected(Lv.Grid.Left[0] +xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, ItemColor);
			break;
		case 4:
			if(LanguageEnCn==0)tText="保存"; else tText="Save";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xSave, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, tText, 6, ItemColor);
			break;
		case 5:
			if(LanguageEnCn==0)tText="删除"; else tText="Del ";			
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xDelete, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, tText, 6, ItemColor);
			break;
		case 6:
			if(LanguageEnCn==0)tText="新建"; else tText="New ";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xNew, 		Lv.Grid.Top[1] + 4, 60, 30, 3, clNearWhite, tText, 6, ItemColor);
			break;
		case 7:
			//EditML.Selected = 1;
			break;
		default:

			break;
	}		
}

void TLinkageProgram::Check4Selected(void)
{
	//EditML.Selected = 0;
	char *tText;
	if(IsViewList)return;
	switch(Inx){
		case 0:
			EEntry.Selected = 1;
			EEntry.SetPstTail();
			EEntry.Show();
			break;
		case 1:
			if(DoStop){
				if(LanguageEnCn==0)tText="停止"; else tText="Stop";
				TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clDeepBlue, tText, 6, clNearWhite);
			}else{
				if(LanguageEnCn==0)tText="启动"; else tText="Avt ";
				TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clDeepBlue, tText, 6, clNearWhite);
			}	
			break;
		case 2:
			TRoundSquare::sSelected(Lv.Grid.Left[0] +xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, clNearWhite);
			break;
		case 3:
			TRoundSquare::sSelected(Lv.Grid.Left[0] +xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, clNearWhite);
			break;
		case 4:
			if(LanguageEnCn==0)tText="保存"; else tText="Save";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xSave, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clDeepBlue, tText, 6, clNearWhite);
			break;
		case 5:	
			if(LanguageEnCn==0)tText="删除"; else tText="Del ";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xDelete, 	Lv.Grid.Top[1] + 4, 60, 30, 3, clDeepBlue, tText, 6, clNearWhite);
			break;
		case 6:
			if(LanguageEnCn==0)tText="新建"; else tText="New ";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xNew, 		Lv.Grid.Top[1] + 4, 60, 30, 3, clDeepBlue, tText, 6, clNearWhite);
			break;
		case 7:
			//EditML.Selected = 1;
			break;
		default:

			break;
	}		
}

void TLinkageProgram::ClearPanelSelected()
{
	ClearSelected();
}

void TLinkageProgram::InitPanel(void)
{
	int x,y,x2,y2, aW,aH,i, yt;
	yt = y+3;
	
	InterLink.LoadExpression2Ram();
	InterLink.ReScanExpViaRam();
	LoadExpCountFromRam();
	
	TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
	
	if(ExpCount == 0){
		EntryState = 2;
		EEntry.Str.FromStr("0001");
		EditingLinkageIndex = 0;
		ShouldBeClear =1;
	}else{
		EditingLinkageIndex = 0;
		for(i=0; i<dLINKAGE_MAX_COUNT; i++){
			if(ExistTabel[i]){
				EditingLinkageIndex = i;
				break;
			}
		}
		EntryState = 1;
		EEntry.Str.FromUInt4Dg(EditingLinkageIndex +1);
		EEntry.Show();
		ShouldBeLoad = 1;
		GetLnkMask(EditingLinkageIndex);
		GetLnkDoStop(EditingLinkageIndex);
		GetLnkSelfActive(EditingLinkageIndex);
		DrawIsMask();
		DrawActiveByStartStop();
		DrawIsSelfActive();
		ShowAllGrid();
	}
	
	Check4Selected();
	DrawGridLine();
	ShowEntryState();
}

void TLinkageProgram::DrawActiveByStartStop()
{
	char *tText;
	if(Inx == 1){
		if(DoStop){
			if(LanguageEnCn==0)tText="停止"; else tText="Stop";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clDeepBlue, tText, 6, clNearWhite);
		}else{
			if(LanguageEnCn==0)tText="启动"; else tText="Act ";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clDeepBlue, tText, 6, clNearWhite);
		}	
	}else{
		if(DoStop){
			if(LanguageEnCn==0)tText="停止"; else tText="Stop";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clNearWhite, tText, 6, ItemColor);
		}else{
			if(LanguageEnCn==0)tText="启动"; else tText="Act ";
			TRoundRect::sDrawBySize(Lv.Grid.Left[0] +xActiveBy + 60, Lv.Grid.Top[0] + 4, 56, 28, 3, clNearWhite, tText, 6, ItemColor);
		}
	}
}

void TLinkageProgram::DrawIsMask()
{
	if(Inx ==2){
		TRoundSquare::sSelected(Lv.Grid.Left[0] +xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, clNearWhite);
	}else{
		TRoundSquare::sSelected(Lv.Grid.Left[0] +xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, ItemColor);
	}
	if(IsMask){
		TRoundSquare::sDrawBySize(Lv.Grid.Left[0] + xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, dRoundR, dWdClr , 1);
	}else{
		TRoundSquare::sDrawBySize(Lv.Grid.Left[0] + xMask, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, dRoundR, dWdDisabelClr , 0);
	}
}

void TLinkageProgram::DrawIsSelfActive()
{
	if(Inx ==3){
		TRoundSquare::sSelected(Lv.Grid.Left[0] +xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, clNearWhite);
	}else{
		TRoundSquare::sSelected(Lv.Grid.Left[0] +xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, 4, ItemColor);
	}
	if(IsSelfActive){
		TRoundSquare::sDrawBySize(Lv.Grid.Left[0] + xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, dRoundR, dWdClr , 1);
	}else{
		TRoundSquare::sDrawBySize(Lv.Grid.Left[0] + xSelfActive, Lv.Grid.Top[0] + 6, dWWidth, dWHeigh, dRoundR, dWdDisabelClr , 0);
	}
}

void TLinkageProgram::DrawInputTip()
{
	short x,y, i;
	x = 10 + 4;
	y = 36 + 290 +18;
	RectFillRender(x, y, x+562, y+26, Color);
	if(IsInputSymbol){
		PathText[0] = 0;
		PathText[1] = 0;
		PathText[2] = 0;
		PathText[3] = 0;
		for(i=0; i<10; i++){
			PathText[0] = i + '0';
			PathText[1] = '.';
			TextRender_string24(x, y,	clNearBlack, PathText);
			x += 56;
		}
		x = 10+24 +4;
		PathText[0] = 0;
		PathText[1] = 0;
		PathText[2] = 0;
		PathText[3] = 0;
		for(i=0; i<10; i++){
			PathText[0] = CharLinkage[i];
			TextRender_string24(x, y, clBlue, PathText);
			x += 56;
		}
		PathText[0] = 0;
		PathText[1] = 0;
		PathText[2] = 0;
		PathText[3] = 0;
	}else{
		TMyString::sFromStr("当前输入数字, 按中/英键切换到符号输入", PathText);
		TextRender_string24(x, y, clNearBlack, PathText);
	}
}

void TLinkageProgram::DrawTip()
{
	short x,y, i;
	
	if(IsProgram == 0){
		Inx = 0;
		RenderGridBack();
		InitPanel();
		IsWhowingTip = 0;
		if(ShouldBeClear){
			LoadExpVoid();
			DrawIsMask();
			DrawActiveByStartStop();
			DrawIsSelfActive();
			ShowAllGrid();
		}				
		if(ShouldBeLoad){
			LoadExp(EditingLinkageIndex);
			ShowAllGrid();
		}
		return;
	}		
	
	x = 150;
	y = 150;
		RectFillRender(x, y, x+562, y+92, Color);
		TextRender_string24(x, y ,clNearBlack, 		"1.TAB键在控制面板与编辑区切换");
		TextRender_string24(x, y + 30, clNearBlack, 	"2.控制面板选中时,左右键切换编辑内容及按钮");
		TextRender_string24(x, y + 60, clNearBlack, 	"3.控制面板选中条目编号时");
		TextRender_string24(x, y + 90, clNearBlack, 	"  设置键查询键切换到临近有效条目");
		TextRender_string24(x, y +120 ,clNearBlack, 	"4.编辑区选中时,确认键开始设置");
		TextRender_string24(x, y +150,clNearBlack, 	"5.编辑区选中时,上下左右键选定设置项");
		TextRender_string24(x, y +200,clNearBlack, 	"      按确认键继续   ");
}

unsigned char TLinkageProgram::LoadInputList(unsigned char Path0)
{
	int y;
	unsigned int aAddr;
	unsigned char aType;
	unsigned char P0;
	InputCount = 0;

	P0 = Path0-1;
	for(y=0 ;y<256; y++){
		if(Port[P0].ExistTable[y]){
			aType = Port[P0].dTypeTable[y];
			aAddr = dAddrSdRam_LinkageInput + (InputCount * 4) ;
			*(volatile unsigned char *)(aAddr + 0) = 0;
			*(volatile unsigned char *)(aAddr + 1) = P0 +1;
			*(volatile unsigned char *)(aAddr + 2) = y +1;
			*(volatile unsigned char *)(aAddr + 3) = aType;
			InputCount ++;
		}
	}

	InputPageCount = InputCount / 10;
	if(InputCount % 10){
		InputPageCount++;
	}
	
	InputPageIndex = 0;
	
	CurrentPath0 = Path0;
	
	return InputCount;
}

void TLinkageProgram::DrawInputListXX()
{
	int i, x, y;
	unsigned char aP0, aP1, aType;
	unsigned int aClr, aAddr,  wc;
	if(IsViewList){
		aClr = clBlue;
	}else{
		aClr = clDeepGray;
	}
	
	//RectFillRender(Content.Left+6 +1, Content.Top+6+1, Content.Left+6 +1 + 206, Content.Top+6+1 +34, aClr);
	//TextRender_string24(Content.Left+12, 	Content.Top + 12 ,	clNearWhite, "设备列表 回路:");
	//TextDigitRender2_24(Content.Left+180, 	Content.Top + 12 ,	clNearWhite, CurrentPath0);
	//VertLineRender	(Content.Left+6,		Content.Top + 6, 	Content.Height - 10,	clGray);
	//VertLineRender	(Content.Left+203,	Content.Top + 6, 	Content.Height - 10,	clGray);
	//HorizLineRender(Content.Left+6,		Content.Top + 6,		208,			clGray);
	//HorizLineRender(Content.Left+6,		Content.Top + 42,		208,			clGray);
	//HorizLineRender(Content.Left+6,		Content.Top + 360,	208,			clGray);
	
	
	RectFillRender(3,70,7,434,aClr);
	RectFillRender(3,70,222,74,aClr);
	RectFillRender(3,430,222,434,aClr);
	RectFillRender(218,70,222,434,aClr);
	
	RectFillRender(8,116,205,429,clMoneyGreen);
	
	i = InputPageIndex * 10;
	wc =0;
	for(; i<InputCount; i++){
		x = 10;
		y = wc * 32 + 116;
		aAddr = dAddrSdRam_LinkageInput + (i * 4);
		//aP0 = *(volatile unsigned char *)(aAddr +1);
		aP1 = *(volatile unsigned char *)(aAddr +2);
		aType =  *(volatile unsigned char *)(aAddr +3);
		//TMyString::sFrom2Dg(aP0, PathText);
		//TextRender_string24	(x,	y,clBlack, PathText);
		//TextRender_string24	(x+24,y,clBlack,"-");
		TMyString::sFrom3Dg	(aP1, PathText);
		TextRender_string24	(x+0,y,clBlack, PathText);
		TextRender_string24	(x+36,y,clBlack,"-");
		TMyString::sFromStr 	(StrTypeShortName[aType], PathText);
		TMyString::sBrokeFixLen	(PathText, 12);
		TextRender_string24	(x+48,y,clBlack,PathText);

		wc++;
		if(wc >= 10)break;
	}
	i = InputPageIndex * 10;
	TVScrollBar::sDrawByPoint(206, 116, 215, 428, aClr, clGray, InputCount, 10, i);
}


int TLinkageProgram::SearchPort(unsigned char aP0)
{
	int y;
	unsigned int aAddr;
	unsigned char aType;
	unsigned char P0;
	unsigned char iCount = 0;

	P0 = aP0-1;
	if(MainCtl.fData.Split.PortCount == 0){
		return iCount;
	}
	if(MainCtl.fData.Split.ExistTablePort[P0] == 0xA5){
		for(y=0 ;y<256; y++){
			if(Port[P0].ExistTable[y]){
				aType = Port[P0].dTypeTable[y];
				aAddr = dAddrSdRam_LinkageInput + (iCount * 4) ;
				*(volatile unsigned char *)(aAddr + 0) = 0;
				*(volatile unsigned char *)(aAddr + 1) = P0 +1;
				*(volatile unsigned char *)(aAddr + 2) = y +1;
				*(volatile unsigned char *)(aAddr + 3) = aType;
				iCount ++;
			}
		}
		return iCount;
	}
	return iCount;	
}

int TLinkageProgram::TrySearchStartPort()
{
	int i;
	for(i=1; i<(dPORT_MAX_COUNT+1); i++){
		if(SearchPort(i)){
			LoadInputList(i);
			CurrentPath0 = i;
			return i;
		}
	}
	return 0;
}

int TLinkageProgram::TrySearchPrePort()
{
	unsigned char P0;
	int i;
	P0 = CurrentPath0-1;
	for(i=0; i<dPORT_MAX_COUNT; i++){
		if(P0 == 0){
			P0 = dPORT_MAX_COUNT-1;
		}else
		if(P0 >= dPORT_MAX_COUNT){
			P0 = dPORT_MAX_COUNT-1;;
		}else{
			P0--;
		}
		if(MainCtl.fData.Split.ExistTablePort[P0] == 0xA5){
			return P0+1;
		}
	}
	return 0;
}

int TLinkageProgram::TrySearchNextPort()
{
	unsigned char P0;
	int i;
	P0 = CurrentPath0-1;
	for(i=0; i<dPORT_MAX_COUNT; i++){
		if(P0 >= dPORT_MAX_COUNT){
			P0 = 0;
		}else{
			P0++;
		}
		if(MainCtl.fData.Split.ExistTablePort[P0] == 0xA5){
			return P0+1;
		}
	}
	return 0;	
}

void TLinkageProgram::TryDecValue(int IsForce)
{
	int aVal,i;
	unsigned int index;
	unsigned int Found;
	Found = 0;
	ShouldBeClear  = 0;
	ShouldBeLoad  = 0;
	if( (Inx == 0) || (IsForce) ){
		if(ExpCount){
			aVal = EEntry.Str.ToInteger();
			if(  (aVal > dLINKAGE_MAX_COUNT) || (aVal < 1)  ){
				aVal = 1;
			}
			index = aVal;
			for(i=0; i<dLINKAGE_MAX_COUNT; i++){
				index--;
				if(index == 0)index=dLINKAGE_MAX_COUNT;
				if(ExistTabel[index -1]){
					//RestoreFromEdit(EditingLinkageIndex);
					EditingLinkageIndex = index -1;
					EEntry.Str.FromUInt4Dg(EditingLinkageIndex +1);
					EEntry.SetPstTail();
					EEntry.Show();
					//EditML.Enable = 1;
					//SetEditStart(EditingLinkageIndex);
					EntryState = 1;
					Found = 1;
					ShouldBeLoad  = 1;
					break;
				}
			}
		}
		if(Found == 0){
			ExpCount = 0;
			EditingLinkageIndex = 0;
			EntryState = 2;
			TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
			EEntry.Str.FromStr("0001");
			EEntry.SetPstTail();
			EEntry.Show();
			ShouldBeClear  = 1;
		}
	}
	ShowEntryState();
}

void TLinkageProgram::TryIncValue(int IsForce)
{
	int aVal,i;
	unsigned int index;
	unsigned int Found;
	Found = 0;
	ShouldBeClear = 0;
	ShouldBeLoad = 0;
	if( (Inx == 0) || (IsForce) ){
		if(ExpCount){
			aVal = EEntry.Str.ToInteger();
			if(  (aVal > dLINKAGE_MAX_COUNT) || (aVal < 1)  ){
				aVal = 1;
			}
			index = aVal;
			for(i=0; i<dLINKAGE_MAX_COUNT; i++){
				index++;
				if(index > dLINKAGE_MAX_COUNT)index=1;
				if(ExistTabel[index -1]){
					//RestoreFromEdit(EditingLinkageIndex);
					EditingLinkageIndex = index -1;
					EEntry.Str.FromUInt4Dg(EditingLinkageIndex +1);
					EEntry.SetPstTail();
					EEntry.Show();
					//EditML.Enable = 1;
					//SetEditStart(EditingLinkageIndex);
					EntryState = 1;
					Found = 1;
					ShouldBeLoad = 1;
					break;
				}
			}
		}
		if(Found == 0){
			ExpCount = 0;
			EntryState = 2;
			EditingLinkageIndex = 0;
			TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
			EEntry.Str.FromStr("0001");
			EEntry.SetPstTail();
			EEntry.Show();
			ShouldBeClear = 1;
			//EditML.Enable = 0;
			//EditML.Str.Clear();
			//EditML.Show();
		}
	}
	ShowEntryState();
}

void TLinkageProgram::FindNextExp()
{
	int aVal,i;
	unsigned int index;
	unsigned int Found;
	Found = 0;
	ShouldBeClear = 0;
	ShouldBeLoad  = 0;
	if(ExpCount){
		aVal = EEntry.Str.ToInteger();
		if(  (aVal > dLINKAGE_MAX_COUNT) || (aVal < 1)  ){
			aVal = 1;
		}
		index = aVal;
		for(i=0; i<dLINKAGE_MAX_COUNT; i++){
			index++;
			if(index > dLINKAGE_MAX_COUNT)index=1;
			if(ExistTabel[index -1]){
				//RestoreFromEdit(EditingLinkageIndex);
				EditingLinkageIndex = index -1;
				EEntry.Str.FromUInt4Dg(EditingLinkageIndex +1);
				EEntry.SetPstTail();
				EEntry.Show();
				EntryState = 1;
				Found = 1;
				ShouldBeLoad  = 1;
				break;
			}
		}
	}
	if(Found == 0){
		ExpCount = 0;
		EntryState = 2;
		EditingLinkageIndex = 0;
		TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
		EEntry.Str.FromStr("----");
		EEntry.SetPstTail();
		EEntry.Show();
		ShouldBeClear = 1;
	}	
}

void TLinkageProgram::LoadExpCountFromRam()
{
	unsigned int i,x;
	char Cz;
	unsigned int SysLinkAddr;
	TDMix Idf;
	ExpCount = 0;
	for(i=0; i<dLINKAGE_MAX_COUNT; i++){
		SysLinkAddr = dSdAddrLinkageExp + (i*1024);
		Idf.D32 = *(volatile unsigned int *)(SysLinkAddr);
		if(  (Idf.D8[0] == 'T') && (Idf.D8[1] == 'R') && (Idf.D8[2] == 'U') && (Idf.D8[3] == 'E') ){
			ExistTabel[i] = 1;
			ExpCount++;
		}else{
			ExistTabel[i] = 0;
		}
	}	
}

void TLinkageProgram::LoadExpression2Ram(unsigned int aInx)
{
	unsigned int x;
	unsigned int fAddr4Index;
	unsigned int SysLinkAddr;
	volatile unsigned int Sta;
	unsigned int IsAva, i;
	
	IsAva = 1;
	
	fAddr4Index = dFlashAddrLinkageExp + (aInx * 1024);
	//sAddr = dAddrSdRam_Commom + (aInx * 1024);
	SysLinkAddr = dSdAddrLinkageExp + (aInx * 1024);
	do{
		DelayUs(2);
		Sta = nor_get_busy_state(dFlashLinkageExpChipX);
	}while(Sta);
	nor_read_page(dFlashLinkageExpChipX, fAddr4Index, ReadWriteData.D8);
	if(  (ReadWriteData.D8[0] == 'T') && (ReadWriteData.D8[1] == 'R') && (ReadWriteData.D8[2] == 'U') && (ReadWriteData.D8[3] == 'E' )  ){
		for(x=0; x<64; x++){
			//*(volatile unsigned int *)(sAddr 		+ x * 4) = ReadWriteData.D32[x];
			*(volatile unsigned int *)(SysLinkAddr 	+ x * 4) = ReadWriteData.D32[x];
		}		
	}else{
		ReadWriteData.D8[0] = '\0';ReadWriteData.D8[1] = '\0';
		//*(volatile unsigned int *)(sAddr) = 0;
		*(volatile unsigned int *)(SysLinkAddr) = 0;
		IsAva = 0;
	}
	
	if(IsAva){
		for(i=0; i<3; i++){
			fAddr4Index += 256;
			SysLinkAddr += 256;
			do{
				DelayUs(2);
				Sta = nor_get_busy_state(dFlashLinkageExpChipX);
			}while(Sta);
			nor_read_page(dFlashLinkageExpChipX, fAddr4Index, ReadWriteData.D8);
			for(x=0; x<64; x++){
				*(volatile unsigned int *)(SysLinkAddr 	+ x * 4) = ReadWriteData.D32[x];
			}
		}
	}
}

void TLinkageProgram::LoadExpression2RamFor4K(unsigned int aInx)
{
	unsigned int mInx,i;
	mInx = aInx & 0xFFFF'FFFC;
	for(i=0; i<4; i++){
		LoadExpression2Ram(mInx + i);
	}
}

void TLinkageProgram::LoadExpression2Ram()
{
	unsigned int z;
	for(z=0; z<dLINKAGE_MAX_COUNT; z++){
		LoadExpression2Ram(z);
	}
}

//____________________________________________________________________________________________________________________
void TLinkageProgram::Erase4Index(unsigned int aInx)
{
	unsigned int fAddr4K;
	fAddr4K = dFlashAddrLinkageExp + ((aInx * 1024) & 0x00FF'F000);
	WaitChipIdle(5);
	nor_erase_sector_4k(dFlashLinkageExpChipX,fAddr4K);
	WaitChipIdle(400);
}

void TLinkageProgram::Write4Index(unsigned int aInx)
{
	unsigned int fAddr4K;
	unsigned int fAddr4Index;
	unsigned int sAddr4K;
	unsigned int SysLinkAddr;
	int i,x, ord;
	TDMix tCrc;
	unsigned int ToWriteInx = (aInx & 0x07FC);
	fAddr4K = dFlashAddrLinkageExp + ((aInx * 1024) & 0x00FF'F000);
	sAddr4K = dSdAddrLinkageExp + ((aInx * 1024) & 0x00FFF000);
	for(i=0; i<4; i++){
		Crc32Reset();
		fAddr4Index = fAddr4K + (i * 1024);
		SysLinkAddr = sAddr4K + (i * 1024);
		for(ord=0; ord<4; ord++){
			for(x=0; x<64; x++){
				ReadWriteData.D32[x] = *(volatile unsigned int *)(SysLinkAddr + (x * 4) );
				if(ord<3 or x<63)Crc32Feed(ReadWriteData.D32[x]);
			}
			if(ord==3)ReadWriteData.D32[63]=Crc32GetResult();
			WaitChipIdle(5);
			nor_write_page(dFlashLinkageExpChipX, fAddr4Index, ReadWriteData.D8);
			fAddr4Index+=256;
			SysLinkAddr+=256;
		}
		WaitChipIdle(5);
		InterLink.CheckStorageCrc(ToWriteInx+1);
		WaitChipIdle(5);
		ToWriteInx++;
	}
}

void TLinkageProgram::EntryClear()
{
	if( (eY<8) && (eX<4) ){
		for(int i=0; i<12; i++){
			tEntry[eY][eX][i] = '\0';
		}
		ShowOneGrid(eX,eY);
		DrawSelectedGrid(eX,eY,eX,eY);
	}
}
//___________________________________________________________________________________________________________________
void TLinkageProgram::SetEditStart()
{
	unsigned int i,x,y;
	
	for(i=0; i<8; i++){
		EuCode.Str.Text[i] = tEntry[eY][eX][i];
	}
	for(i=0; i<8; i++){
		if( ((EuCode.Str.Text[i] >= '0') && (EuCode.Str.Text[i] <= '9') )  || (EuCode.Str.Text[i] == '*') || (EuCode.Str.Text[i] == '#') ) {
			
		}else{
			EuCode.Str.Text[i] = '\0';
			EuCode.Str.Text[i+1] = '\0';
			break;
		}
	}
	EuCode.Str.Text[8] = '\0';
	EuCode.Str.Text[9] = '\0';
	for(i=0; i<3; i++){
		EdType.Str.Text[i] = tEntry[eY][eX][i + 8];
	}
	for(i=0; i<3; i++){
		if( (EdType.Str.Text[i] != '*') && ((EdType.Str.Text[i] < '0') || (EdType.Str.Text[i] > '9')) ){
			EdType.Str.Text[i] = '\0';
			EdType.Str.Text[i +1] = '\0';
		}
	}
	EdType.Str.Text[3] = '\0';
	EdType.Str.Text[4] = '\0';
	
	if(eY < 4){
		IsInput = 1;
		
		if(  (tEntry[eY][eX][11] >= '1') && (tEntry[eY][eX][11] <= '9') ){
			EInnerCount.Str.Text[0] = tEntry[eY][eX][11];
			EInnerCount.Str.Text[1] = '\0';
		}else{
			EInnerCount.Str.Text[0] = '\0';
			EInnerCount.Str.Text[1] = '\0';
		}
		EInnerCount.SetPstTail();
		if(tEntry[eY][eX][12] == 'X'){
			tLogic = 'X';
			ELogic.Str.FromStr("与");
		}else
		if(tEntry[eY][eX][12] == '+'){
			tLogic = '+';
			ELogic.Str.FromStr("或");
		}else{
			tLogic = ' ';
			ELogic.Str.FromStr("xx");
		}
		if(  (tEntry[eY][eX][13] >= '1') && (tEntry[eY][eX][13] <= '9') ){
			EInCount.Str.Text[0] = tEntry[eY][eX][13];
			EInCount.Str.Text[1] = '\0';
		}else{
			EInCount.Str.Text[0] = '\0';
			EInCount.Str.Text[1] = '\0';
		}
		EInCount.SetPstTail();
	}else
	if(eY < 8){
		IsInput = 0;
		EDelay.Str.Text[0] = tEntry[eY][eX][11];
		EDelay.Str.Text[1] = tEntry[eY][eX][12];
		EDelay.Str.Text[2] = tEntry[eY][eX][13];
		for(i=0; i<3; i++){
			if( (EDelay.Str.Text[i] < '0') || (EDelay.Str.Text[i] > '9') ){
				EDelay.Str.Text[i] = '\0';
				EDelay.Str.Text[i +1] = '\0';
			}
		}
		EDelay.Str.Text[3] = '\0';
		EDelay.Str.Text[4] = '\0';
	}
}

int TLinkageProgram::TryRestoreFromEdit()
{
	//EntryChar
	unsigned int i;
	for(i=0; i<8; i++){
		if( ( (EuCode.Str.Text[i] < '0') || (EuCode.Str.Text[i] > '9') ) && (EuCode.Str.Text[i] != '*') ){
			return 1;
		}
	}
	if (EuCode.Str.Text[8] != 0){
		return 1;
	}
	
	if(IsInput){
		for(i=0; i<3; i++){
			if( (EdType.Str.Text[i] < '0') || (EdType.Str.Text[i] > '9') ){
				return 1;
			}
		}
	}
	if (EdType.Str.Text[3] != 0){
		return 1;
	}
	if(IsInput){
		
	}else{
		if(EuCode.Str.Text[0] != '*'){
			i = TMyString::sToInteger(EdType.Str.Text);
			if( (i <0) || ( i > 254) ){
				return 1;
			}
		}
	}
	
	if(IsInput){
		if( (EInnerCount.Str.Text[0] < '1')  ||  (EInnerCount.Str.Text[0] >  '9') || (EInnerCount.Str.Text[1] != 0 )){
			return 1;
		}
		if( (tLogic != 'X') && (tLogic != '+') ){
			return 1;
		}
		if(tLogic == 'X'){
			if( (EInCount.Str.Text[0] < '1')  ||    (EInCount.Str.Text[0] >  '9') ){
				return 1;
			}
		}
	}else{
		if(EDelay.Str.Text[0] != 0){
			if( (EDelay.Str.Text[0] < '0')  ||  (EDelay.Str.Text[0] >  '9') ){
				return 1;
			}
			if(EDelay.Str.Text[1] != 0){
				if( (EDelay.Str.Text[1] < '0')  ||  (EDelay.Str.Text[1] >  '9') ){
					return 1;
				}
				if(EDelay.Str.Text[2] != 0){
					if( (EDelay.Str.Text[2] < '0')  ||  (EDelay.Str.Text[2] >  '9') ){
						return 1;
					}
				}
			}
			i = TMyString::sToInteger(EDelay.Str.Text);
			if( (i < 0) || ( i > 600 ) ){
				return 1;
			}
		}
		
	}
	return 0;
}

void TLinkageProgram::RestoreFromEdit()
{
	unsigned int i,x,y, NotUse, NewParCnt;
	ParCntHasChanged = 0;
	for(i=0; i<18; i++)tEntry[eY][eX][i] = '\0';
	for(i=0; i<8; i++){
		tEntry[eY][eX][i] = EuCode.Str.Text[i]; 
	}
	TMyString::sFillFixLen(tEntry[eY][eX], 8);
	for(i=0; i<3; i++){
		tEntry[eY][eX][i + 8] = EdType.Str.Text[i];
	}
	TMyString::sFillFixLen(tEntry[eY][eX], 11);
	if(eY<4){
		if( (EInnerCount.Str.Text[0] >= '1')  &&    ((EInnerCount.Str.Text[0] <=  '9')) ){
			tEntry[eY][eX][11] = EInnerCount.Str.Text[0];
		}else{
			tEntry[eY][eX][11] = ' ';
		}
		
		if(tLogic == 'X'){
			tEntry[eY][eX][12] = 'X';
		}else
		if(tLogic == '+'){
			tEntry[eY][eX][12] = '+';
		}else{
			tEntry[eY][eX][12] = ' ';
		}
		
		if(tLogic == 'X'){
			if( (EInCount.Str.Text[0] >= '1')  &&    ((EInCount.Str.Text[0] <=  '9')) ){
				tEntry[eY][eX][13] = EInCount.Str.Text[0];
				NewParCnt = EInCount.Str.Text[0] -'0';
			}else{
				tEntry[eY][eX][13] = ' ';
				NewParCnt = 1;
			}
			if(NewParCnt != ParCnt){
				ParCnt = NewParCnt;
				ParCntHasChanged = 1;
			}
		}else{
			tEntry[eY][eX][13] = ' ';
		}
		
		if(  (tEntry[eY][eX][0] != '*') && (tEntry[eY][eX][0] != '#') ){
			if(  (tEntry[eY][eX][0] < '0') || (tEntry[eY][eX][0] > '9')  ){
				tEntry[eY][eX][11] = ' ';
				tEntry[eY][eX][12] = ' ';
				tEntry[eY][eX][13] = ' ';
			}
		}
		
		TMyString::sFillFixLen(tEntry[eY][eX], 14);
		tEntry[eY][eX][14] = '\0';
		tEntry[eY][eX][15] = '\0';
	}else
	if(eY<8){
		tEntry[eY][eX][11] = EDelay.Str.Text[0];
		tEntry[eY][eX][12] = EDelay.Str.Text[1];
		tEntry[eY][eX][13] = EDelay.Str.Text[2];
		TMyString::sFillFixLen(tEntry[eY][eX], 14);
		tEntry[eY][eX][14] = '\0';
		tEntry[eY][eX][15] = '\0';
	}
}

void TLinkageProgram::RedrawParCnt()
{
	unsigned int y, x;
	if(ParCntHasChanged == 0)return;
	for(y=0; y<4; y++){
		for(x=0; x<4; x++){
			if(   ( (tEntry[y][x][0] >= '0') && (tEntry[y][x][0] <= '9')  ) || (tEntry[y][x][0] == '*') || (tEntry[y][x][0] == '#')  ) {
					if(tEntry[y][x][12] == 'X'){
						if((ParCnt > 0) && (ParCnt < 10)){
							tEntry[y][x][13] = ParCnt + '0';
						}else{
							tEntry[y][x][13] = ' ';
						}
						ShowOneGrid(x,y);
					}
			}
		}
	}
}

void TLinkageProgram::ClearGridSelected()
{
	unsigned int x, y, aClr;
	int tWidth, tHeigth, InxY;
	if(eY < 4){
		aClr = ItemColor; 
		InxY = eY +1;
	}else{
		aClr = ItemColor;
		InxY = eY +2;
	}
	x = GridX[eX] + 1;
	y = GridTop[InxY] +1;
	tWidth = GridX[eX+1] -GridX[eX] -2;
	tHeigth = GridBottom[InxY] - GridTop[InxY] -1;
	
	VertLineRender	(x,	y, 	 tHeigth,	aClr);
	VertLineRender	(x+1,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -3,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -2,	y, 	 tHeigth,	aClr);
	
	HorizLineRender	(x,	GridTop[InxY]+1, 	 tWidth,	aClr);
	HorizLineRender	(x,	GridTop[InxY]+2, 	 tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-1, 	 tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-0, 	 tWidth,	aClr);	
}

void TLinkageProgram::DrawSelectedGrid(unsigned int oldX, unsigned int oldY, unsigned int NewX, unsigned int NewY)
{
	unsigned int x, y, aClr;
	int tWidth, tHeigth, InxY;
	x = GridX[oldX] + 1;
	if(oldY < 4){
		aClr = ItemColor; 
		InxY = oldY +1;
	}else{
		aClr = ItemColor;
		InxY = oldY +2;
	}
	x = GridX[oldX] + 1;
	y = GridTop[InxY] +1;
	tWidth = GridX[oldX+1] -GridX[oldX] -2;
	tHeigth = GridBottom[InxY] - GridTop[InxY] -1;
	
	VertLineRender	(x,	y, 	 tHeigth,	aClr);
	VertLineRender	(x+1,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -3,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -2,	y, 	 tHeigth,	aClr);
	
	HorizLineRender	(x,	GridTop[InxY]+1, 	 	tWidth,	aClr);
	HorizLineRender	(x,	GridTop[InxY]+2, 	 	tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-1, 	 tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-0, 	 tWidth,	aClr);
	
	x = GridX[NewX] + 1;
	if(NewY < 4){
		InxY = NewY +1;
	}else{
		InxY = NewY +2;
	}
	x = GridX[NewX] + 1;
	y = GridTop[InxY] +1;
	tWidth = GridX[NewX+1] -GridX[NewX] -2;
	tHeigth = GridBottom[InxY] - GridTop[InxY] -1;
	aClr = clBlue;
	VertLineRender	(x,	y, 	 tHeigth,	aClr);
	VertLineRender	(x+1,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -3,	y, 	 tHeigth,	aClr);
	VertLineRender	(x + tWidth -2,	y, 	 tHeigth,	aClr);
	
	HorizLineRender	(x,	GridTop[InxY]+1, 	 	tWidth,	aClr);
	HorizLineRender	(x,	GridTop[InxY]+2, 	 	tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-1, 	 tWidth,	aClr);
	HorizLineRender	(x,	GridBottom[InxY]-0, 	 tWidth,	aClr);
}

void TLinkageProgram::ShowOneGrid(unsigned int x, unsigned int y)
{
	unsigned int pX, pY, i;
	int InxY;
	if(y<4){
		InxY = y+1;
	}else{
		InxY = y+2;
	}
	pX = GridX[x] + 4;
	pY = GridTop[InxY] + 2;
	for(i=0; i<18; i++)PathText[i] = '\0';
	for(i=0; i<8; i++){
		PathText[i] = tEntry[y][x][i];
	}
	TMyString::sFillFixLen(PathText, 8);
	PathText[8] = ' ';
	for(i=0; i<3; i++){
		PathText[i+9] = tEntry[y][x][i+8];
	} 
	TMyString::sFillFixLen(PathText, 12);
	if(y<4){
		PathText[12] = ' ';
		PathText[13] = tEntry[y][x][11];
		PathText[14] = tEntry[y][x][12];
		PathText[15] = tEntry[y][x][13];
		TMyString::sFillFixLen(PathText, 16);
		PathText[16] = '\0';
		PathText[17] = '\0';
	}else
	if(y<8){
		PathText[12] = ' ';
		PathText[13] = tEntry[y][x][11];
		PathText[14] = tEntry[y][x][12];
		PathText[15] = tEntry[y][x][13];
		PathText[16] = '\0';
		PathText[17] = '\0';
	}
	
	TMyString::sFillFixLen(PathText, 16);
	PathText[16] = '\0';
	PathText[17] = '\0';
	
	TextRender_string24(pX, pY ,clNearWhite, ItemColor, PathText); 		
}

void TLinkageProgram::ShowAllGrid()
{
	unsigned int x, y;
	for(y=0; y<8; y++)for (x=0; x<4; x++)ShowOneGrid(x,y);
}

void TLinkageProgram::ShowEntryState()
{
	if( EntryState == 0){
		if(LanguageEnCn==0)TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 	"编号超限  ");
		else TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 			"Index Exceeds   ");
	}else
	if( EntryState == 1){
		if(LanguageEnCn==0)TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 	"已配置联动");
		else TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 			"Valid Expression");
	}else
	if( EntryState == 2){
		if(LanguageEnCn==0)TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 	"新联动    ");
		else TextRender_string24(xEntryState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, 			"New Expression  ");
	}
}

int TLinkageProgram::NewEntry()
{
	int i, FoundEmpty;
	FoundEmpty = 0;
	for(i=0; i<dLINKAGE_MAX_COUNT; i++){
		if(ExistTabel[i] == 0){
			EditingLinkageIndex = i;
			EEntry.Str.FromUInt4Dg( EditingLinkageIndex+1);
			EEntry.Show();
			
			LoadExpVoid();
			DrawIsMask();
			DrawActiveByStartStop();
			DrawIsSelfActive();
			ShowAllGrid();
			ShowTip(4);
			FoundEmpty =1;
			break;
		}
	}
	if(FoundEmpty == 0){
		ShowTip(-3);
		return -1;
	}else{
		return 0;
	}
}

void TLinkageProgram::ShowTip(int aTip)
{
	if(LanguageEnCn==0){
		if(aTip == 0){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "        ");
		}else
		if(aTip == -1){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "删除成功");
		}else
		if(aTip == 1){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "保存成功");
		}else
		if(aTip == -2){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "操作失败");
		}else
		if(aTip == 2){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "开始保存");
		}else
		if(aTip == 3){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "开始删除");
		}else
		if(aTip == -3){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "空间不足");
		}
	}else{
		if(aTip == 0){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "        ");
		}else
		if(aTip == -1){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "Deleted ");
		}else
		if(aTip == 1){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "Saved OK");
		}else
		if(aTip == -2){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "Failed  ");
		}else
		if(aTip == 2){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "Saving  ");
		}else
		if(aTip == 3){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "Deleting");
		}else
		if(aTip == -3){
			TextRender_string24(xOperatState, Lv.Grid.Top[1] +2, clNearWhite, ItemColor, "No Space");
		}
	}
}

void TLinkageProgram::WriteEntry()
{
	Erase4Index(EditingLinkageIndex);
	Write4Index(EditingLinkageIndex);
}

void TLinkageProgram::DeleteEntry()
{
	unsigned int sAddr, i;
	sAddr = dSdAddrLinkageExp + (EditingLinkageIndex  * 1024);
	for(i=0; i<64; i++){
		*(volatile unsigned int *)(sAddr + i *4) = 0;
	}
	Erase4Index(EditingLinkageIndex);
	WaitChipIdle(50);
	Write4Index(EditingLinkageIndex);
}

void TLinkageProgram::ReScanExpViaRam()
{
	unsigned int i,x;
	char Cz;
	unsigned int SysLinkAddr;
	TDMix Val;
	ExpCount = 0;
	for(i=0; i<dLINKAGE_MAX_COUNT; i++){
		SysLinkAddr = dSdAddrLinkageExp + (i*1024);
		Val.D32 = *(volatile unsigned int *)(SysLinkAddr);
		if(  (Val.D8[0] == 'T') && (Val.D8[1] == 'R') && (Val.D8[2] == 'U') && (Val.D8[3] == 'E') ) {
			ExistTabel[i] = 1;
			ExpCount++;
		}else{
			ExistTabel[i] = 0;
		}
	}	
}

void TLinkageProgram::IdfButtonEn()
{
	if(EntryState == 0){
		IsDeleteEn = 0;
		return;
	}else{
		IsDeleteEn = 1;
	}
	
	if(ExpCount == 0){
		IsDeleteEn = 0;
	}else{
		if(IsNew == 0){
			EEntry.Enable = 1;
		}else{
			EEntry.Enable = 0;
		}
	}
	EEntry.Show();
	
	IsSaveEn = 1;
	if(IsNew){
		IsDeleteEn = 0;

	}else{
		IsSaveEn = 0;
		IsDeleteEn = 0;

		if( (Inx == 1) || (Inx == 2) ){
			ClearSelected();
			Inx = 3;
			Check4Selected();
		}
	}
}

void TLinkageProgram::CheckUserCodeUniquely(int aIsInput)
{
	int CharNum, iVal, tP0, tP1;
	int Uniquely, Got;
	unsigned char tType;
	CharNum = EuCode.Str.GetLength();
	if(CharNum == 8){
		Uniquely = 1;
		for(iVal=0; iVal<8; iVal++){
			if( (EuCode.Str.Text[iVal] < '0') || (EuCode.Str.Text[iVal] > '9') ){
				Uniquely = 0;
				break;
			}
		}
		Got = 0;
		iVal = EuCode.Str.ToInteger();
		if(Uniquely && (iVal>0) ){
			for(tP0=0; tP0<dPORT_MAX_COUNT; tP0++){
				if( (iVal>= Port[tP0].UserCodeMin) && (iVal<= Port[tP0].UserCodeMax) ){
					for(tP1=0; tP1<250; tP1++){
						if(iVal == Port[tP0].UcList[tP1].Full){
							if(Port[tP0].AssignType[tP1] != 0){
								tType = Port[tP0].AssignType[tP1];
							}else{
								tType = Port[tP0].dTypeTable[tP1];
							}
							Got = 1;
						}
					}
				}
			}
			if( (Got == 0) && (aIsInput == 0) ){
				for(tP0=0; tP0<dDIRECTCTL_MAX_COUNT; tP0++){
					if(DirectCtlBoard[tP0].IsRegisted){
						for(tP1=0; tP1<dDIRECTCTL_KEY_MAX_COUNT; tP1++){
							if(iVal == DirectCtlBoard[tP0].UcList[tP1].Full){
								tType = DirectCtlBoard[tP0].AssignType[tP1];
								Got = 1;
							}
						}
					}
				}
			}
		}
		
		if(Got){
			EdType.Str.FromUInt3Dg(tType);
			EdType.Show();
			CheckShowDevType();
		}
	}
}

void TLinkageProgram::PermissionCmdGO()
{
	if(PermissionCmd == 0){
		//Delete
		if(EntryState == 1){
			ShowTip(3);
			DeleteEntry();
			LoadExpression2RamFor4K(EditingLinkageIndex);
			InterLink.ReScanExpViaRam();
			LoadExpCountFromRam();
			ShowTip(-1);
			TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
			FindNextExp();
			if(EntryState == 2){
				LoadExpVoid();
				DrawIsMask();
				DrawActiveByStartStop();
				DrawIsSelfActive();
				ShowAllGrid();
				if(Inx == 3){
					Inx=4;
					IsDeleteEn = 0;
				}
			}
			if(EntryState == 1){
				LoadExp(EditingLinkageIndex);
				DrawIsMask();
				DrawActiveByStartStop();
				DrawIsSelfActive();
				ShowAllGrid();
			}
		}
	}else
	if(PermissionCmd ==1){
		//Save
		if(EntryState){
			ShowTip(2);
			RestoreExp(EditingLinkageIndex);
			WriteEntry();
			LoadExpression2RamFor4K(EditingLinkageIndex);
			InterLink.ReScanExpViaRam();
			LoadExpCountFromRam();
			ShowTip(1);
			TextDigitRender4_24(Lv.Grid.Left[0] + xCount, Lv.Grid.Top[0] +6, clNearWhite, ItemColor, ExpCount);
			EntryState = 1;
			LoadExp(EditingLinkageIndex);
			DrawIsMask();
			DrawActiveByStartStop();
			DrawIsSelfActive();
			ShowAllGrid();
		}
	}
}

void TLinkageProgram::PermissionCmdReturnDraw()
{
	ActX = 0;
	RenderGridBack();
	DrawGridLine();
	ShowAllGrid();
	
	ActX = 0;
	Inx = 3;
	ClearGridSelected();
	Check4Selected();
}

void TLinkageProgram::Skip2Entry(unsigned int aEntry)
{
	ShouldBeClear = 0;
	ShouldBeLoad = 0;

	if(aEntry > dLINKAGE_MAX_COUNT)return;;
	EditingLinkageIndex = aEntry -1;
	EEntry.Str.FromUInt4Dg(aEntry);
	EEntry.SetPstTail();
	EEntry.Show();
	
	if(ExistTabel[EditingLinkageIndex]){
		EntryState = 1;
		LoadExp(EditingLinkageIndex);
		DrawIsMask();
		DrawActiveByStartStop();
		DrawIsSelfActive();
		ShowAllGrid();
	}else{
		ShouldBeClear = 1;
		EntryState = 2;
		LoadExpVoid();
		DrawIsMask();
		DrawActiveByStartStop();
		DrawIsSelfActive();
		ShowAllGrid();
	}
	ActX = 1;
	ClearPanelSelected();
	DrawSelectedGrid(eX, eY, eX, eY);
	ShowEntryState();
}

int TLinkageProgram::CheckUserCodeOk()
{
	int iVal, IncludeAst;
	if(EuCode.Str.GetLength() != 8){
		return 0;
	}
	for(int i=0;i<8;i++){
		if( ((EuCode.Str.Text[i] < '0') || (EuCode.Str.Text[i] >'9')) && (EuCode.Str.Text[i] != '*') )return 0;
	}
	IncludeAst = 0;
	for(int i=0;i<8;i++){
		if(EuCode.Str.Text[i] == '*')IncludeAst =1;
	}
	if(IncludeAst == 0){
		iVal = EuCode.Str.ToInteger();
		if(iVal == 0)return 0;
	}
	return 1;
}

int TLinkageProgram::CheckTypeOk()
{
	int iVal;
	if(EdType.Str.GetLength() != 3)return 0;
	if(IsInput){
		if( (EdType.Str.Text[0]=='*') or (EdType.Str.Text[1]=='*') or (EdType.Str.Text[2]=='*') )return 0;
		iVal = EdType.Str.ToInteger(); 
		if( iVal>0 and iVal<256){
			return 1;
		}
	}else{
		if( (EdType.Str.Text[0]=='*') and (EdType.Str.Text[1]=='*') and (EdType.Str.Text[2]=='*'))return 1;
		if((EdType.Str.Text[0]=='*') or (EdType.Str.Text[1]=='*') or (EdType.Str.Text[2]=='*'))return 0;
		iVal = EdType.Str.ToInteger(); 
		if(iVal>0 && iVal<256){
			return 1;
		}
	}
	return 0;
}

TGuiMsgReturn TLinkageProgram::KeyIn(unsigned char aKey)
{
	TGuiMsgReturn aMsg = guiMsgNone, PmsRtnMsg;
	int iVal;
	unsigned char NewPath0;
	unsigned char LoadKey;
	unsigned char tType;
	char LastChr;
	
	if(IsWhowingTip){
		if(aKey == VK_EXECUTE){
			Inx = 0;
			RenderGridBack();
			InitPanel();
			IsWhowingTip = 0;
			if(ShouldBeClear){
				LoadExpVoid();
				DrawIsMask();
				DrawActiveByStartStop();
				DrawIsSelfActive();
				ShowAllGrid();
			}				
			if(ShouldBeLoad){
				LoadExp(EditingLinkageIndex);
				ShowAllGrid();
			}
		}else
		if(aKey == VK_RETURN){
			return guiMsgReturn;
		}
	}else
	if(IsPermission){
		PmsRtnMsg = PmsIntervene4Gui.KeyIn(aKey);
		if(PmsRtnMsg == guiMsgOkAndReturn){
			//Enter And Run Go
			IsPermission = 0;
			PermissionCmdReturnDraw();
			PermissionCmdGO();
		}else
		if(PmsRtnMsg == guiMsgReturn){
			//Not Enter Redraw
			IsPermission = 0;
			PermissionCmdReturnDraw();
		}
		return aMsg;
	}else{
			if(ActX >2){
				ActX = 0;
			}
			if(ActX == 0){
				switch(aKey){
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
					case VK_LEFT:
					case VK_RIGHT:
					case VK_DELETE:
						if(Inx == 0){
							if(aKey == VK_RIGHT){
								if( EEntry.Str.GetEndPst() <= EEntry.Pst){
									ClearSelected();
									Inx =1;
									Check4Selected();
								}
							}
							if(Inx == 0){
								EEntry.KeyIn(aKey);
								EEntry.ReDraw();
								iVal = EEntry.Str.ToInteger();
								
								if(iVal > dLINKAGE_MAX_COUNT){
									EntryState = 0;
								}else
								if(iVal <1 ){
									EntryState = 0;
								}else{
									EditingLinkageIndex = iVal -1;
									if(ExistTabel[EditingLinkageIndex]){
										ShouldBeLoad = 1;
										EntryState = 1;
										LoadExp(EditingLinkageIndex);
										DrawIsMask();
										DrawActiveByStartStop();
										DrawIsSelfActive();
										ShowAllGrid();
									}else{
										ShouldBeClear = 1;
										EntryState = 2;	
										LoadExpVoid();
										DrawIsMask();
										DrawActiveByStartStop();
										DrawIsSelfActive();
										ShowAllGrid();
									}
								}
								ShowEntryState();
							}
						}else{
							if(aKey == VK_LEFT){
								if( (Inx > 0) && (Inx<4) ){
									ClearSelected();
									Inx --;
									Check4Selected();
								}else
								if( (Inx == 5) || ( Inx == 6) ){
									ClearSelected();
									Inx --;
									Check4Selected();
								}
							}else
							if(aKey == VK_RIGHT){
								if( (Inx==1) || (Inx==2) || (Inx==4) || (Inx==5) ){
									ClearSelected();
									Inx ++;
									Check4Selected();
								}
							}
						}
						break;
					case VK_UP:
						if(Inx == 0){
							TryIncValue(0);
							if(EntryState == 2){
								LoadExpVoid();
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}
							if(EntryState == 1){
								LoadExp(EditingLinkageIndex);
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}
						}else
						if(Inx > 3){
							ClearSelected();
							Inx =3;
							Check4Selected();
						}
						break;
					case VK_DOWN:
						if(Inx==0){
							TryDecValue(0);
							if(EntryState == 2){
								LoadExpVoid();
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}else
							if(EntryState == 1){
								LoadExp(EditingLinkageIndex);
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}
						}else
						if( (Inx==4) || (Inx==5) || (Inx==6) ){
							ActX = 1;
							ClearSelected();
							DrawSelectedGrid(eX, eY, eX, eY);
						}else
						if( (Inx==1) || (Inx==2) || (Inx==3)){
							ClearSelected();
							Inx =4;
							Check4Selected();
						}
						break;
					case dfKEY_SETUP:		//0x70		//  Key value for SETUP
						if(Inx == 0){
							TryDecValue(0);
							if(EntryState == 2){
								LoadExpVoid();
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}else
							if(EntryState == 1){
								LoadExp(EditingLinkageIndex);
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}
						}else
						if(Inx == 1){
							if(DoStop){
								DoStop = 0;
							}else{
								DoStop = 1;
							}
							DrawActiveByStartStop();
						}else
						if(Inx == 2){
							if(IsMask){
								IsMask = 0;
							}else{
								IsMask = 1;
							}
							DrawIsMask();
						}else
						if(Inx == 3){
							if(IsSelfActive){
								IsSelfActive = 0;
							}else{
								IsSelfActive = 1;
							}
							DrawIsSelfActive();
						}
						break;
					case dfKEY_QUERY:		//0x71		//  Key value for QUERY
						if(Inx == 0){
							ClearSelected();
							Inx =1;
							Check4Selected();
						}
						break;
					case VK_TAB:
						ActX = 1;
						ClearSelected();
						DrawSelectedGrid(eX, eY, eX, eY);
						break;
					case VK_EXECUTE:
						if(Inx == 1){
							if(DoStop){
								DoStop = 0;
							}else{
								DoStop = 1;
							}
							DrawActiveByStartStop();
						}else
						if(Inx == 2){
							if(IsMask){
								IsMask = 0;
							}else{
								IsMask = 1;
							}
							DrawIsMask();
						}else
						if(Inx == 3){
							if(IsSelfActive){
								IsSelfActive = 0;
							}else{
								IsSelfActive = 1;
							}
							DrawIsSelfActive();
						}else
						if(Inx == 4){
							//Save
							if(EntryState){
								PermissionCmd = 1;
								if(SystemPermission > 2){
									PermissionCmdGO();
								}else{
									IsPermission = 1;
									ClearSelected();
									PmsIntervene4Gui.Show4Gui(Lv.Grid.Left[2] + 200, Lv.Grid.Top[2] + 16, 400, 140, 3);
								}
							}
						}else
						if(Inx == 5){
							//Delete
							if( EntryState ==1 ){
								PermissionCmd = 0;
								if(SystemPermission > 2){
									PermissionCmdGO();
								}else{
									IsPermission = 1;
									ClearSelected();
									PmsIntervene4Gui.Show4Gui(Lv.Grid.Left[2] + 200, Lv.Grid.Top[2] + 16, 400, 140, 3);
								}
							}else
							if(EntryState == 2){
								LoadExpVoid();
								DrawIsMask();
								DrawActiveByStartStop();
								DrawIsSelfActive();
								ShowAllGrid();
							}
						}else
						if(Inx == 6){
							//New
							if(NewEntry() == 0){
								EntryState = 2;
								ActX = 1;
								ClearPanelSelected();
								DrawSelectedGrid(eX, eY, eX, eY);
							}
						}
						break;
					case VK_RETURN:
						aMsg = guiMsgReturn;
						break;
				}	
			}else
			if(ActX == 1){
				switch(aKey){
					case VK_LEFT:
						if (eX >0){
							eX--;
							DrawSelectedGrid(eX+1, eY, eX, eY);
						}
						break;
					case VK_RIGHT:
						if (eX <3){
							eX++;
							DrawSelectedGrid(eX-1, eY, eX, eY);
						}
						break;
					case VK_UP:
						if( eY >0){
							eY--;
							DrawSelectedGrid(eX, eY+1, eX, eY);
						}else{
							ActX = 0;
							Inx = 4;
							ClearGridSelected();
							Check4Selected();
						}
						break;
					case VK_DOWN:
						if( eY <7){
							eY++;
							DrawSelectedGrid(eX, eY-1, eX, eY);
						}
						break;
					case dfKEY_SETUP:		//0x70		//  Key value for SETUP
						//Save Here
						
						break;
					case VK_TAB:
						ActX = 0;
						Inx = 4;
						ClearGridSelected();
						Check4Selected();
						break;
					case VK_DELETE:
						EntryClear();
						break;
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
					case VK_DECIMAL:
					case VK_OEM_2:
					case VK_EXECUTE:
						ActX = 2;
						eWhat = 0;
						ShowItemEdit();
						CheckEWhatWhoActive();
						RedrawEEdit();
						break;
					case VK_RETURN:
						aMsg = guiMsgReturn;
						break;
				}		
			}else
			if(ActX == 2){
				if(IsInput){
					switch(aKey){
						case dfKEY_ENCN:
							break;
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
						case VK_LEFT:
						case VK_RIGHT:
						case VK_DELETE:
						case VK_DECIMAL:
						case VK_OEM_2:
							if(eWhat == 0){
								EuCode.KeyIn(aKey);
								EuCode.Show();
								CheckUserCodeUniquely(1);
							}else
							if(eWhat == 1){
								if( (aKey != VK_DECIMAL) && (aKey != VK_OEM_2)){
									EdType.KeyIn(aKey);
									CheckShowDevType();
								}
							}else
							if(eWhat == 2){
								if(	(aKey != VK_DECIMAL) && (aKey != VK_OEM_2)  ) {
									EInnerCount.KeyIn(aKey);
									EInnerCount.Show();
								}
							}else
							if(eWhat == 3){
								if(tLogic == '+')tLogic = 'X';
								else tLogic = '+';
								if(tLogic == '+')if(LanguageEnCn==0)ELogic.Str.FromStr("或"); else ELogic.Str.FromStr("or");
								else if (tLogic == 'X')if(LanguageEnCn==0)ELogic.Str.FromStr("与"); else ELogic.Str.FromStr("And");
								else ELogic.Str.FromStr("  ");
								ELogic.Show();
							}else
							if(eWhat == 4){
								if(	(aKey != VK_DECIMAL) && (aKey != VK_OEM_2)  ) {
									EInCount.KeyIn(aKey);
									EInCount.Show();	
								}
							}
							break;
						case VK_UP:
							if(eWhat >0){
								eWhat--;
								CheckEWhatWhoActive();
								RedrawEEdit();
							}
							break;
						case VK_DOWN:
							if(eWhat <4){
								eWhat++;
								CheckEWhatWhoActive();
								RedrawEEdit();
							}
							break;
						case dfKEY_SETUP:		//0x70		//  Key value for SETUP
							
							break;
						case dfKEY_QUERY:		//0x71		//  Key value for QUERY
							break;
						case VK_EXECUTE:
							if(TryRestoreFromEdit() == 0){
								RestoreFromEdit();
								RedrawParCnt();
							}
							ActX = 1;
							RenderGridBack();
							DrawGridLine();
							ShowAllGrid();
							DrawSelectedGrid(eX, eY, eX, eY);
							break;
						case VK_RETURN:
							ActX = 1;
							RenderGridBack();
							DrawGridLine();
							ShowAllGrid();
							DrawSelectedGrid(eX, eY, eX, eY);
							break;
					}					
				}else{
					switch(aKey){
						case dfKEY_ENCN:
							break;
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
						case VK_LEFT:
						case VK_RIGHT:
						case VK_DELETE:
						case VK_DECIMAL:
						case VK_OEM_2:
							if(eWhat == 0){
								EuCode.KeyIn(aKey);
								EuCode.Show();
								CheckUserCodeUniquely(0);
							}else
							if(eWhat == 1){
								if(aKey != VK_OEM_2){
									EdType.KeyIn(aKey);
									CheckShowDevType();
								}
							}else{
								if(  (aKey != VK_DECIMAL) && (aKey != VK_OEM_2)  ){
									EDelay.KeyIn(aKey);
									EDelay.Show();
								}
							}
							break;
						case VK_UP:
							if(eWhat >0){
								eWhat--;
								CheckEWhatWhoActive();
								RedrawEEdit();
							}
							break;
						case VK_DOWN:
							if(eWhat <2){
								eWhat++;
								CheckEWhatWhoActive();
								RedrawEEdit();
							}
							break;
						case dfKEY_SETUP:		//0x70		//  Key value for SETUP
							
							break;
						case dfKEY_QUERY:		//0x71		//  Key value for QUERY
							break;
						case VK_EXECUTE:
							if(CheckUserCodeOk() && CheckTypeOk()){
								if(TryRestoreFromEdit() == 0){
									RestoreFromEdit();
								}
								ActX = 1;
								RenderGridBack();
								DrawGridLine();
								ShowAllGrid();
								DrawSelectedGrid(eX, eY, eX, eY);
							}else{
								
							}
							break;
						case VK_RETURN:
							ActX = 1;
							RenderGridBack();
							DrawGridLine();
							ShowAllGrid();
							DrawSelectedGrid(eX, eY, eX, eY);
							break;
					}
				}					
			}
	}
	return aMsg;	
}

void TLinkageProgram::CheckShowDevType()
{
	int iVal;
	if(EdType.Str.GetLength() != 3){
		EdType.SelectedColor = clRed;
		if(LanguageEnCn==0)STextDType.SetText("输入不完整",24);
		else STextDType.SetText("Dev Invalid",24);
	}else{
		if(IsInput){
			iVal = EdType.Str.ToInteger(); 
			if( (iVal > 0) && (iVal < 256)){
				EdType.SelectedColor = clBlue;
				if(LanguageEnCn==0){
					STextDType.SetText(StrTypeShortName[iVal],24);
				}else{
					STextDType.SetText(StrTypeShortNameEn[iVal],24);
				}
			}else{
				EdType.SelectedColor = clRed;
				if(LanguageEnCn==0)STextDType.SetText(	"类型超出范围",24);
				else STextDType.SetText(			"Dev Type Invalid",24);
			}			
		}else{
			if(EdType.Str.Text[0] == '*' and EdType.Str.Text[1]=='*' and EdType.Str.Text[2]=='*' and EdType.Str.Text[3]=='\0'){
					EdType.SelectedColor = clBlue;
					if(LanguageEnCn==0){
						STextDType.SetText("所有输出类型",24);
					}else{
						STextDType.SetText("All Out Type",24);
					}
			}else
			if(EdType.Str.Text[0]=='*' or EdType.Str.Text[1]=='*' or EdType.Str.Text[2]=='*'){
					EdType.SelectedColor = clRed;
					if(LanguageEnCn==0)STextDType.SetText(	"类型超出范围",24);
					else STextDType.SetText(			"Dev Type Invalid",24);
			}else{
				iVal = EdType.Str.ToInteger(); 
				if( (iVal > -1) && (iVal < 256)){
					EdType.SelectedColor = clBlue;
					if(LanguageEnCn==0){
						if(iVal == 0){
							EdType.SelectedColor = clRed;
							STextDType.SetText("无效类型",24);
						}else{
							STextDType.SetText(StrTypeShortName[iVal],24);
						}
					}else{
						if(iVal == 0){
							EdType.SelectedColor = clRed;
							STextDType.SetText("Invalid Type",24);
						}else{
							STextDType.SetText(StrTypeShortNameEn[iVal],24);
						}
					}
				}else{
					EdType.SelectedColor = clRed;
					if(LanguageEnCn==0)STextDType.SetText(	"类型超出范围",24);
					else STextDType.SetText(			"Dev Type Invalid",24);
				}
			}
		}
	}
	EdType.Show();
	STextDType.Show();
}

void TLinkageProgram::ShowItemEdit()
{

	#define FixColColor	clMedGray
	#define OddColor		clNearMoneyGreen
	unsigned int clr;
	unsigned int x, y, x2, y2, w, h;
	int iVal;
	
	if(eY <4)IsInput =1; else IsInput = 0;
	
	if(IsInput){
		x = 200;	
		x2 = 600;
		y = 150;
		y2 = 430;
		w = 400;
		h = 280;
	}else{
		x = 200;	
		x2 = 600;
		y = 150;
		y2 = 350;
		w = 400;
		h = 200;
	}
	
	VertLineRender(x,		y, 		h -1,			0xFFFFFFFF);
	VertLineRender(x2 -1,	y +1,		h -2,			0xFF808080);
	VertLineRender(x2,	y,		h,			0xFF404040);
	
	HorizLineRender(x, 		y, 		w - 1, 		0xFFFFFFFF);
	HorizLineRender(x +1, 		y2 -1,  	w- 2, 		0xFF808080);
	HorizLineRender(x,		y2,		w,			0xFF404040);
	
	RectFillRender(x+1, y+2, x2-3, y+37, clNavy);
	RectFillRender(x+1, y+38, x2-3, y2-2, clFrmFace);
	if(LanguageEnCn==0){
		if (IsInput)
			TextRender_string24(x +8, y +  6,clNearWhite, "编辑条目细节-输入");
		else 
			TextRender_string24(x +8, y +  6,clNearWhite, "编辑条目细节-输出");
		TextRender_string24(x +8, y + 48,clNearBlack, "设备编码:");
		TextRender_string24(x +8, y + 88,clNearBlack, "设备类型:");
		
		if (IsInput){
			TextRender_string24(x +8, y +168,clNearBlack, "逻辑关系:");
		}else{
			TextRender_string24(x +8, y +128,clNearBlack, "延时时间:");
		}
	}else{
		if (IsInput)
			TextRender_string24(x +8, y +  6,clNearWhite, "Edit-Input");
		else 
			TextRender_string24(x +8, y +  6,clNearWhite, "Edit-Output");
		TextRender_string24(x +8, y + 48,clNearBlack, "AuxID:");
		TextRender_string24(x +8, y + 88,clNearBlack, "Dev Type:");
		
		if (IsInput){
			TextRender_string24(x +8, y +168,clNearBlack, "Logical:");
		}else{
			TextRender_string24(x +8, y +128,clNearBlack, "Delay Sec:");
		}
	}

	EuCode.Init(x+120,y+ 48,120,30,0,0,clNearBlack,clNearWhite);
	EuCode.SetMaxLen(8);
	EuCode.Str.FromStr("xxxxxxxx");
	EuCode.Pst = 7;
	EdType.Init(x+120,y+ 88,46,30,0,0,clNearBlack,clNearWhite);
	EdType.SetMaxLen(3);
	EdType.Str.FromStr("xxx");
	EdType.Pst = 2;
	
	EInnerCount.Init(x+120,y+128,46,30,0,0,clNearBlack,clNearWhite);
	
	if(IsInput){
		ELogic.Init(x+120,y+168,46,30,0,0,clNearBlack,clNearWhite);
		ELogic.SetMaxLen(2);
		if(LanguageEnCn==0)ELogic.Str.FromStr("或");
		else ELogic.Str.FromStr("or");
		ELogic.IsShowCursor = 0;
		ELogic.Pst = 1;
	}else{
		EDelay.Init(x+120,y+128,46,30,0,0,clNearBlack,clNearWhite);
		EDelay.SetMaxLen(3);
		EDelay.Str.FromStr("600");
		EDelay.IsShowCursor = 1;
		EDelay.Pst = 2;
	}
	
	EInCount.Init(x+120,y+208,46,30,0,0,clNearBlack,clNearWhite);
	
	SetEditStart();
	EuCode.SetPstTail();
	EdType.SetPstTail();
	EuCode.Show();
	EdType.Show();
	if(IsInput){
		ELogic.SetPstTail();
		ELogic.Show();
		EInnerCount.SetMaxLen(1);
		EInCount.SetMaxLen(1);
		EInnerCount.SetPstTail();
		EInCount.SetPstTail();
	
		EInnerCount.Show();
		EInCount.Show();
	}else{
		EDelay.SetPstTail();
		EDelay.Show();
	}
	
	STextDType.Init(x + 170,	y+ 88,	200,	30,0,0,clNearBlack,clFrmFace);
	CheckShowDevType();
	
	if(LanguageEnCn==0){
		if(IsInput){
			TextRender_string24(x +8, y +128,clNearBlack, "内部数量:"); TextRender_string24(x +168, y +128,clNearBlack, "范围:1~9");
			TextRender_string24(x +8, y +208,clNearBlack, "输入数量:"); TextRender_string24(x +168, y +208,clNearBlack, "范围:1~9");
			TextRender_string24(x +22, y +248,clNearBlack, "确认键执行修改,返回键放弃修改");
		}else{
			TextRender_string24(x +22, y +168,clNearBlack, "确认键执行修改,返回键放弃修改");
		}
	}else{
		if(IsInput){
			TextRender_string24(x +8, y +128,clNearBlack, "Internal:"); 
			TextRender_string24(x +168, y +128,clNearBlack, "Scope:1..9");
			TextRender_string24(x +8, y +208,clNearBlack, "And Num:"); 
			TextRender_string24(x +168, y +208,clNearBlack, "Scope:1..9");
			TextRender_string24(x +22, y +248,clNearBlack, "Key OK Modify, Or Return");
		}else{
			TextRender_string24(x +22, y +168,clNearBlack, "Key OK Modify, Or Return");
		}
	}
	
	if(IsInput){
		x2 = x + 170;
		y2 = y + 168  + 6;
		y2 += 9;
		h =3;
		for(w=0; w<10; w++){
			VertLineRender(x2, y2, h, clNearBlack);
			y2--;
			h += 2; 
			x2++;
		}

		x2 = x + 170 + 14;
		y2 = y + 168 + 6;
		y2 += 0;
		h =21;
		for(w=0; w<10; w++){
			VertLineRender(x2, y2, h, clNearBlack);
			x2++;
			h -= 2; 
			y2++;
		}
	}
}

void TLinkageProgram::RedrawEEdit()
{
	EuCode.Show();
	EdType.Show();
	if(IsInput){
		EInnerCount.Show();
		ELogic.Show();
		EInCount.Show();	
	}else{ 
		EDelay.Show();
	}
}

void TLinkageProgram::CheckEWhatWhoActive()
{
	EuCode.Selected = 0;
	EdType.Selected = 0;
	EInnerCount.Selected = 0;
	ELogic.Selected = 0;
	EInCount.Selected = 0;
	EDelay.Selected = 0;
	if(eWhat == 0) EuCode.Selected = 1;
	else if(eWhat == 1) EdType.Selected = 1;
	else{
		if(IsInput){
			if(eWhat == 2)EInnerCount.Selected = 1;
			else if(eWhat == 3)ELogic.Selected = 1;
			else if(eWhat == 4)EInCount.Selected = 1;
		}else{
			EDelay.Selected = 1;
		}
	}
}

void TLinkageProgram::RedrawItemEdit()
{
	
}

void TLinkageProgram::LoadExp(unsigned int aExp)
{
	unsigned int x,y,i;
	unsigned int SysLinkAddr;
	unsigned int aAddr4Char;
	unsigned int aAddr4Int;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	
	if(*(volatile unsigned char *)(SysLinkAddr + 4) == 'M')IsMask =1; else IsMask=0; 
	if(*(volatile unsigned char *)(SysLinkAddr + 5) == 'S')DoStop =1; else DoStop=0;
	if(*(volatile unsigned char *)(SysLinkAddr + 6) == 'F')IsSelfActive =1; else IsSelfActive=0; 
	for(y=0; y<8; y++){
		for(x=0; x<4; x++){
			aAddr4Char = SysLinkAddr + (y * 4 * 16) + (x * 16) + 16;
			for(i=0; i<16; i++){
				tEntry[y][x][i] = *(volatile unsigned char *)(aAddr4Char++);
			}
			tEntry[y][x][16] = '\0';
			tEntry[y][x][17] = '\0';
		}
	}
}

void TLinkageProgram::LoadExpVoid()
{
	unsigned int x,y,i;
	for(y=0; y<8; y++){
		for(x=0; x<4; x++){
			for(i=0; i<16; i++){
				tEntry[y][x][i] = '\0';
			}
			tEntry[y][x][16] = '\0';
			tEntry[y][x][17] = '\0';
		}
	}
	IsMask = 0;
	DoStop = 0;
	IsSelfActive = 0;
}

void TLinkageProgram::RestoreExp(unsigned int aExp)
{
	unsigned int x,y,i;
	unsigned int SysLinkAddr;
	unsigned int aAddr4Char;
	unsigned int aAddr4Int;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	
	aAddr4Char = SysLinkAddr;
	*(volatile unsigned char *)(aAddr4Char++) = 'T';
	*(volatile unsigned char *)(aAddr4Char++) = 'R';
	*(volatile unsigned char *)(aAddr4Char++) = 'U';
	*(volatile unsigned char *)(aAddr4Char++) = 'E';
	
	SetLnkMask(aExp);
	SetLnkDoStop(aExp);
	SetLnkSelfActive(aExp);
	
	for(y=0; y<8; y++){
		for(x=0; x<4; x++){
			aAddr4Char = SysLinkAddr + (y * 4 * 16) + (x * 16) + 16;
			for(i=0; i<16; i++){
				*(volatile unsigned char *)(aAddr4Char++) = tEntry[y][x][i];
			}
		}
	}	
}

void TLinkageProgram::GetLnkMask(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(*(volatile unsigned char *)(SysLinkAddr + 4) == 'M'){
		IsMask = 1;
	}else{
		IsMask = 0;
	}	
}

void TLinkageProgram::SetLnkMask(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(IsMask){
		*(volatile unsigned char *)(SysLinkAddr + 4) = 'M';
	}else{
		*(volatile unsigned char *)(SysLinkAddr + 4) = ' ';
	}
}

void TLinkageProgram::GetLnkDoStop(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(*(volatile unsigned char *)(SysLinkAddr + 5) == 'S'){
		DoStop = 1;
	}else{
		DoStop = 0;
	}		
}

void TLinkageProgram::GetLnkSelfActive(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(*(volatile unsigned char *)(SysLinkAddr + 6) == 'F'){
		IsSelfActive = 1;
	}else{
		IsSelfActive = 0;
	}		
}

void TLinkageProgram::SetLnkDoStop(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(DoStop){
		*(volatile unsigned char *)(SysLinkAddr + 5) = 'S';
	}else{
		*(volatile unsigned char *)(SysLinkAddr + 5) = ' ';
	}	
}

void TLinkageProgram::SetLnkSelfActive(unsigned int aExp)
{
	unsigned int SysLinkAddr;
	SysLinkAddr = dSdAddrLinkageExp + (aExp * 1024);
	if(IsSelfActive){
		*(volatile unsigned char *)(SysLinkAddr + 6) = 'F';
	}else{
		*(volatile unsigned char *)(SysLinkAddr + 6) = ' ';
	}	
}
















