#include "StdAfx.h" #include #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::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} };