/***************************************************************************
**
**    $Header$
**
**    $Log$
** 
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  FLDDLG.CPP
//
//  Description:The Implementation file of dialog box for Peripheral window
//
//  Author:     Jerry Yan 
//				modify by Richard Guo, 10/24/96
//
//  Date:       09/18/95
//
//  Modification:
//
//      1. 09/18/95, Initial version 
//
//
//  Copyright (C) 1995 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"  
#include "percore.h"
//#include "xview.h"
#include "flddlg.h"
#include "listcol.h"
#include "mylist.h"   
#include "spin.h"
#include "abiextfn.h"
#include "cpucom.h"
#include "cpusvr.h"   
#include "regsvr.h"
#include "uicom2.h"
#include "hosterrs.h"
//#include "errcodec.h"   

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
extern WORD cpuid; 
extern HINSTANCE hPerLib; 

CString strBitName[16],strBitValue[16];
#define  TWIPS_PER_INCH 1440
int ColWidth;             

#define KC196_WSR_BASEID	480
/////////////////////////////////////////////////////////////////////////////
// CFldDlg dialog


CFldDlg::CFldDlg(CWnd* pParent /*=NULL*/, int index)
    : CDialog(CFldDlg::IDD, pParent)
{   
     m_pParent=pParent; 
     m_nIndex=index;  
//     m_wBaseID = wBaseID;
     m_nFldMax=1;
    //{{AFX_DATA_INIT(CFldDlg)
     m_strFldVal = "";
     m_strRegVal = "";  
	//}}AFX_DATA_INIT    
	
	lpPerCore = new CPerCore(cpuid, hPerLib);
}
       
CFldDlg::~CFldDlg()
{
	if (lpPerCore) delete lpPerCore;
}           

void CFldDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CFldDlg)
    DDX_Text(pDX, IDC_FIELD_VAL, m_strFldVal);
    DDX_Text(pDX, IDC_REG_VAL, m_strRegVal);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFldDlg, CDialog)
    //{{AFX_MSG_MAP(CFldDlg)
    ON_LBN_SELCHANGE(IDC_FIELD_LIST, OnSelchangeFieldList)
    ON_BN_CLICKED(IDC_NEXT_BUTT, OnNextButt)
    ON_BN_CLICKED(IDC_PREV_BUTT, OnPrevButt)
    ON_BN_CLICKED(IDC_CLOSE_BUTT, OnCloseButt)
    ON_BN_CLICKED(IDC_WRI_BUTT, OnWriButt)
    ON_WM_VSCROLL()
	ON_EN_SETFOCUS(IDC_REG_VAL, OnSetfocusRegVal)
	ON_LBN_SETFOCUS(IDC_FIELD_LIST, OnSetfocusFieldList)
	ON_EN_SETFOCUS(IDC_FIELD_VAL, OnSetfocusFieldVal)
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_LBUTTONDBLCLK()
    ON_EN_KILLFOCUS(IDC_REG_VAL,OnRegValKillFocus)    
    ON_EN_KILLFOCUS(IDC_FIELD_VAL,OnFieldValKillFocus)  
	ON_WM_HSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CFldDlg message handlers

BOOL CFldDlg::OnInitDialog()
{
    CDialog::OnInitDialog();  
    
    CenterWindow();
    
  //SetWindowPlacement
    m_bCanClose=TRUE; 
    HFONT hFont;
    hFont=(HFONT)GetStockObject(ANSI_FIXED_FONT);
    CFont Font; 
    GetDlgItem(IDC_FIELD_LIST)->SetFont(Font.FromHandle(hFont));
//    GetDlgItem(IDC_RO_EDIT)->SetFont(Font.FromHandle(hFont));
    ((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->SetHorizontalExtent(1400);   
    
    PERI_DRAWDATA* lpDrawData;    
    lpDrawData=(PERI_DRAWDATA*)(((CListBox*)(m_pParent->GetDlgItem(IDC_LIST1)))->GetItemDataPtr(m_nIndex) ); 

    int bitplace = lpDrawData->offset; 
    if(bitplace>0) bitplace--;
    
    m_wBaseID = lpDrawData->BaseID; 
    
	InitDlgData(bitplace);
	    
    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CFldDlg::OnSelchangeFieldList()
{   
    int  cursel;                                                    
    // set field value      
    cursel=((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->GetCurSel();      
    
    SetEdit(cursel);
    
}

void CFldDlg::ResetListContent()
{
	CListBox* lpFieldList = (CListBox*)GetDlgItem(IDC_FIELD_LIST);
	int nCount = lpFieldList->GetCount();
	PERI_FIELD_DRAWDATA* lpFieldItem;
	while(nCount>0)
	{
		lpFieldItem = (PERI_FIELD_DRAWDATA*)lpFieldList->GetItemDataPtr(nCount-1);	
		delete lpFieldItem;
		lpFieldList->DeleteString(nCount-1);
		nCount--;
	}	
}

void CFldDlg::UpdateRegValue()
{                   
    switch(m_nByteNum){
    	case 1: // Byte
    		wsprintf(m_strRegVal.GetBuffer(10), "0x%02lX", m_dwRegVal);
    		break;
		case 2: // Word
			wsprintf(m_strRegVal.GetBuffer(10), "0x%04lX", m_dwRegVal);
			break;
		case 4: // DWord   	
			wsprintf(m_strRegVal.GetBuffer(14), "0x%08lX", m_dwRegVal);
			break;      
	}

    UpdateData(FALSE); 
    m_strRegVal.ReleaseBuffer();
}
             
void CFldDlg::SetDlgList()
{ 
    ResetListContent();
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->ResetContent();
//    int regval; 
    
    WORD wStartID = lpPerCore->GetRegStrID(m_wBaseID);
    WORD wSerialNo = lpPerCore->RegSerialNo(m_wBaseID);
     
    char szTemp[256], szDesc[256];
    char* szData, *szCur;           

    ::LoadString(hPerLib, m_wBaseID, szTemp, 255);
    szCur = szTemp;
    gstrtok(szCur, ","); //bypass father base string id
    gstrtok(szCur, ","); //bypass register serial number
    gstrtok(szCur, ","); //bypass byte flag
	szData = gstrtok(szCur, ",");
	int nChildNum = atoi(szData);    
    
    wStartID++;
    for(int i=0; i<nChildNum; i++)
    {
		 WORD wStart, wLen;
		 
		 PERI_FIELD_DRAWDATA* lpField = new PERI_FIELD_DRAWDATA;
		 szData = gstrtok(szCur, ",");
		 RegBitStartLen(szData, wStart, wLen); 
		 
		 szData = gstrtok(szCur, ",");
		 lpField->needMerge = !atoi(szData);
		 lpField->byStart = (BYTE)wStart;
		 lpField->byLen = (BYTE)wLen;                
//		 MergeBitName(wSerialNo, lpField->byStart, 
//		 		(BYTE)(lpField->byStart+lpField->byLen-1), lpField->szName);
		 lpField->wDescStrID = wStartID++;
		 
		 char szDescStr[256];
		 WORD nFieldVal;
		     
		 nFieldVal = (WORD)(m_dwRegVal >> lpField->byStart);
		 nFieldVal &= ((WORD)1<<lpField->byLen) - 1;
		 
		 		
		 lpPerCore->GetBitDescStr(wStartID, nFieldVal, lpField->needMerge, szDescStr);
		 wsprintf(szDesc, "%s", szDescStr);
		 
		 ((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->InsertString(i, szDesc);
		 ((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->SetItemDataPtr(i, lpField);
		 
		 if ((cpuid >= EP196KC_CPUID_START) && 
		     (cpuid <= EP196KC_CPUID_END) &&
		     (m_wBaseID == KC196_WSR_BASEID) && (i==0)) // for KC, handle individully
		 {
		 	wStartID += 19;
		 }
		 else
		 {
		 	if (lpField->needMerge)
		 		wStartID++;
		 	else
		 		wStartID += (WORD)1<<lpField->byLen;
		 }
    }  
}             


void CFldDlg::SetEdit(int cursel)
{ 
	
    PERI_FIELD_DRAWDATA *lpField;
//    char sztemp[256];         
    
    lpField = (PERI_FIELD_DRAWDATA*)
    	((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->GetItemData(cursel);
    
//    char szDesc[256];
    
    DWORD regval = m_dwRegVal; 
    m_nFldMax = 1 << lpField->byLen;
    regval= (regval>> lpField->byStart) & (m_nFldMax-1);
    
////////////////////////////////////////////////////////////////////
    ((CSpinControl*)GetDlgItem(1995))->SetRange(0,m_nFldMax);   
    
/////////////////////////////////////////////////////////////////////   
    if(regval<=0x0f)
	    sprintf(m_strFldVal.GetBuffer(14),"0x0%X",regval);
    else
     	sprintf(m_strFldVal.GetBuffer(14),"0x%X",regval);

    UpdateData(FALSE);
    m_strFldVal.ReleaseBuffer();
    //set notes 
    char szBuff[256];
    if (lpField->byLen==1)
    	wsprintf(szBuff,"%d:", lpField->byStart);
    else
    	wsprintf(szBuff, "%d-%d:", lpField->byStart, 
    		lpField->byStart + lpField->byLen-1);
    		
    ////////////////////////////////////////////////////
    GetDlgItem(IDC_RO_EDIT0)->SetWindowText(szBuff);
////////////////////////////////////////////////////////    
	
    ::LoadString(hPerLib, lpField->wDescStrID, szBuff, 255); 
    SetDlgItemText(IDC_RO_EDIT1, szBuff);
    
    lpPerCore->GetBitDescStr(lpField->wDescStrID+1, (WORD)regval, 
    		lpField->needMerge, szBuff);
	    		
    SetDlgItemText(IDC_RO_EDIT2,szBuff); 
    SetGrid(m_dwRegVal);
}              


void CFldDlg::OnNextButt()
{      
    m_bCanClose=TRUE;
    
    m_wBaseID = lpPerCore->RightBrotherBase(m_wBaseID);
    
    InitDlgData(0); 
    
    
}
   

void CFldDlg::OnPrevButt()
{
    m_bCanClose=TRUE;

    m_wBaseID = lpPerCore->LeftBrotherBase(m_wBaseID);
	
	InitDlgData(0);    
}

void CFldDlg::InitDlgData(int cursel)
{
    
    WORD wDescStrID = lpPerCore->GetRegStrID(m_wBaseID);
    
    char sztemp[256];
    
    WORD wSerialNo = lpPerCore->RegSerialNo(m_wBaseID);
    GetRegLen(wSerialNo, m_nByteNum);    
    
    m_nScrollCol = 0;
    
    ::LoadString(hPerLib, wDescStrID, sztemp, 255);
    
    SetWindowText(sztemp);   
    
    ///////////////////////////////////////////////////////////////////
	
    GetRegValue(wSerialNo, m_dwRegVal);      

    UpdateRegValue();
    
    SetDlgList(); 
    
    GridInit();
   	CaluGridRect();  
    SetNameScroll(cursel); 

    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(cursel);
    SetEdit(cursel);    
}

void CFldDlg::SetNameScroll(int cursel)
{       
	m_nScrollCol = 0;
	
	if (m_nByteNum<=1)
		((CScrollBar*)GetDlgItem(IDC_PER_NAME_SCROLL))->ShowScrollBar(FALSE);		
	else
	{                             
		CScrollBar* pScroll = (CScrollBar*)GetDlgItem(IDC_PER_NAME_SCROLL);
		
		CRect scrollRect;
		pScroll->GetWindowRect(scrollRect);
		ScreenToClient(scrollRect);
		
		scrollRect.OffsetRect(0, m_GridRect.bottom-scrollRect.top + 4);

		scrollRect.left = m_GridRect.left;
		scrollRect.right = m_GridRect.right;
				
		pScroll->MoveWindow(scrollRect);
		
		pScroll->ShowScrollBar(TRUE);
		pScroll->EnableScrollBar(ESB_ENABLE_BOTH);
		pScroll->SetScrollRange(0, (m_nByteNum-1)*8);
		
		pScroll->SetScrollPos((cursel/8)*8);;
	}
}

void CFldDlg::OnCloseButt()
{
      m_bCanClose=TRUE;
  //  if(m_bCanClose)
      CDialog::OnCancel();
 
}



void CFldDlg::OnWriButt()
{
    DWORD regval;                            
    if(GetFocus()!=GetDlgItem(IDC_WRI_BUTT) )
       GetDlgItem(IDC_WRI_BUTT)->SetFocus();
    if(m_bCanClose)                          
     {
    	
    	regval= (DWORD)Hex2Dec(m_strRegVal.GetBuffer(14));
		WORD wRegSerialNo = lpPerCore->RegSerialNo(m_wBaseID);
		
////////////////////////////////////////////////////////////
    	SetRegValue(wRegSerialNo, regval); 
    	GetRegValue(wRegSerialNo, regval);
    	
//////////////////////////////////////////////////////////////
    	if(regval<=0x0f)                              
    	    sprintf(m_strRegVal.GetBuffer(14),"0x0%X",regval);
    	else
    		sprintf(m_strRegVal.GetBuffer(14),"0x%X",regval);
    	UpdateData(FALSE); 
    	m_strRegVal.ReleaseBuffer(); 
    
    	int reg_index;
    	
    	((CMyList*)m_pParent->GetDlgItem(IDC_LIST1))->CurTopItem(
    		m_wBaseID, reg_index);
    	
    	int nCount;
    	nCount = ((CListBox*)m_pParent->GetDlgItem(IDC_LIST1))->GetCount();

		PERI_DRAWDATA* lpTop;                      
//		PERI_DRAWDATA* lpCur;   
//		PERI_DRAWDATA* lpFather;
    	
		lpTop = (PERI_DRAWDATA*)(((CListBox*)(m_pParent->GetDlgItem(
			IDC_LIST1)))->GetItemDataPtr(reg_index));
		
		wRegSerialNo = lpPerCore->RegSerialNo(lpTop->BaseID);
		GetRegValue(wRegSerialNo, lpTop->dwVal);

//		reg_index++;
//		lpFather = lpTop;
		
		((CListBox*)(m_pParent->GetDlgItem(IDC_LIST1)))->DeleteString(reg_index);                
		
        ((CListBox*)(m_pParent->GetDlgItem(IDC_LIST1)))->InsertString(
        		reg_index, (LPSTR)lpTop); 
//		while(reg_index < nCount){
//			lpCur = (PERI_DRAWDATA*)(((CListBox*)(m_pParent->GetDlgItem(
//				IDC_LIST1)))->GetItemDataPtr(reg_index));
				
//    		if (lpTop->Level >= lpCur->Level)
//    			break; // not belong to this register
    			
    		if(lpTop->isExpanded){
        		int nChildCount;
        		((CMyList*)(m_pParent->GetDlgItem(IDC_LIST1
        				)))->DeleteOffspringItem(reg_index);  
	        	nChildCount = ((CMyList*)(m_pParent->GetDlgItem(IDC_LIST1
	        			)))->InsertChildItem(reg_index);       
				
//				reg_index += nChildCount;
//				if (reg_index >= nCount) break;
//				lpCur = (PERI_DRAWDATA*)(((CListBox*)(m_pParent->GetDlgItem(
//					IDC_LIST1)))->GetItemDataPtr(reg_index));
//				if (lpTop->Level >= lpCur->Level) break;
				
    		}           
    			
//    		wRegSerialNo = lpPerCore->RegSerialNo(lpCur->BaseID);
//    		GetRegValue(wRegSerialNo, lpCur->dwVal); 
//    		reg_index++;  
//    		lpFather = lpCur;
//    	}
    
    	RepaintCPU();
		RepaintMemory();
//		RepaintBMemory();
	
		RepaintStack();
		RepaintVariable(); 
    	CDialog::OnOK(); 
   	   }
//   	   else
//   	   {  
//            AfxMessageBox("Your input is not valible!",MB_OK);
//        }
   	m_bCanClose=TRUE;    
}


void CFldDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    DWORD fldval; 
    DWORD regval;
    long sign; 
    char Buff[8]="";  
    
    if(pScrollBar==(CScrollBar*)GetDlgItem(1995))
    {                        
       PERI_FIELD_DRAWDATA* lpField;
       int cursel = ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetCurSel();
       lpField = (PERI_FIELD_DRAWDATA*)
     	  ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetItemDataPtr(cursel);
       
       if(nSBCode==SB_LINEUP)
       {
      	 sign=Hex2Dec(m_strFldVal.GetBuffer(14))    ;
    	 fldval=(sign+1)%m_nFldMax; 
    	 sign=fldval-sign;
         if(fldval<=0x0f)
            sprintf(m_strFldVal.GetBuffer(14),"0x0%lX",fldval);
         else                                             
         	sprintf(m_strFldVal.GetBuffer(14),"0x%lX",fldval);
    	 UpdateData(FALSE);   
		
//         regval=Hex2Dec(m_strRegVal.GetBuffer(7));
		 regval = m_dwRegVal;
//    	 m_strRegVal.ReleaseBuffer();
    	 if(sign>0)
        	regval+=(sign<< lpField->byStart);
    	 else regval-=((-sign)<< lpField->byStart); 
    
    	 m_dwRegVal=regval;
    	 if(regval<=0x0f)
			sprintf(m_strRegVal.GetBuffer(14),"0x0%lX",regval);    	 
    	 else
    	    sprintf(m_strRegVal.GetBuffer(14),"0x%lX",regval);
    	 UpdateData(FALSE);
    	 m_strRegVal.ReleaseBuffer(); 
////////////////////////////////////////   
    //SendMessage(WM_COMMAND,IDC_FIELD_VAL, MAKELONG(GetDlgItem(IDC_FIELD_VAL)->m_hWnd,EN_CHANGE));
       }  
       else
       {
         sign=Hex2Dec(m_strFldVal.GetBuffer(14));  
         if(sign==0)
            fldval=m_nFldMax-1;
         else   
            fldval=(DWORD)((abs(sign-1))%m_nFldMax);          
    	 sign=fldval-sign;
         if(fldval<=0x0f)
            sprintf(m_strFldVal.GetBuffer(14),"0x0%lX",fldval);
         else
          	sprintf(m_strFldVal.GetBuffer(14),"0x%lX",fldval);   
    	 UpdateData(FALSE);  

         regval=Hex2Dec(m_strRegVal.GetBuffer(14)); 
    	 m_strRegVal.ReleaseBuffer();
//		 regval = m_dwRegVal;
    	 if(sign>0)
        	regval+=(sign<< lpField->byStart);
    	 else regval-=((-sign)<< lpField->byStart);
    	 m_dwRegVal=regval;
   		 if(regval<=0x0f)
   		   	sprintf(m_strRegVal.GetBuffer(14),"0x0%lX",regval);
   		 else
   		 	sprintf(m_strRegVal.GetBuffer(14),"0x%lX",regval);
    	 UpdateData(FALSE); 
   		 m_strRegVal.ReleaseBuffer(); 
    
    //SendMessage(WM_COMMAND,IDC_FIELD_VAL, MAKELONG(GetDlgItem(IDC_FIELD_VAL)->m_hWnd,EN_CHANGE));
        }      
  	    SetGrid(regval); 

    char szDesc[256];
    
    lpPerCore->GetBitDescStr(lpField->wDescStrID+1, (WORD)fldval, 
    		lpField->needMerge, szDesc);
    
    SetDlgItemText(IDC_RO_EDIT2,szDesc); 

    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->InsertString(cursel,szDesc);
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->DeleteString(cursel+1);
   
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetItemDataPtr(cursel,lpField); 
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(cursel);
    
   }   
  ///////////////////////////////////////////////////
    
    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
} 


void CFldDlg::GridInit()
{ 
	char szBuf[256]="";
	char *sztemp;          
	char *szToken;
        
	for(int i=0;i<m_nByteNum*8;i++){
	    strBitName[i]='\0';
        strBitValue[i]='\0';
        m_nExplain[i] = -1; // mean no explain string
     }
    
    WORD wSerialNo = lpPerCore->RegSerialNo(m_wBaseID);
    ::LoadString(hPerLib,m_wBaseID,szBuf,255); 
	sztemp = szBuf;
		
	gstrtok(sztemp,",");  // bypass father string ID
	gstrtok(sztemp, ","); // bypass register serial number
	gstrtok(sztemp, ","); // bypass byte flag
	szToken = gstrtok(sztemp, ",");  // get total number	
	int nTotal = atoi(szToken);
		
	char szBuffer[256];
	    
	m_nNameRow = 1;	    
	for(i=0; i<nTotal; i++){         
		WORD wStart, wLen;
		szToken = gstrtok(sztemp, ",");
		RegBitStartLen(szToken, wStart, wLen); 

	    ((CListBox*)(GetDlgItem(IDC_FIELD_LIST)))->GetText(i, szBuffer); 
    
		for(WORD j=wStart;j<wStart+wLen; j++){
//			GetRegBitName(wSerialNo, (BYTE)j, strBitName[j].GetBuffer(7));  
			GetRegBitName(szBuffer, (BYTE)(j-wStart), strBitName[j].GetBuffer(20));
			strBitName[j].ReleaseBuffer();       
			m_nExplain[j] = i;
		}                                     
		gstrtok(sztemp, ",");
	}
	
	for (i=0; i<m_nByteNum*8; i++){
		if (strBitName[i].Find('_') > 0)
		{
			m_nNameRow = 2;
			break;
		}
	}		
}
                 
                 
void CFldDlg::SetGrid(DWORD regvalue)
{
    int nCol;  
    DWORD n;
	for ( nCol = 0; nCol < m_nByteNum*8; nCol++)
	{   
       n=regvalue%2;
       regvalue=regvalue>>1;
       strBitValue[nCol]=n?'1':'0';
 	}            
 	CRect rect;
    GetClientRect(&rect);
    rect.top=m_GridRect.top-2;
    rect.bottom=rect.top+m_DefCellSize.cy*3 + 24;
    InvalidateRect(&rect,TRUE );
// 	Invalidate(TRUE);
 	UpdateWindow();
}


void CFldDlg::OnRegValKillFocus()
{
/*   int tem, cursel;
    tem=m_dwRegVal;  
    
    cursel=((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetCurSel();    
    UpdateData(TRUE); 
    AnsiUpper(m_strRegVal.GetBuffer(7)); 
    m_strRegVal.ReleaseBuffer(); 
    
    if(!CheckString(m_strRegVal) )  
        {
          m_bCanClose=FALSE;
//        AfxMessageBox("Your input is not valible!",MB_OK);
		  ErrDisplayError(ER_PRE_INVALID_INPUT);           
       	  if(tem<=0x0f)
       	  	sprintf(m_strRegVal.GetBuffer(7),"0x0%X",tem);
       	  else
       	  	sprintf(m_strRegVal.GetBuffer(7),"0x%X",tem);	
          UpdateData(FALSE);
            
            
           // GetFocus()->PostMessage(WM_LBUTTONUP); 
          GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONDOWN);
          GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONUP); 

         } 
     else{
    
    	  m_dwRegVal=Hex2Dec(m_strRegVal.GetBuffer(7));
    	  m_strRegVal.ReleaseBuffer();
    	  UpdateData(FALSE);
    	  if(tem!=m_dwRegVal)
   		   {
    			SetDlgList(m_nRegid); 
//   				GridInit(m_nRegid); 
       			((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(cursel);
   	    		SetEdit(cursel); 
   		    }          
   	      }
*/ 
    int cursel; 
    DWORD tem;
    tem= m_dwRegVal;  
    
    cursel=((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetCurSel();    
    UpdateData(TRUE); 
    AnsiUpper(m_strRegVal.GetBuffer(14)); 
    m_strRegVal.ReleaseBuffer();          
    
    DWORD dwMaxVal = 0;
    switch(m_nByteNum){
    	case 1:
    		dwMaxVal = 0xff;
    		break;
    	case 2:
    		dwMaxVal = 0xffff;
    		break;
    	case 4:
    		dwMaxVal = 0xffffffff;
    		break;
    }
    
    switch(CheckString(m_strRegVal, dwMaxVal))
	{
		case PER_INVALID_CARD:
			m_bCanClose=FALSE;
        	AfxMessageBox("Your input is not valible!",MB_OK);
//		  ErrDisplayError(ER_PRE_INVALID_INPUT);           
       	  	if(tem<=0x0f)
       	  		sprintf(m_strRegVal.GetBuffer(14),"0x0%X",tem);
       	  	else
       	  		sprintf(m_strRegVal.GetBuffer(14),"0x%X",tem);	
          	UpdateData(FALSE);
           // GetFocus()->PostMessage(WM_LBUTTONUP); 
          	GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONDOWN);
          	GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONUP); 
          	return;
        case PER_TOO_LARGE:
            m_bCanClose=FALSE;
	        AfxMessageBox("Your input is too large!",MB_OK);
            if(tem<=0x0f)
       	  		sprintf(m_strRegVal.GetBuffer(14),"0x0%X",tem);
       	  	else
       	  		sprintf(m_strRegVal.GetBuffer(14),"0x%X",tem);	
            UpdateData(FALSE);
           // GetFocus()->PostMessage(WM_LBUTTONUP); 
          	GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONDOWN);
          	GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONUP); 
            return ;	
        case PER_OK:
    	    m_dwRegVal= (DWORD)Hex2Dec(m_strRegVal.GetBuffer(14));
    	  	m_strRegVal.ReleaseBuffer();

    	  	UpdateData(FALSE);
    	  	if(tem!=m_dwRegVal)
   		   	{              
   		   		UpdateRegValue();
    			SetDlgList(); 
//   				GridInit(m_nRegid); 
       			((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(cursel);
   	    		SetEdit(cursel); 
   		    }          
   	 }

}   


void CFldDlg::OnFieldValKillFocus()
{
	int  cursel;
    CString tem;
    tem=m_strFldVal;  
    
    cursel=((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetCurSel();    
    PERI_FIELD_DRAWDATA* lpField;
    lpField = (PERI_FIELD_DRAWDATA*)
    	((CListBox*)GetDlgItem(IDC_FIELD_LIST))->GetItemDataPtr(cursel);

    UpdateData(TRUE); 
    AnsiUpper(m_strFldVal.GetBuffer(16)); 
    m_strFldVal.ReleaseBuffer(); 
    
    DWORD tint=Hex2Dec(m_strFldVal.GetBuffer(16));
    m_strFldVal.ReleaseBuffer();
    
    switch(CheckString(m_strFldVal, m_nFldMax) )  
    {
    	case PER_INVALID_CARD:
          	m_bCanClose=FALSE;
        	AfxMessageBox("Your input is not valible!",MB_OK);
//          ErrDisplayError(ER_PRE_INVALID_INPUT);  
          	m_strFldVal=tem;
          	UpdateData(FALSE);            
           
           //GetFocus()->SetCapture();
            GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONDOWN); 
            GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONUP); 
            
            break;
        case PER_TOO_LARGE:
            m_bCanClose=FALSE;
//            ErrDisplayError(ER_PRE_VALUE_TOO_LARGE);
            m_strFldVal=tem;
            UpdateData(FALSE);
           //GetFocus()->PostMessage(WM_LBUTTONUP);
            GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONDOWN);
            GetDlgItem(IDC_FIELD_LIST)->PostMessage(WM_LBUTTONUP); 
            break;
		case PER_OK:
    		UpdateData(FALSE);
    	//	OnChangeFieldVal();

            int regval,sign;
            sign=(int)(Hex2Dec(m_strFldVal.GetBuffer(14))-Hex2Dec(tem.GetBuffer(14)));
    		m_strFldVal.ReleaseBuffer();
    		tem.ReleaseBuffer(); 
            
            regval=(int)Hex2Dec(m_strRegVal.GetBuffer(14)); 
   		    m_strRegVal.ReleaseBuffer();
   			if(sign>0)
      		 	regval+=(sign<< lpField->byStart);
   			else regval-=((-sign)<< lpField->byStart);
   			m_dwRegVal=regval;                              
   			
   			if(regval<=0x0f)
   				sprintf(m_strRegVal.GetBuffer(14),"0x0%X",regval);
   			else	
   				sprintf(m_strRegVal.GetBuffer(14),"0x%X",regval);
    		UpdateData(FALSE); 
   			m_strRegVal.ReleaseBuffer(); 
  	        SetGrid(m_dwRegVal);	  
      } 
    
    char szDesc[256];    
    
    lpPerCore->GetBitDescStr(lpField->wDescStrID+1, (WORD)Hex2Dec(m_strFldVal.GetBuffer(14)),
    	 lpField->needMerge, szDesc);
    m_strFldVal.ReleaseBuffer();                   
    
    
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->InsertString(cursel,szDesc);
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->DeleteString(cursel+1);
   
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetItemDataPtr(cursel,lpField); 
    ((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(cursel);
}				         

void CFldDlg::OnSetfocusRegVal()
{
	m_bCanClose=TRUE;
}

void CFldDlg::OnSetfocusFieldList()
{
	m_bCanClose=TRUE;
}

void CFldDlg::OnSetfocusFieldVal()
{
  m_bCanClose=TRUE;
}

void CFldDlg::OnDestroy()
{
/*	(m_pParent->GetDlgItem(IDC_LIST1) )->SendMessage(WM_LBUTTONDOWN); 
   (m_pParent->GetDlgItem(IDC_LIST1) )->SendMessage(WM_LBUTTONUP);
   ((CListBox*)(m_pParent->GetDlgItem(IDC_LIST1)))->SetCurSel(m_nIndex);
*/  
	ResetListContent();
	CDialog::OnDestroy();
}




void CFldDlg::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
    dc.SetBkMode(TRANSPARENT);
//////////////////////////////////////////////////////////////////
    GridSetName(&dc); 
    DrawFrame(&dc,m_GridRect,0);
    m_GridRect.InflateRect(1,1);
	DrawFrame(&dc,m_GridRect,1);
	m_GridRect.InflateRect(-1, -1);

	if (m_nByteNum > 1)
	{
		CRect scrollRect;

		GetDlgItem(IDC_PER_NAME_SCROLL)->GetWindowRect(scrollRect);
		ScreenToClient(scrollRect);
		
		scrollRect.InflateRect(1,1);
		DrawFrame(&dc, scrollRect, 0);
	}

//	3D style of the control.
	CRect rect;
	GetDlgItem(IDC_STATIC_REGISTER)->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.InflateRect(1,1);
	DrawFrame(&dc,rect,1);

	GetDlgItem(IDC_STATIC_FIELD)->GetWindowRect(&rect);	
	ScreenToClient(&rect);
	rect.InflateRect(1,1);
	DrawFrame(&dc,rect,1);

	GetDlgItem(IDC_STATIC_FIELDVALUE)->GetWindowRect(&rect);	
	ScreenToClient(&rect);
	rect.InflateRect(1,1);
	DrawFrame(&dc,rect,1);

	GetDlgItem(IDC_RO_EDIT0)->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.InflateRect(1,1);
	DrawFrame(&dc,rect,1);

	GetDlgItem(IDC_RO_EDIT1)->GetWindowRect(&rect);	
	CRect rect1;                                    
	GetDlgItem(IDC_RO_EDIT2)->GetWindowRect(&rect1);
	rect=rect|rect1;
	ScreenToClient(&rect);
	rect.InflateRect(1,1);
	DrawFrame(&dc,rect,0);
	// Do not call CDialog::OnPaint() for painting messages
}


void CFldDlg::CaluGridRect()
{       
	int i,nLen; 
	CSize size;           
	
    int org_x,org_y,end_x,end_y;
	
	CDC* pDC = GetDC();
    
    CRect ClientRect;
    GetClientRect(&ClientRect);

	// get bit name site
	CRect rect;
	GetDlgItem(IDC_PER_BIT)->GetWindowRect(&rect);
	ScreenToClient(&rect);
    
    org_x=ClientRect.Width()/8;
    org_y=rect.top;    
             
    end_x=ClientRect.Width()-org_x;
    
    size=pDC->GetOutputTextExtent("II",2);
	
//	end_y=org_y+(2+size.cy)*(m_nNameRow+1); //+1;  
	end_y=org_y+(2+size.cy)*3;
    
    m_DefCellSize.cx=(end_x-org_x-7)/8;
    m_DefCellSize.cy=(end_y-org_y)/(m_nNameRow+1);    	

	m_GridRect.SetRect(org_x,org_y,end_x,end_y);

	for(i=8*m_nByteNum-8-m_nScrollCol; i<8*m_nByteNum-m_nScrollCol;i++){                     
	  nLen=strBitName[i].GetLength() ;   
	  int nPart = -1;
	  
	  if (m_nNameRow >1) nPart = strBitName[i].Find('_');
	  
	  char* pName = strBitName[i].GetBuffer(nLen+1);
	  
	  if (nPart >=0 )
	  {   
	  	  CSize firstSize = pDC->GetOutputTextExtent(pName, nPart);
	  	  size = pDC->GetOutputTextExtent(pName+nPart+1, nLen-nPart-1);
	  	  if (firstSize.cx > size.cx) size.cx = firstSize.cx;
	  }
	  else
		  size=pDC->GetOutputTextExtent(strBitName[i].GetBuffer(nLen+1),nLen);
		  
	  strBitName[i].ReleaseBuffer();
	  if(size.cx>m_DefCellSize.cx+1){
	    m_GridRect.OffsetRect(-(size.cx-m_DefCellSize.cx)/2,0);
	    m_GridRect.right+=size.cx-m_DefCellSize.cx+2;
	    m_nAbnormal[i]=size.cx+2;
	  }
	  else                     
	    m_nAbnormal[i]=0;
	}                      
	
	ReleaseDC(pDC);
} 

void CFldDlg::DrawFrame(CDC * pdc, CRect rect,UINT flag)
{
    
//	ScreenToClient(&rect);
//	rect.InflateRect(1,1);
	    
    CPen* pOldPen,*pPen=new CPen;
//    pPen->CreatePen(PS_SOLID, 1,RGB(0,0,0) );
    CPoint points[4];   
    if(flag==0){
        points[0]=CPoint(rect.left,rect.bottom);
    	points[1]=CPoint(rect.left,rect.top);
    	points[2]=CPoint(rect.right,rect.top);
    	points[3]=CPoint(rect.right,rect.bottom); 
     }
    else{ 	
        points[0]=CPoint(rect.left,rect.bottom);
    	points[1]=CPoint(rect.right,rect.bottom); 
    	points[2]=CPoint(rect.right,rect.top);
    	points[3]=CPoint(rect.left,rect.top);
     }
//    pOldPen=pdc->SelectObject(pPen); 
    pdc->MoveTo(points[0]);
 	pdc->LineTo(points[1]);
 	pdc->LineTo(points[2]);
    pPen->DeleteObject();
       
    pPen->CreatePen(PS_SOLID,1,RGB(255,255,255) );
    pOldPen=pdc->SelectObject(pPen);
 	pdc->LineTo(points[3]);
 	pdc->LineTo(points[0]);
    pdc->SelectObject(pOldPen);
    pPen->DeleteObject();    
    delete pPen;
}    

/*
void CFldDlg::GridSetName(CDC* pDC)
{
	CRect CellRect; 
	CPen *pOldPen;
	int i,nLeft=m_GridRect.TopLeft().x,nRight,nLen ;
	nRight=nLeft;
	for(i=0;i<8;i++){
	  if(m_nAbnormal[i]==0){
	      nRight+=m_DefCellSize.cx;
          CellRect.SetRect(nLeft,m_GridRect.top,nRight,
                           m_GridRect.top+m_DefCellSize.cy); 		 	  
          nLeft+=m_DefCellSize.cx;nLeft++;nRight++; 
      }
      else{
        nRight+=m_nAbnormal[i];  
        CellRect.SetRect(nLeft,m_GridRect.top,nRight,
                       m_GridRect.top+m_DefCellSize.cy); 		 	  
        nLeft+=m_nAbnormal[i];nLeft++;nRight++; 
      } 
      if(i!=7){
         pDC->MoveTo(nRight,m_GridRect.top);  
         pDC->LineTo(nRight,m_GridRect.bottom);
         pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
         pDC->MoveTo(nRight+1,m_GridRect.top);  
         pDC->LineTo(nRight+1,m_GridRect.bottom);
         pDC->SelectObject(pOldPen);
      }
      nLen= strBitName[i].GetLength();
      pDC->DrawText(strBitName[i].GetBuffer(nLen+1),nLen,&CellRect,
                    DT_CENTER);
      strBitName[i].ReleaseBuffer();
      CellRect.OffsetRect(0,m_DefCellSize.cy);
      nLen= strBitValue[i].GetLength();
      pDC->DrawText(strBitValue[i].GetBuffer(nLen+1),nLen,&CellRect,
                    DT_CENTER);     
      strBitValue[i].ReleaseBuffer();                    
    } 
    pDC->MoveTo(m_GridRect.right,(m_GridRect.bottom+m_GridRect.top)/2);
	pDC->LineTo(m_GridRect.left, (m_GridRect.bottom+m_GridRect.top)/2);
    pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
    pDC->MoveTo(m_GridRect.right,(m_GridRect.bottom+m_GridRect.top)/2+1);
	pDC->LineTo(m_GridRect.left, (m_GridRect.bottom+m_GridRect.top)/2+1);
    pDC->SelectObject(pOldPen);
}
*/

void CFldDlg::GridSetName(CDC* pDC)
{
	CRect CellRect; 
	CPen *pOldPen;
	int i,nLeft=m_GridRect.TopLeft().x,nRight,nLen ;
	nRight=nLeft;
	for(i=7+(m_nByteNum-1)*8-m_nScrollCol; i>=(m_nByteNum-1)*8-m_nScrollCol;
			i--)
	{
	  if(m_nAbnormal[i]==0){
	      nRight+=m_DefCellSize.cx;
          CellRect.SetRect(nLeft,m_GridRect.top,nRight,
                           m_GridRect.top+m_DefCellSize.cy*m_nNameRow); 		 	  
          nLeft+=m_DefCellSize.cx;nLeft++;nRight++; 
      }
      else{
        nRight+=m_nAbnormal[i];  
        CellRect.SetRect(nLeft,m_GridRect.top,nRight,
                       m_GridRect.top+m_DefCellSize.cy*m_nNameRow); 		 	  
        nLeft+=m_nAbnormal[i];nLeft++;nRight++; 
      } 
      if(i!=(m_nByteNum-1)*8-m_nScrollCol){
         pDC->MoveTo(nRight,m_GridRect.top);  
         pDC->LineTo(nRight,m_GridRect.bottom);
         pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
         pDC->MoveTo(nRight+1,m_GridRect.top);  
         pDC->LineTo(nRight+1,m_GridRect.bottom);
         pDC->SelectObject(pOldPen);
      }
      
      nLen= strBitName[i].GetLength();
      char* pName = strBitName[i].GetBuffer(nLen+1);
      
      if (m_nNameRow==1)
      {
      	pDC->DrawText(pName, nLen,&CellRect,
                    DT_CENTER | DT_VCENTER | DT_SINGLELINE);
      }
      else{ // multiply row
      	int nPart = strBitName[i].Find('_');
   		CellRect.bottom -= m_DefCellSize.cy;
      	if (nPart > 0){
      		pDC->DrawText(pName, nPart, &CellRect, 
      			DT_CENTER | DT_VCENTER | DT_SINGLELINE);               
			CellRect.OffsetRect(0, m_DefCellSize.cy);      		
      		pDC->DrawText(pName+nPart+1, nLen-nPart-1, &CellRect, 
      			DT_CENTER | DT_VCENTER | DT_SINGLELINE);
      	}
      	else{
			CellRect.OffsetRect(0, m_DefCellSize.cy/2);
      		pDC->DrawText(pName, nLen, &CellRect, 
      			DT_CENTER | DT_VCENTER | DT_SINGLELINE);
      		CellRect.OffsetRect(0, m_DefCellSize.cy-m_DefCellSize.cy/2);
      	}
      }
      
      strBitName[i].ReleaseBuffer();                 
      
      CellRect.OffsetRect(0,m_DefCellSize.cy);
      nLen= strBitValue[i].GetLength();
      pDC->DrawText(strBitValue[i].GetBuffer(nLen+1),nLen,&CellRect,
                    DT_CENTER | DT_VCENTER | DT_SINGLELINE);     
      strBitValue[i].ReleaseBuffer();                    
    }                                               
    
    int nSeparate = (m_nNameRow*m_GridRect.bottom + m_GridRect.top)
    				/(m_nNameRow+1);
    				
    pDC->MoveTo(m_GridRect.right, nSeparate);
	pDC->LineTo(m_GridRect.left, nSeparate);
    pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
    pDC->MoveTo(m_GridRect.right, nSeparate+1);
	pDC->LineTo(m_GridRect.left, nSeparate+1);
    pDC->SelectObject(pOldPen);

}

void CFldDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	
	CDialog::OnLButtonDblClk(nFlags, point);      
	
	CRect CellRect(m_GridRect);
	
	CellRect.top += CellRect.Height()*m_nNameRow/(m_nNameRow+1);
	
	if (!CellRect.PtInRect(point)) return;

	int nRight = CellRect.left;	
	for(int i=7+(m_nByteNum-1)*8-m_nScrollCol;i>=1+(m_nByteNum-1)*8-m_nScrollCol;i--)
	{
	  if(m_nAbnormal[i]==0){
	      nRight+=m_DefCellSize.cx;
      }
      else{
        nRight+=m_nAbnormal[i];  
      } 
      if (point.x<=nRight) break;
      nRight++;                  
    }

	if (m_dwRegVal & (1<<i))
	{
		m_dwRegVal &= ~(1<<i);
		strBitValue[i] = '0';
	}
	else
	{
		m_dwRegVal |= (1l<<i);
		strBitValue[i] = '1';
	}
	
	UpdateRegValue();
	
    if (m_nExplain[i] >= 0)
    {             
	    SetDlgList(); 
    	((CListBox*)GetDlgItem(IDC_FIELD_LIST))->SetCurSel(m_nExplain[i]);
    	SetEdit(m_nExplain[i]);
    }          
    else 	InvalidateRect(m_GridRect, TRUE);
}

void CFldDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: Add your message handler code here and/or call default
    if(pScrollBar==(CScrollBar*)GetDlgItem(IDC_PER_NAME_SCROLL))
    {   
    	CScrollBar* pScroll = (CScrollBar*)GetDlgItem(IDC_PER_NAME_SCROLL);
    	int nOldPos, nNewPos;
    	int nMin, nMax;
		
		nOldPos = nNewPos = pScroll->GetScrollPos();    	
		pScroll->GetScrollRange(&nMin, &nMax);
		
    	switch(nSBCode){
    		case SB_LEFT:  
    			nNewPos = nMin;
    			break;		
//    		case SB_ENDSCROLL:
//    			nNewPos = nMax;
//				break;
    		case SB_LINELEFT:
    			if (nNewPos > nMin) nNewPos--;
    			break;
    		case SB_LINERIGHT:         
    			if (nNewPos < nMax) nNewPos++;
    			break;
    		case SB_PAGELEFT:
    			nNewPos = (nNewPos-nMin>8) ? nNewPos-8 : nMin;
    			break;
    		case SB_PAGERIGHT:
    			nNewPos = (nNewPos+8<nMax) ?  nNewPos+8 : nMax;
    			break;
    		case SB_RIGHT:
    			nNewPos = nMax;
    			break;
    		case SB_THUMBPOSITION:
    		case SB_THUMBTRACK:    
    			nNewPos = nPos;
    			break;
    	}
	
		if (nOldPos != nNewPos){  
			pScroll->SetScrollPos(nNewPos);
			
			m_nScrollCol = nNewPos;

			CRect RectGrid = m_GridRect;			
//			InvalidateRect(m_GridRect, TRUE);			
			CaluGridRect();  
			
			RectGrid |= m_GridRect;
			
			RectGrid.InflateRect(10, 2);
			
			
			InvalidateRect(RectGrid, TRUE);  
			
		}
	}                                                          
	
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
