/************************************************************************\
 * File Version Information
 * $Header: /Altair32v2/windbg_reg.c 26    11/08/06 9:22p Racini $
 ************************************************************************/
/************************************************************************\
  MITS Altair Emulator
  Debugger register window
  
  Main debugger support for the Solace Sol-20 emulator
  Copyright (c) Jim Battle, 2000, 2001

  Modifications for the Altair32 Emulator
  Copyright (c) 2001-2006 Richard A. Cini


Change Log:
  2001/11/07  RAC -- Initial changes
  2001/12/14  RAC -- RELEASE MARKER -- v2.1
  2002/01/02  RAC -- Synched with Solace 3.0
  2002/01/31  RAC -- RELEASE MARKER -- v2.2
  2002/07/07  RAC -- RELEASE MARKER -- v2.3
  2002/08/23  RAC -- RELEASE MARKER -- v2.30.10
  2002/11/15  RAC -- RELEASE MARKER -- v2.40.2100
  2003/04/26  RAC -- RELEASE MARKER -- v2.50.2045
  2004/01/20  RAC -- Diff'ed changes from FJS (Fred J. Scipione)
  2004/07/30  RAC -- RELEASE MARKER -- v3.00.0135
  2006/05/12  RAC -- RELEASE MARKER -- v3.10.0200
  2006/11/15  RAC -- RELEASE MARKER -- v3.20.0400
\************************************************************************/
#include <windows.h>
#include <windowsx.h>	// message cracker macros
#include <stdlib.h>
#include <stdio.h>		// C-lib - I/O 
#include <string.h>
#include "altair32.h"
#include "windbg.h"
#include "windbg_sub.h"
#include "extensions.h" // corrections for bad functions in windowsx


static struct tagREGSTATE {
    int win_x;		// width of display, in pixels
    int win_y;		// height of display, in pixels
    int chars_x;	// width of display, in characters
    int chars_y;	// height of display, in characters
    // FIXME:
    //   in time, we could store the value of the regs from the last
    //   time we updated and use this information to print the
    //   differing register colors in red.
} regstate;

static BOOL
OnCreateReg(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    return TRUE;
}

// handle window resize events
static void
OnSizeReg(HWND hwnd, UINT state, int cx, int cy)
{
    regstate.win_x = cx;
    regstate.win_y = cy;

    regstate.chars_x = (cx + dbgstate.fix_x - 1) / dbgstate.fix_x;
    regstate.chars_y = (cy + dbgstate.fix_y - 1) / dbgstate.fix_y;
}

static void
OnPaintReg(HWND hwnd)
{
    const int xoff = 3;	// how many pixels from left edge of window
    PAINTSTRUCT	ps;
    HDC hdc;
    char buf[80];
    int saved, len;

    hdc = BeginPaint(hwnd, &ps);
    saved = SaveDC(hdc);

    if (!dbgstate.active) {

	// gray out the surface
	GrayOutWindow(hwnd, hdc);

    } else {

	// in order to reduce flashing on single step operation, when
	// we create the window we tell windows not to automatically
	// erase invalidated regions to the background color.  instead,
	// we just draw opaque text.  however, we have to be careful to
	// erase the border too.  that is what we do here.
	// erase strip down the left, bottom, right sides.
	// all the sprintf()'s below format strings 13 chars wide.
	COLORREF bg = RGB(0xFF, 0xFF, 0xFF);
	HBRUSH hBrush = CreateSolidBrush(bg);
	HPEN hPen     = CreatePen(PS_SOLID, 1, bg);
	SelectObject(hdc, hBrush);
	SelectObject(hdc, hPen);
	Rectangle(hdc, 0,0, xoff, regstate.win_y);	// L,T,R,B
	Rectangle(hdc, xoff, 7*dbgstate.fix_y, regstate.win_x, regstate.win_y);
	Rectangle(hdc, xoff + 13*dbgstate.fix_x, 0, regstate.win_x, regstate.win_y);
	DeleteObject(hBrush);
	DeleteObject(hPen);

	SelectFont(hdc, dbgstate.fixed_font);

	len = sprintf(buf, " A=%02X=%03d    ", I80Regs.nAF.B.h, I80Regs.nAF.B.h);
	TextOut(hdc, xoff, 0, buf, len);

	len = sprintf(buf, " F=%02X=%c%c%c%c%c%c ",
			  I80Regs.nAF.B.l,
			((I80Regs.nAF.B.l) & 0x80) ? 'S' : ' ',
			((I80Regs.nAF.B.l) & 0x40) ? 'Z' : ' ',
			((I80Regs.nAF.B.l) & 0x10) ? 'H' : ' ',
			((I80Regs.nAF.B.l) & 0x04) ? 'P' : ' ',
			((I80Regs.nAF.B.l) & 0x02) ? 'N' : ' ',
			((I80Regs.nAF.B.l) & 0x01) ? 'C' : ' '
		    );
	TextOut(hdc, xoff, 1*dbgstate.fix_y, buf, len);

	len = sprintf(buf, "BC=%04X=%5d", I80Regs.nBC.W, I80Regs.nBC.W);
	TextOut(hdc, xoff, 2*dbgstate.fix_y, buf, len);
	
	len = sprintf(buf, "DE=%04X=%5d", I80Regs.nDE.W, I80Regs.nDE.W);
	TextOut(hdc, xoff, 3*dbgstate.fix_y, buf, len);

	len = sprintf(buf, "HL=%04X=%5d", I80Regs.nHL.W, I80Regs.nHL.W);
	TextOut(hdc, xoff, 4*dbgstate.fix_y, buf, len);

	len = sprintf(buf, "SP=%04X      ", I80Regs.nSP.W);
	TextOut(hdc, xoff, 5*dbgstate.fix_y, buf, len);
	
	len = sprintf(buf, "PC=%04X      ", I80Regs.nPC.W);
	TextOut(hdc, xoff, 6*dbgstate.fix_y, buf, len);
	
//	len = sprintf(buf, "TICK=%08X", (long)0);	// FIXME
//	TextOut(hdc, xoff, 7*dbgstate.fix_y, buf, len);
    }

    RestoreDC(hdc, saved);
    EndPaint(hwnd, &ps);
}

static void
OnDestroyReg(HWND hwnd)
{
    dbgstate.hRegWnd = NULL;
}

// main window handler
static LRESULT CALLBACK
WndProcReg(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    switch (iMsg) {
	HANDLE_MSG(hWnd, WM_CREATE,  OnCreateReg);
	HANDLE_MSG(hWnd, WM_SIZE,    OnSizeReg);
	HANDLE_MSG(hWnd, WM_PAINT,   OnPaintReg);
	HANDLE_MSG(hWnd, WM_DESTROY, OnDestroyReg);
    }

    return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

void
RegisterRegClass(void)
{
    WNDCLASSEX  wndclass;

    wndclass.cbSize        = sizeof(wndclass);
    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wndclass.lpfnWndProc   = WndProcReg;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = winstate.hInst;
    wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = NULL; // (HBRUSH)(COLOR_WINDOW + 1); don't auto erase background
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = "solacereg";
    wndclass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&wndclass);
}

HWND
CreateRegWindow(HWND hwnd)
{
    DWORD winstyle = WS_CHILD | WS_VISIBLE;
#if 1
    DWORD extstyle = WS_EX_CLIENTEDGE;
#else
    // non-editable windows are supposed to have this style,
    // but it doesn't look right to me
    DWORD extstyle = WS_EX_STATICEDGE;
#endif
    HWND  hwndreg;

    hwndreg = CreateWindowEx(
		extstyle,		// extended style
		"solacereg",		// window class name
		0,			// window caption
		winstyle,		// window style
		0,0,			// initial x,y position
		0,0,			// initial x,y size
		hwnd,			// parent window handle
		NULL,			// window menu handle
		winstate.hInst,		// program instance handle
		NULL);			// creation parameters

    ASSERT(hwndreg != NULL);

    return hwndreg;
}

/* end of file: windbg_reg.c */
