#include "StdAfx.h" #include "Console.h" #include #include "Network/PacketBuilder.h" Console* g_pkConsole = NULL; ConsoleFunc* g_pConsoleFuncHead = NULL; bool Console::m_bPrint = false; ConsoleFunc::ConsoleFunc(const char* pName, ConsoleCallBack pCB):pcb(pCB) { pszName = pName; pNext = g_pConsoleFuncHead; g_pConsoleFuncHead = this; } void InitConfoleFunc() { ConsoleFunc* pFunc = g_pConsoleFuncHead; while (pFunc) { // MAP INSERT. g_pkConsole->InsertFunc(pFunc); pFunc = pFunc->pNext; } } void Console::Create() { g_pkConsole = new Console(); InitConfoleFunc(); } void Console::Destroy() { delete g_pkConsole; g_pkConsole = NULL; } void Console::Enable(bool enabled) { m_bConsoleEnabled = enabled; if(m_bConsoleEnabled) { AllocConsole(); stdOut = GetStdHandle(STD_OUTPUT_HANDLE); stdIn = GetStdHandle(STD_INPUT_HANDLE); stdErr = GetStdHandle(STD_ERROR_HANDLE); } } bool Console::IsEnabled() { if(g_pkConsole) return g_pkConsole->m_bConsoleEnabled; return false; } void Console::InsertFunc(ConsoleFunc* pFunc) { const std::string strName = pFunc->pszName; ConsoleCallBack pCB = pFunc->pcb; m_FunMap.insert(std::make_pair(strName, pCB)); } Console::Console() { //for(signed int iIndex = 0; iIndex < MAX_CMDS; iIndex ++) // rgCmds[iIndex][0] = '\0'; //m_siCmdIndex = 0; m_bConsoleEnabled = false; m_InPos = 0; } Console::~Console() { } void Console::Printf(int id, const char*s, ...) { if (id == 367) { // Get the line into a buffer. static const int BufSize = 4096; static char buffer[4096]; DWORD bytes; va_list args; va_start(args, s); signed int len = vsnprintf(buffer, BufSize, s, args); // null-terminate if overflow. if (len < 0 || len >= BufSize) { if (BufSize > 0) buffer[BufSize-1] = '\0'; } // Replace tabs with carats, like the "real" console does. char *pos = buffer; while (*pos) { if (*pos == '\t') { *pos = '^'; } pos++; } // Print it. OVERLAPPED overlap; WriteFile(stdOut, buffer, strlen(buffer), &bytes, &overlap); FlushFileBuffers(stdOut); } } void Console::Printf(const char *s, ...) { m_bPrint = false; if (!m_bPrint) return; // Get the line into a buffer. static const int BufSize = 4096; static char buffer[4096]; DWORD bytes; va_list args; va_start(args, s); signed int len = vsnprintf(buffer, BufSize, s, args); // null-terminate if overflow. if (len < 0 || len >= BufSize) { if (BufSize > 0) buffer[BufSize-1] = '\0'; } // Replace tabs with carats, like the "real" console does. char *pos = buffer; while (*pos) { if (*pos == '\t') { *pos = '^'; } pos++; } // Print it. OVERLAPPED overlap; WriteFile(stdOut, buffer, strlen(buffer), &bytes, &overlap); FlushFileBuffers(stdOut); } void Console::ProcessConsoleLine(const char *consoleLine) { if(m_bConsoleEnabled) { m_Inbuf[m_InPos] = 0; Printf("%s\n", consoleLine); } } void Console::Process() { if(m_bConsoleEnabled) { DWORD numEvents; GetNumberOfConsoleInputEvents(stdIn, &numEvents); if(numEvents) { INPUT_RECORD rec[20]; char outbuf[512]; signed int outpos = 0; char szInputStr[255] = {0}; ReadConsoleInput(stdIn, rec, 20, &numEvents); DWORD i; for(i = 0; i < numEvents; i++) { if(rec[i].EventType == KEY_EVENT) { KEY_EVENT_RECORD *ke = &(rec[i].Event.KeyEvent); if(ke->uChar.AsciiChar == 0) continue; if(ke->bKeyDown) { switch (ke->uChar.AsciiChar) { case '\b': if(m_InPos > 0) { outbuf[outpos++] = '\b'; outbuf[outpos++] = ' '; outbuf[outpos++] = '\b'; m_InPos--; } break; case '\n': case '\r': { outbuf[outpos++] = '\r'; outbuf[outpos++] = '\n'; m_Inbuf[m_InPos] = 0; outbuf[outpos] = 0; Printf("%s", outbuf); std::string strCmd = m_Inbuf; //strCmd = strCmd.substr(0, m_InPos); int fBlankPos = strCmd.find_first_of(" "); std::string strFunName = strCmd.substr(0, fBlankPos); std::map::iterator itor = m_FunMap.find(strFunName); if(itor != m_FunMap.end()) { std::string sArgs; std::vector vArgs; vArgs.clear(); while(fBlankPos != -1) { int lastBlankPos = fBlankPos; fBlankPos = strCmd.find_first_of(" ", fBlankPos + 1); sArgs = strCmd.substr(lastBlankPos + 1, fBlankPos - lastBlankPos - 1); if(strcmp(sArgs.c_str(), "") != 0) vArgs.push_back(sArgs); } (*itor->second)(vArgs); } //// If we have gone off the end of our array, wrap //// back to the beginning //if (m_siCmdIndex >= MAX_CMDS) // m_siCmdIndex %= MAX_CMDS; //// Put the new command into the array //strcpy(rgCmds[m_siCmdIndex ++], m_Inbuf); m_InPos = outpos = 0; } break; default: m_Inbuf[m_InPos++] = ke->uChar.AsciiChar; outbuf[outpos++] = ke->uChar.AsciiChar; break; } } } } if(outpos) { outbuf[outpos] = 0; Printf("%s", outbuf); } } } }