424 lines
18 KiB
C++
424 lines
18 KiB
C++
#include "StdAfx.h"
|
||
#include <windows.h>
|
||
#include ".\luadebugger.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
||
#endif
|
||
|
||
|
||
// 경고가 싫어. -_-
|
||
#pragma warning( disable : 4311 ) // 4 단계 경고
|
||
#pragma warning( disable : 4312 ) // 4 단계 경고
|
||
|
||
|
||
luaL_reg DebugGlue[];
|
||
|
||
CLuaDebugger *g_Console = NULL;
|
||
|
||
|
||
volatile bool CLuaDebugger::m_bWinIsActive = true;
|
||
volatile HWND CLuaDebugger::m_hWnd = NULL;
|
||
volatile HWND CLuaDebugger::m_hEditControl = NULL;
|
||
|
||
char CLuaDebugger::m_CommandBuffer[4096];
|
||
|
||
WNDPROC lpfnInputEdit; // Storage for subclassed edit control
|
||
//////////////////////////////////////////////////////////////////////
|
||
// Construction/Destruction
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
HWND CLuaDebugger::StartConsole(HINSTANCE hInstance, lua_State *pScriptContext)
|
||
{
|
||
if(!g_Console)
|
||
{
|
||
g_Console = new CLuaDebugger();
|
||
}
|
||
|
||
if(!m_hWnd)
|
||
g_Console->Init(hInstance);
|
||
|
||
g_Console->m_pScriptContext = pScriptContext;
|
||
// init the glue functions required for the debug window
|
||
for(int i=0; DebugGlue[i].name; i++)
|
||
{
|
||
lua_register(g_Console->m_pScriptContext, DebugGlue[i].name, DebugGlue[i].func);
|
||
}
|
||
|
||
return (m_hWnd);
|
||
}
|
||
|
||
void CLuaDebugger::StopConsole()
|
||
{
|
||
if(g_Console)
|
||
{
|
||
delete g_Console;
|
||
g_Console = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
CLuaDebugger::CLuaDebugger()
|
||
{
|
||
m_hWnd = NULL;
|
||
memset(m_CommandBuffer, 0, 4096);
|
||
|
||
}
|
||
|
||
CLuaDebugger::~CLuaDebugger()
|
||
{
|
||
if( m_hWnd )
|
||
{
|
||
CloseWindow(m_hWnd);
|
||
m_hWnd = NULL;
|
||
}
|
||
}
|
||
|
||
void CLuaDebugger::AdjustScrollBar(void)
|
||
{
|
||
SCROLLINFO si;
|
||
|
||
si.cbSize = sizeof(si);
|
||
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||
si.nMin = 0;
|
||
si.nMax = (int)m_stringList.size();
|
||
si.nPage = m_textAreaHeight;
|
||
si.nPos = (int)m_stringList.size() - m_ScrollyPos;
|
||
SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE);
|
||
}
|
||
|
||
|
||
void CLuaDebugger::ResizeControls(void)
|
||
{
|
||
RECT r;
|
||
|
||
GetClientRect(m_hWnd, &r);
|
||
m_textAreaHeight = (r.bottom - r.top) / 16;
|
||
|
||
SetWindowPos(m_hEditControl, HWND_TOP, r.left + 2, r.bottom - 18, r.right - r.left - 4, 16, SWP_NOZORDER);
|
||
|
||
AdjustScrollBar();
|
||
InvalidateRect(m_hWnd, NULL, TRUE);
|
||
}
|
||
|
||
void CLuaDebugger::Paint(HDC hDC)
|
||
{
|
||
SetTextColor(hDC, RGB(255,255,255));
|
||
SetBkColor(hDC, RGB(0,0,0));
|
||
|
||
RECT r;
|
||
|
||
GetClientRect(m_hWnd, &r);
|
||
|
||
int x = 2;
|
||
int y = r.bottom - 40;
|
||
|
||
std::list<std::string>::iterator it = m_stringList.begin();
|
||
int skip = m_ScrollyPos;
|
||
while(skip)
|
||
{
|
||
++it;
|
||
--skip;
|
||
}
|
||
|
||
while(it != m_stringList.end())
|
||
{
|
||
TextOutA(hDC, x, y, (*it).c_str(), (int)strlen((*it).c_str()));
|
||
y -= 16;
|
||
++it;
|
||
}
|
||
}
|
||
|
||
|
||
LRESULT WINAPI CLuaDebugger::MsgProc( HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
PAINTSTRUCT ps;
|
||
HDC hdc;
|
||
|
||
switch (uMsg)
|
||
{
|
||
case WM_ACTIVATEAPP:
|
||
m_bWinIsActive = (wParam != 0);
|
||
return 0L;
|
||
|
||
case WM_ACTIVATE:
|
||
// Pause if minimized or not the top window
|
||
m_bWinIsActive = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE);
|
||
return 0L;
|
||
|
||
case WM_DESTROY:
|
||
m_bWinIsActive = false;
|
||
m_hWnd = NULL;
|
||
break;
|
||
|
||
case WM_PAINT:
|
||
hdc = BeginPaint(hWnd, &ps);
|
||
g_Console->Paint(hdc);
|
||
EndPaint(hWnd, &ps);
|
||
break;
|
||
|
||
case WM_CHAR:
|
||
break;
|
||
|
||
case WM_LBUTTONDOWN:
|
||
break;
|
||
|
||
case WM_RBUTTONDOWN:
|
||
break;
|
||
|
||
case WM_LBUTTONUP:
|
||
break;
|
||
|
||
case WM_RBUTTONUP:
|
||
break;
|
||
|
||
case WM_MOUSEMOVE:
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
break;
|
||
|
||
case WM_SIZING:
|
||
case WM_SIZE:
|
||
g_Console->ResizeControls();
|
||
break;
|
||
|
||
case WM_SETCURSOR:
|
||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||
ShowCursor(TRUE);
|
||
break;
|
||
|
||
case WM_VSCROLL:
|
||
switch(LOWORD (wParam))
|
||
{
|
||
// User clicked the shaft above the scroll box.
|
||
|
||
case SB_PAGEUP:
|
||
g_Console->m_ScrollyPos = min((int) (g_Console->m_ScrollyPos+g_Console->m_textAreaHeight), (int) (g_Console->m_stringList.size() - g_Console->m_textAreaHeight)+1);
|
||
//yInc = min(-1, -yClient / yChar);
|
||
break;
|
||
|
||
// User clicked the shaft below the scroll box.
|
||
|
||
case SB_PAGEDOWN:
|
||
// yInc = max(1, yClient / yChar);
|
||
break;
|
||
|
||
// User clicked the top arrow.
|
||
|
||
case SB_LINEUP:
|
||
g_Console->m_ScrollyPos = min(g_Console->m_ScrollyPos+1, (int) (g_Console->m_stringList.size() - g_Console->m_textAreaHeight)+1);
|
||
break;
|
||
|
||
// User clicked the bottom arrow.
|
||
|
||
case SB_LINEDOWN:
|
||
//yInc = 1;
|
||
g_Console->m_ScrollyPos = max(g_Console->m_ScrollyPos-1, 0);
|
||
break;
|
||
|
||
// User dragged the scroll box.
|
||
|
||
case SB_THUMBTRACK:
|
||
//yInc = HIWORD(wParam) - yPos;
|
||
break;
|
||
|
||
default:
|
||
//yInc = 0;
|
||
break;
|
||
|
||
}
|
||
{
|
||
SCROLLINFO si;
|
||
si.cbSize = sizeof(si);
|
||
si.fMask = SIF_POS;
|
||
si.nPos = (int)g_Console->m_stringList.size() - g_Console->m_ScrollyPos;
|
||
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
|
||
}
|
||
InvalidateRect(m_hWnd, NULL, TRUE);
|
||
|
||
break;
|
||
|
||
case WM_USER:
|
||
// command ready from edit control
|
||
// string should be in m_CommandBuffer
|
||
Write(m_CommandBuffer);
|
||
if (0 != luaL_loadbuffer(g_Console->m_pScriptContext, m_CommandBuffer, strlen(m_CommandBuffer), NULL))
|
||
{
|
||
Write("Error loading Command\n");
|
||
}
|
||
if (0 != lua_pcall(g_Console->m_pScriptContext, 0, LUA_MULTRET, 0))
|
||
{
|
||
Write("Error in Command\n");
|
||
Write(luaL_checkstring(g_Console->m_pScriptContext, -1));
|
||
}
|
||
// clear buffer when done processing
|
||
memset(m_CommandBuffer, 0, 4096);
|
||
break;
|
||
}
|
||
|
||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||
}
|
||
|
||
|
||
void CLuaDebugger::Write(const char *pString)
|
||
{
|
||
if(g_Console)
|
||
{
|
||
if(m_hWnd)
|
||
{
|
||
//remove any linefeed chars (look goofy in log)
|
||
char *buf = new char[strlen(pString)+1];
|
||
int indx=0;
|
||
for(int i=0; i<(int) strlen(pString); i++)
|
||
{
|
||
if(pString[i] != 10)
|
||
{
|
||
buf[indx++] = pString[i];
|
||
}
|
||
else
|
||
{
|
||
buf[indx] = 0;
|
||
g_Console->m_stringList.push_front(buf);
|
||
indx = 0;
|
||
}
|
||
|
||
|
||
}
|
||
if(indx > 0)
|
||
{
|
||
buf[indx] = 0;
|
||
g_Console->m_stringList.push_front(buf);
|
||
}
|
||
InvalidateRect(m_hWnd, NULL, TRUE);
|
||
delete [] buf;
|
||
}
|
||
g_Console->AdjustScrollBar();
|
||
}
|
||
}
|
||
|
||
|
||
LRESULT CALLBACK CLuaDebugger::SubclassInputEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch(message)
|
||
{
|
||
case WM_CHAR: // Found a RETURN keystroke!
|
||
if ((TCHAR) wParam == VK_RETURN)
|
||
{
|
||
// get the command string
|
||
long lSizeofString;
|
||
// Get the size of the string
|
||
lSizeofString = (long)SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);
|
||
|
||
// Get the string
|
||
SendMessage(hWnd, WM_GETTEXT, lSizeofString + 1, (LPARAM) m_CommandBuffer);
|
||
|
||
// send message to parent that command was entered
|
||
SendMessage(m_hWnd, WM_USER, 0, lSizeofString);
|
||
|
||
// clear the edit string
|
||
SendMessage(hWnd, WM_SETTEXT, 0, (long)"");
|
||
return 1;
|
||
}
|
||
}
|
||
return CallWindowProc(lpfnInputEdit, hWnd, message, wParam, lParam);
|
||
}
|
||
|
||
void CLuaDebugger::Init(HINSTANCE hInstance)
|
||
{
|
||
m_hInstance = hInstance;
|
||
m_ScrollyPos = 0;
|
||
// create application handler and link to our WindowProc
|
||
WNDCLASSA wc;
|
||
|
||
// Set up and register window class
|
||
wc.style = 0;
|
||
wc.lpfnWndProc = (WNDPROC) MsgProc;
|
||
wc.cbClsExtra = 0;
|
||
wc.cbWndExtra = sizeof(DWORD);
|
||
wc.hInstance = m_hInstance;
|
||
wc.hIcon = NULL;
|
||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
|
||
wc.lpszMenuName = NULL;
|
||
wc.lpszClassName = "Debugger";
|
||
#if 0
|
||
if (!RegisterClass(&wc))
|
||
ThrowError();
|
||
#else
|
||
RegisterClassA(&wc);
|
||
#endif
|
||
|
||
m_hWnd = CreateWindowA("Debugger", // class
|
||
"LUA Debugger", // caption
|
||
WS_OVERLAPPEDWINDOW, // style
|
||
0, // left
|
||
0, // top
|
||
640, // width
|
||
480, // height
|
||
NULL, // parent window
|
||
NULL, // menu
|
||
m_hInstance, // instance
|
||
NULL); // parms
|
||
|
||
ShowWindow(m_hWnd, SW_SHOW);
|
||
UpdateWindow(m_hWnd);
|
||
SetFocus(m_hWnd);
|
||
|
||
m_hEditControl = CreateWindowA("EDIT", // class
|
||
"", // caption
|
||
ES_LEFT | WS_CHILD, // style
|
||
2, // left
|
||
404, // top
|
||
228, // width
|
||
16, // height
|
||
m_hWnd, // parent window
|
||
(HMENU)0xa7, // menu
|
||
m_hInstance, // instance
|
||
NULL); // parms
|
||
|
||
ShowWindow(m_hEditControl, SW_SHOW);
|
||
UpdateWindow(m_hEditControl);
|
||
SetFocus(m_hEditControl);
|
||
m_ScrollyPos = 0;
|
||
|
||
#if defined(WIN64)
|
||
lpfnInputEdit = (WNDPROC) SetWindowLong(m_hEditControl, GWLP_WNDPROC, (long) SubclassInputEditProc);
|
||
#else
|
||
lpfnInputEdit = (WNDPROC) SetWindowLong(m_hEditControl, GWL_WNDPROC, (long) SubclassInputEditProc);
|
||
#endif
|
||
g_Console->ResizeControls();
|
||
|
||
|
||
}
|
||
|
||
static int Debug_Print(lua_State *L)
|
||
{
|
||
#ifdef _DEBUG
|
||
int n = lua_gettop(L); /* number of arguments */
|
||
int i;
|
||
lua_getglobal(L, "tostring");
|
||
for (i=1; i<=n; i++) {
|
||
const char *s;
|
||
lua_pushvalue(L, -1); /* function to be called */
|
||
lua_pushvalue(L, i); /* value to print */
|
||
lua_call(L, 1, 1);
|
||
s = lua_tostring(L, -1); /* get result */
|
||
if (s == NULL)
|
||
return luaL_error(L, "`tostring' must return a string to `print'");
|
||
if (i>1) CLuaDebugger::Write("\t");
|
||
CLuaDebugger::Write(s);
|
||
lua_pop(L, 1); /* pop result */
|
||
}
|
||
CLuaDebugger::Write("\n");
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
luaL_reg DebugGlue[] =
|
||
{
|
||
{"Print", Debug_Print},
|
||
{"print", Debug_Print},
|
||
|
||
{NULL, NULL}
|
||
};
|