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

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  MYLIST.CPP
//
//  Description:The implementation file of main list 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 "xview.h"
#include "mylist.h" 
#include "flddlg.h" 
#include "listcol.h"  
#include "percore.h"

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

extern HINSTANCE hPerLib;              


/////////////////////////////////////////////////////////////////////////////
// CMyList

CMyList::CMyList(CWnd* parent):CListBox()
{ 
    m_pCloseBmp=new CBitmap;
	m_pOpenBmp=new CBitmap; 
	
	m_bLoadBmp = FALSE;
	   
    CRect rect(1,1,100,100);  
    Create(WS_VSCROLL|WS_HSCROLL|LBS_NOINTEGRALHEIGHT|WS_VISIBLE|\
    	LBS_NOTIFY|WS_CHILD|LBS_OWNERDRAWFIXED,rect, parent, IDC_LIST1); 
    
    HFONT hFont;
    hFont=(HFONT)GetStockObject(ANSI_FIXED_FONT);
    CFont Font; 
    SetFont(Font.FromHandle(hFont));
 
	lpPerCore = new CPerCore(cpuid, hPerLib);
	
    InitList();
    SetHorizontalExtent(1400);          
}      


void CMyList::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
	// all items are of fixed size
	// must use LBS_OWNERDRAWVARIABLE for this to work
	lpMIS->itemHeight = 16;
}
  
void CMyList::DrawLine(CDC *pDC,PERI_DRAWDATA *lpData,CRect rect,BOOL flag)
{   // flag = 0, selected
    
    int nWidth = lpData->Level * PERI_LEVEL_WIDTH;
    rect.left += nWidth;   // offset because of level
    
	if(!(lpData->isBit))   // not bit
	{
		CDC*  pdcMemory=new CDC;
		BITMAP bm;          
		CBitmap *pbmpOld ;
    	pdcMemory->CreateCompatibleDC(pDC);
		
		if(lpData->isExpanded)
		{
	    	m_pOpenBmp->GetObject(sizeof(BITMAP), &bm);
    		pbmpOld =pdcMemory->SelectObject(m_pOpenBmp);
	    	pDC->BitBlt(rect.left+1,rect.top+1,bm.bmWidth,bm.bmHeight,pdcMemory,0,0,SRCCOPY);
			pdcMemory->SelectObject(pbmpOld);
        	pdcMemory->DeleteDC();  
        	delete pdcMemory;
    	}
    	else 
		{
		    m_pCloseBmp->GetObject(sizeof(BITMAP), &bm);
    		pbmpOld =pdcMemory->SelectObject(m_pCloseBmp);
	    	pDC->BitBlt(rect.left+1,rect.top+1,bm.bmWidth,bm.bmHeight,pdcMemory,0,0,SRCCOPY);
			pdcMemory->SelectObject(pbmpOld);
    	    pdcMemory->DeleteDC();
    	    delete pdcMemory;
    	} 
    }
    	
    if(flag)        
    	pDC->SetTextColor(RGB(0,0,255));
    else 	pDC->SetTextColor(RGB(255,255,255));

    if(lpData->isBit)
    {
//   	lpData->Addr[1]=0;
        pDC->TextOut(rect.left+34,rect.top,lpData->Addr);
    }
    else
    {	    
 //   	lpData->Addr[3]=0;
    	pDC->TextOut(rect.left+30,rect.top,lpData->Addr);
    }
 
    if(flag)
		pDC->SetTextColor(RGB(255,0,0));      
	else 		                              
		pDC->SetTextColor(RGB(255,255,255));      
	char text[20]=""; 
	if(lpData->isBit)
	{
		 wsprintf(text,"%X",lpData->dwVal);
	}
	else
	{
	    wsprintf(text, "0X%-8X", lpData->dwVal);
	}		
	pDC->TextOut(rect.left+90,rect.top,text);   
	  
    if(flag)
		pDC->SetTextColor(RGB(0,0,0));      
	else
		pDC->SetTextColor(RGB(255,255,255));	
	
//	char sztemp[256]="";
    char szDesc[256]="";
    
    lpPerCore->GetDescStr(lpData, szDesc);
//    wsprintf(sztemp, "%-10s   %s", lpData->szName, szDesc);
	    
	pDC->TextOut(rect.left+155-nWidth,rect.top,szDesc); 
	if(!flag)                               
		pDC->SetTextColor(RGB(0,0,0));      
		      
}  
  
  
void CMyList::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	PERI_DRAWDATA *lpData=(PERI_DRAWDATA *)(lpDIS->itemData); 
    pDC->SetBkMode(TRANSPARENT);
    CRect rect=lpDIS->rcItem;
//    rect.InflateRect(0,-1);
	if ((lpDIS->itemState & ODS_SELECTED) &&
		(lpDIS->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
	{
		// item has been selected - hilite frame
		COLORREF crHilite = RGB(0,0,255);
		CBrush br(crHilite);
        pDC->FillRect(&lpDIS->rcItem,&br);
		DrawLine(pDC,lpData,rect,0);			
	}

	if (!(lpDIS->itemState & ODS_SELECTED) &&
		(lpDIS->itemAction & ODA_SELECT))
	{
		// Item has been de-selected -- remove frame
		CBrush br(RGB(255,255,255));
        pDC->FillRect(&lpDIS->rcItem,&br);
		DrawLine(pDC,lpData,rect,1);			
	}

	if ( (lpDIS->itemAction & ODA_DRAWENTIRE)&&!(lpDIS->itemState & ODS_SELECTED))
	{
		// Paint the color item in the color requested
		DrawLine(pDC,lpData,rect,1);
	}

}


BOOL CMyList::InitList()
{

    if (!m_bLoadBmp)
    {
    	if(!m_pCloseBmp->LoadBitmap(IDB_VAR_CLOSE_RED)) 
    	{	
    		AfxMessageBox("Can not load Bitmap");
        	return 0;
    	}    
    	if(!m_pOpenBmp->LoadBitmap(IDB_VAR_OPEN_RED))
    	{              
    		AfxMessageBox("Can not load Bitmap");
    		return 0;
    	}
    	m_bLoadBmp = TRUE;
    }
    		
    PERI_DRAWDATA * lpDrawData;  
    WORD wItemRange = lpPerCore->RootItemCount();    

    DWORD dwAllReg[256];
    emuGetAllReg(dwAllReg);
    
    for(WORD wChild=0;wChild<wItemRange; wChild++)
    { 
    	lpDrawData=new PERI_DRAWDATA;

		lpDrawData->BaseID = lpPerCore->RootChildBaseID(wChild);
        lpDrawData->Index = lpPerCore->RegSerialNo(lpDrawData->BaseID);
        lpDrawData->offset = 0; 
        
//        GetRegValue(lpDrawData->Index, lpDrawData->dwVal);
		lpDrawData->dwVal = dwAllReg[lpDrawData->Index]; 
		int nLen;
		
		GetRegLen(lpDrawData->Index, nLen);
		
		switch(nLen){
			case 1:
				lpDrawData->dwVal &= 0xff;
				break;
			case 2:
				lpDrawData->dwVal &= 0xffff;
				break;
		}
		
//        GetRegName(lpDrawData->Index, lpDrawData->szName);
        
        lpDrawData->StringID = lpPerCore->RootChildDescID(wChild);   
        MergeRegAddr(lpDrawData->Index, lpDrawData->Addr);
        
        lpDrawData->Level = 0;
        lpDrawData->isBit=0;
        lpDrawData->isExpanded=0;
        
        AddString((LPSTR)lpDrawData); 
        SetItemDataPtr(wChild, lpDrawData); 
    }
   return 1;                      
}      


CMyList::~CMyList()
{     
	if (m_pCloseBmp)
	{
		m_pCloseBmp->DeleteObject();
		delete m_pCloseBmp;
	}
	
	if (m_pOpenBmp){
		m_pOpenBmp->DeleteObject();
		delete m_pOpenBmp;    
	}
	
	if (lpPerCore) delete lpPerCore;
} 


void CMyList::ResetContent()
{
	PERI_DRAWDATA *lpData;   
	int count;
	count=GetCount();
	while(count>0)
	{
		lpData=(PERI_DRAWDATA*)GetItemDataPtr(count-1);
		delete lpData;
		DeleteString(count-1);                
//		count=GetCount();
		count--;
	}
}

BEGIN_MESSAGE_MAP(CMyList, CListBox)
    //{{AFX_MSG_MAP(CMyList)
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
    ON_WM_LBUTTONUP()   
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyList message handlers

     
void CMyList::OnLButtonUp(UINT nFlags,CPoint point)
{
    CWnd::OnLButtonUp(nFlags,point);

    PERI_DRAWDATA * lpDrawData;  
                                 
    int   cursel=GetCurSel();   
    if(cursel==CB_ERR) return;
    
    lpDrawData=(PERI_DRAWDATA*)GetItemDataPtr(cursel);
    int   nOffset = PERI_LEVEL_WIDTH * lpDrawData->Level;
    
    point.x = point.x - nOffset;
    if((1<point.x) &&(point.x<40))
       { 
         if ( !lpDrawData->isBit )        
            { 
              if(!lpDrawData->isExpanded) 
              { 
             //     DeleteString(cursel);
             //     InsertString(cursel,(LPSTR)lpDrawData);
             //     SetItemDataPtr(cursel,lpDrawData);
	                InsertChildItem(cursel);
                 }
              else
                { 
              //    DeleteString(cursel);
              //    InsertString(cursel,(LPSTR)lpDrawData);
              //    SetItemDataPtr(cursel,lpDrawData);
                  DeleteOffspringItem(cursel);   
                  
                }             
            } 
          SetCurSel(cursel);      
       }
} 



int CMyList::InsertChildItem(int reg_index)
{
    char szBuf[256]="";      
    char *szTemp;
    char *szData;   
    int  nByteFlag;  
    WORD wChildNum; 
    
    PERI_DRAWDATA * lpDrawData;  
                                 
    lpDrawData=(PERI_DRAWDATA*)GetItemDataPtr(reg_index);
    if (lpDrawData->isBit || lpDrawData->isExpanded) return 0;
            
    ::LoadString(hPerLib, lpDrawData->BaseID, szBuf, 255);
    szTemp = szBuf;            
    
    gstrtok(szTemp, ",");  //bypass father base ID
    gstrtok(szTemp, ",");  //bypass register serial number
    szData = gstrtok(szTemp, ",");    
    nByteFlag = atoi(szData);   
    
    szData = gstrtok(szTemp, ",");
    wChildNum = (WORD)atoi(szData);  
    
    if (nByteFlag == 0){   // children are not bit
		WORD  wSpace;    
  	  	WORD  wStartBase;

		szData = gstrtok(szTemp, ",");
    	wSpace = (WORD)atoi(szData);
    
    	szData = gstrtok(szTemp, ",");
    	wStartBase = (WORD)atoi(szData);
    
   		for(WORD i=0; i<wChildNum; i++){
			PERI_DRAWDATA *lpData = new PERI_DRAWDATA;
        	lpData->isBit = 0;
        	lpData->isExpanded = 0;       
        	lpData->BaseID = wStartBase + wSpace * i;
        	
        	lpData->Index = lpPerCore->RegSerialNo(lpData->BaseID);  
        	
        	//GetRegName(lpData->Index, lpData->szName);
        	GetRegValue(lpData->Index,lpData->dwVal); 
        	MergeRegAddr(lpData->Index, lpData->Addr);
         	lpData->offset = (BYTE)(i+1);
        	lpData->Level = lpDrawData->Level;
        	lpData->Level++;  
			
			lpPerCore->GetRegStrID(lpDrawData, lpData);         	 
			
        	reg_index++;
        	InsertString(reg_index,(LPSTR)lpData); 
	        SetItemDataPtr(reg_index,lpData); 
         } 
     }
     else{ // children are bit
		for(WORD i=0; i<wChildNum; i++){
			PERI_DRAWDATA *lpData = new PERI_DRAWDATA;
        	lpData->isBit = 1;
         	lpData->BaseID = lpDrawData->BaseID;      
        	lpData->Index = lpDrawData->Index;   
        	
        	szData = gstrtok(szTemp, ",");  // get bit from and end data
        	
        	WORD wStartBit, wBitLen;
        	RegBitStartLen(szData, wStartBit, wBitLen);
		    lpData->dwVal = lpDrawData->dwVal;
        	lpData->dwVal >>= wStartBit;
        	lpData->dwVal &= ((1<<wBitLen)-1); 
        	
        //	MergeBitName(lpData->Index, (BYTE)wStartBit, (BYTE)(wStartBit+wBitLen-1), 
        //			lpData->szName);
        	strcpy(lpData->Addr, szData);        	
        	lpData->offset = (BYTE)(i+1);
        	lpData->Level = lpDrawData->Level;
        	lpData->Level++;
                
        	szData = gstrtok(szTemp, ","); // get desciption string need merge flag
        	lpData->isExpanded = atoi(szData);
        	
   	       	lpPerCore->GetRegStrID(lpDrawData, lpData);  
   	       	
   	        reg_index++;
   	        InsertString(reg_index,(LPSTR)lpData); 
	        SetItemDataPtr(reg_index,lpData);
         }  
      }           
    lpDrawData->isExpanded = 1;
    return (int)wChildNum;
}                        

int CMyList::InsertOffspringItem(int reg_index)
{
    PERI_DRAWDATA * lpDrawData;  
                                 
    lpDrawData=(PERI_DRAWDATA*)GetItemDataPtr(reg_index);

	if(lpDrawData->isBit) return 0;
	
	int nChild;
	int nCur = reg_index+1;      
	int i;
	if(!lpDrawData->isExpanded){
		nChild = InsertChildItem(reg_index);
	
		for(i=0;i<nChild;i++)
		{
			nCur +=InsertOffspringItem(nCur);
			
			nCur++; // add itself;
		}             
		return nCur-reg_index-1;
	}   
	else{
		int nCount = GetCount();
		if (reg_index >= nCount-1) return 0;
		
		PERI_DRAWDATA* lpData;    
		for(i=reg_index+1; i<nCount; i++){
			lpData = (PERI_DRAWDATA*) GetItemDataPtr(nCur);
			if(lpDrawData->Level >= lpData->Level) break;
			nCur += InsertOffspringItem(nCur);    
			nCur++;
		}             
		return nCur-i;
	}
	
	return lpDrawData->isExpanded ? nCur-i : nCur-reg_index-1;			

}

int CMyList::DeleteOffspringItem(int reg_index)
{      
    PERI_DRAWDATA * lpDrawData;  
                                 
    lpDrawData=(PERI_DRAWDATA*)GetItemDataPtr(reg_index);
    if (!lpDrawData->isExpanded) return 0;
    
    int nCount = GetCount();
    for (int i=reg_index+1; i<nCount; i++)
    {
       PERI_DRAWDATA* lpData;
       lpData=(PERI_DRAWDATA*)GetItemDataPtr(reg_index+1);
       if (lpData->Level <= lpDrawData->Level) 
       		break;
       DeleteString(reg_index+1);  
       delete lpData;
    }                          
    lpDrawData->isExpanded = 0;
    return i-reg_index-1;
}


void CMyList::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	
//	OnLButtonUp(nFlags,point);	 
/*	
	int cursel;
    cursel=GetCurSel(); 

	PERI_DRAWDATA * lpDrawData;  
    
    lpDrawData=(PERI_DRAWDATA*)GetItemDataPtr(cursel);  
   	if (!lpDrawData->isBit){                	
   		if(lpDrawData->isExpanded) 
        { 
                  lpDrawData->isExpanded=0;
                  DeleteOffspringItem(cursel,lpDrawData);
        }        
		MSG msg;
		GetMessage(&msg, m_hWnd, WM_LBUTTONUP, WM_LBUTTONUP); 
		InsertOffspringItem(cursel);
 		return;
 	}
*/                   
    CListBox::OnLButtonDblClk(nFlags, point);

}

void CMyList::OnRButtonDown(UINT, CPoint point)
{
    GetParent()->SendMessage(WM_RBUTTONDOWN,0,MAKELONG(point.x,point.y));
}

BOOL CMyList::CurTopItem(WORD wBaseID, int &index)  
{
	WORD wForeFatherID = wBaseID;
	if ((wForeFatherID=lpPerCore->AncestorBaseID(wBaseID))==WORD(-1))
		return FALSE;
	
	int nCount = GetCount();
	for(index=0; index<nCount; index++)
	{
	   PERI_DRAWDATA* lpData;
       lpData=(PERI_DRAWDATA*)GetItemDataPtr(index);
       if (lpData->BaseID == wForeFatherID)
			return TRUE;
	}
	
	return FALSE;       		
}                                                                 
                                                                   
void CMyList::OnDestroy()
{
	
	// TODO: Add your message handler code here  
	ResetContent();

	CListBox::OnDestroy();
	
}

/***********************end of file*******************************/    
