/*
	WinSTon

	Debugger Tab Control

	To make it easy to view any part of the WinSTon state we have a 'Tab' control
	which we can page between. Unfortunately Tab Controls are a total pain under
	Windows but they are very suited for the debugger we wish to implement.
	To keep things simple, all dialog items are added in the Resource editor
	and then we turn each 'page' of item on/off when we click the tabs. This saves
	us having to handle child windows and all that nonsense.
*/

#include "..\includes\winston.h"
#include "..\includes\debug.h"
#include "..\includes\debugger.h"
#include "..\includes\debuggertab.h"
#include "..\includes\debuggertabmemory.h"
#include "..\includes\debuggertabvideo.h"
#include "..\includes\debuggertabikbd.h"
#include "..\includes\debuggertabmfp.h"
#include "..\includes\debuggertabfdc.h"
#include "..\includes\debuggertabpsg.h"
#include "..\includes\debuggertabhistory.h"

#ifdef USE_DEBUGGER

int nCurrentTab;										// DEBUGTAB_xxxx current tab page open

//-----------------------------------------------------------------------
/*
	Init Tab Control in Debugger
*/
void Debugger_Tab_Init(HWND hWnd)
{
	// Create 'tabs'
	Debugger_Tab_AddTab(hWnd,"Memory",0);
	Debugger_Tab_AddTab(hWnd,"Video",1);
	Debugger_Tab_AddTab(hWnd,"IKBD",2);
	Debugger_Tab_AddTab(hWnd,"MFP",3);
	Debugger_Tab_AddTab(hWnd,"FDC",4);
	Debugger_Tab_AddTab(hWnd,"PSG",5);
	Debugger_Tab_AddTab(hWnd,"History",6);

	// Init each section
	Debugger_TabMemory_Init(hWnd);
	Debugger_TabVideo_Init(hWnd);
	Debugger_TabIKBD_Init(hWnd);
	Debugger_TabMFP_Init(hWnd);
	Debugger_TabFDC_Init(hWnd);
	Debugger_TabPSG_Init(hWnd);
	Debugger_TabHistory_Init(hWnd);

	Debugger_Tab_ShowTab(hWnd,DEBUGTAB_MEMORY);
}

//-----------------------------------------------------------------------
/*
	Add 'Tab' button to tab control in Debugger
*/
void Debugger_Tab_AddTab(HWND hWnd,char *pszString,int Index)
{
	TCITEM TcItem;

	// Add 'Tab' item
	TcItem.mask = TCIF_TEXT;
	TcItem.dwState = 0;
	TcItem.dwStateMask = 0;
	TcItem.pszText = pszString;
	TcItem.cchTextMax = 0;
	TcItem.iImage = 0;
	TcItem.lParam = 0;

	TabCtrl_InsertItem(GetDlgItem(hWnd,IDC_DEBUG_TAB), Index,&TcItem);
}

//-----------------------------------------------------------------------
/*
	Show 'Tab' window, pass DEBUGTAB_xxx index
*/
void Debugger_Tab_ShowTab(HWND hWnd,int Index)
{
	// Hide/Show all Tabs
	Debugger_TabMemory_ShowPage(hWnd,Index==DEBUGTAB_MEMORY ? TRUE:FALSE);
	Debugger_TabVideo_ShowPage(hWnd,Index==DEBUGTAB_VIDEO ? TRUE:FALSE);
	Debugger_TabIKBD_ShowPage(hWnd,Index==DEBUGTAB_IKBD ? TRUE:FALSE);
	Debugger_TabMFP_ShowPage(hWnd,Index==DEBUGTAB_MFP ? TRUE:FALSE);
	Debugger_TabFDC_ShowPage(hWnd,Index==DEBUGTAB_FDC ? TRUE:FALSE);
	Debugger_TabPSG_ShowPage(hWnd,Index==DEBUGTAB_PSG ? TRUE:FALSE);
	Debugger_TabHistory_ShowPage(hWnd,Index==DEBUGTAB_HISTORY ? TRUE:FALSE);

	// Store index for updates etc...
	nCurrentTab = Index;
}

//-----------------------------------------------------------------------
/*
	Update current 'Tab' window
*/
void Debugger_Tab_Update(HWND hWnd)
{
	// Update all Tab windows
	Debugger_TabMemory_UpdateDisplay(hWnd);
	Debugger_TabVideo_UpdateDisplay(hWnd);
	Debugger_TabIKBD_UpdateDisplay(hWnd);
	Debugger_TabMFP_UpdateDisplay(hWnd);
	Debugger_TabFDC_UpdateDisplay(hWnd);
	Debugger_TabPSG_UpdateDisplay(hWnd);
	Debugger_TabHistory_UpdateDisplay(hWnd);
}

//-----------------------------------------------------------------------
/*
	Find length of string up until '0' or 'tab'
*/
int Debugger_Tab_GetTabString(char *pString,int Index,int nStringChars)
{
	// Scan to end to tab
	while( (Index<nStringChars) && !((pString[Index]=='\0') || (pString[Index]=='\t')) )
		Index++;

	return Index;
}

//-----------------------------------------------------------------------
/*
	Draw 'Tabbed' TextOut
*/
void Debugger_Tab_TabbedTextOut(HDC hDC,int x,int y,char *pString,int nStringChars,int *pBoxTabs)
{
	int i=0,j=0,nChars;

	while(i<nStringChars) {
		nChars = Debugger_Tab_GetTabString(pString,i,nStringChars);
		if (pString[i]==CHAR_CURSOR)
			DrawIcon(hDC,x+pBoxTabs[j],y+2,CursorIcon);
		else if (pString[i]==CHAR_BREAKPOINT)
			DrawIcon(hDC,x+pBoxTabs[j],y+2,RedDotIcon);
		else
			TextOut(hDC,x+pBoxTabs[j],y+1,&pString[i],nChars-i);
		i = nChars+1;
		j++;
	}
}

//-----------------------------------------------------------------------
/*
	Draw Tab List View items
*/
void Debugger_Tab_DrawListViewStrings(DRAWITEMSTRUCT *pDrawItem,char **pszStrings,int **pszTabs,int nStrings,int y)
{
	HRGN ClippingRegion,LineClippingRegion;
	HBRUSH hBackBrush,hHiLightBrush;
	RECT ClipRect;
	int ColumnWidth;
	int i;

	// Are we trying to draw to item in clipping rectangle?
	if (((pDrawItem->rcItem.top-LISTVIEW_START_Y)/LISTVIEW_ITEMHEIGHT)!=y)
		return;											// No, ignore as will be clipping anyway

	// Create brushes needed
	hBackBrush = CreateSolidBrush(ListView_GetBkColor(pDrawItem->hwndItem));
	hHiLightBrush = GetSysColorBrush(2);

	// Create clipping region, as we need to clear the whole line and then draw each column
	LineClippingRegion = CreateRectRgnIndirect(&pDrawItem->rcItem);
	SelectClipRgn(pDrawItem->hDC,NULL);
	SelectClipRgn(pDrawItem->hDC,LineClippingRegion);

	// Clear background(or set hi-light)
	GetWindowRect(pDrawItem->hwndItem,&ClipRect);
	ClipRect.left = 0;
	ClipRect.top = LISTVIEW_START_Y+(y*LISTVIEW_ITEMHEIGHT);
	ClipRect.bottom = ClipRect.top+LISTVIEW_ITEMHEIGHT;

	if (pDrawItem->itemState&ODS_SELECTED) {
		FillRect(pDrawItem->hDC,&ClipRect,hHiLightBrush);
		SetTextColor(pDrawItem->hDC,RGB(255,255,255));
	}
	else {
		FillRect(pDrawItem->hDC,&ClipRect,hBackBrush);
		SetTextColor(pDrawItem->hDC,ListView_GetTextColor(pDrawItem->hwndItem));
	}

	// Work form left column
	ClipRect.left = 0;
	for(i=0; i<nStrings; i++) {
		// Find width, so can clip to this
		ColumnWidth = ListView_GetColumnWidth(pDrawItem->hwndItem,i);

		// Create clipping region
		ClipRect.top = pDrawItem->rcItem.top;
		ClipRect.right = ClipRect.left+ColumnWidth;
		ClipRect.bottom = pDrawItem->rcItem.bottom;
		ClippingRegion = CreateRectRgnIndirect(&ClipRect);
		SelectClipRgn(pDrawItem->hDC,ClippingRegion);

		// Draw text
		Debugger_Tab_TabbedTextOut(pDrawItem->hDC,ClipRect.left,LISTVIEW_START_Y+(y*LISTVIEW_ITEMHEIGHT),*pszStrings,strlen(*pszStrings),*pszTabs);

		// Cleanup
		DeleteObject(ClippingRegion);

		// Ready for next column
		ClipRect.left += ColumnWidth;
		pszStrings++;
		pszTabs++;
	}

	// Free brushes
	DeleteObject(hBackBrush);

	// Reset clipping region
	SelectClipRgn(pDrawItem->hDC,NULL);
	SelectClipRgn(pDrawItem->hDC,LineClippingRegion);
	DeleteObject(LineClippingRegion);
}

#endif	//USE_DEBUGGER
