diff --git a/Source/Core/Common/Src/ConsoleListener.cpp b/Source/Core/Common/Src/ConsoleListener.cpp index 163bcdefb0..7da35eefd5 100644 --- a/Source/Core/Common/Src/ConsoleListener.cpp +++ b/Source/Core/Common/Src/ConsoleListener.cpp @@ -57,23 +57,12 @@ void ConsoleListener::Open(int Width, int Height, const char *Title) #ifdef _WIN32 // Open the console window and create the window handle for GetStdHandle() AllocConsole(); - // Save the window handle that AllocConsole() created hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - // Set the console window title SetConsoleTitle(Title); - - // Set the total letter space to MAX_BYTES - int LWidth = Width / 8; - int LBufHeight = floor((float)(MAX_BYTES / (LWidth + 1))); - COORD co = {LWidth, LBufHeight}; - SetConsoleScreenBufferSize(hConsole, co); - - /* Set the window size in number of letters. The height is hard coded here - because it can be changed with MoveWindow() later */ - SMALL_RECT coo = {0,0, (LWidth - 1), 50}; // Top, left, right, bottom - SetConsoleWindowInfo(hConsole, TRUE, &coo); + // Set letter space + LetterSpace(80, 4000); #endif } @@ -104,68 +93,175 @@ bool ConsoleListener::IsOpen() //////////////////////////////////////////////////////////////////////////////////////////////////////// // Size // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +/* +Short documentation: + LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are dependent on each other, that's the + reason for the additional checks. +*/ +void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) +{ +#ifdef _WIN32 + bool SB, SW; + + if (BufferFirst) + { + // Change screen buffer size + COORD Co = {BufferWidth, BufferHeight}; + SB = SetConsoleScreenBufferSize(hConsole, Co); + // Change the screen buffer window size + SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom + SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); + } + else + { + // Change the screen buffer window size + SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom + SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); + // Change screen buffer size + COORD Co = {BufferWidth, BufferHeight}; + SB = SetConsoleScreenBufferSize(hConsole, Co); + } +#endif +} void ConsoleListener::LetterSpace(int Width, int Height) { #ifdef _WIN32 - // Get console info CONSOLE_SCREEN_BUFFER_INFO ConInfo; GetConsoleScreenBufferInfo(hConsole, &ConInfo); - // Change the screen buffer window size - SMALL_RECT coo = {0,0, Width, Height}; // top, left, right, bottom - bool SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); + // + int OldBufferWidth = ConInfo.dwSize.X; + int OldBufferHeight = ConInfo.dwSize.Y; + int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left); + int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top); + // + int NewBufferWidth = Width; + int NewBufferHeight = Height; + int NewScreenWidth = NewBufferWidth - 1; + int NewScreenHeight = OldScreenHeight; - // Change screen buffer to the screen buffer window size - COORD Co = {Width + 1, Height + 1}; - bool SB = SetConsoleScreenBufferSize(hConsole, Co); + // Width + BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1)); + // Height + BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1)); // Resize the window too - MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(Height*12 + 50), true); - - // Logging - //printf("LetterSpace(): L:%i T:%i Iconic:%i\n", ConsoleLeft, ConsoleTop, ConsoleIconic); + //MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true); #endif } +#ifdef _WIN32 +COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth) +{ + COORD Ret = {0, 0}; + // Full rows + int Step = floor((float)BytesRead / (float)BufferWidth); + Ret.Y += Step; + // Partial row + Ret.X = BytesRead - (BufferWidth * Step); + return Ret; +} +#endif void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize) { #ifdef _WIN32 // Check size if (Width < 8 || Height < 12) return; + bool DBef = true; + bool DAft = true; + std::string SLog = ""; + + HWND hWnd = GetConsoleWindow(); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + // Get console info CONSOLE_SCREEN_BUFFER_INFO ConInfo; GetConsoleScreenBufferInfo(hConsole, &ConInfo); - // Letter space - int LWidth = floor((float)(Width / 8)); - int LHeight = floor((float)(Height / 12)); - int LBufHeight = floor((float)(MAX_BYTES / (LWidth + 1))); + DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y; - // Check size - DWORD dwConSize = ConInfo.dwSize.X * ConInfo.dwSize.Y; - if (dwConSize > MAX_BYTES) return; - // Read the current text - char Str[MAX_BYTES]; + // --------------------------------------------------------------------- + // Save the current text + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ DWORD cCharsRead = 0; COORD coordScreen = { 0, 0 }; - ReadConsoleOutputCharacter(hConsole, Str, dwConSize, coordScreen, &cCharsRead); - // Change the screen buffer window size - SMALL_RECT coo = {0,0, LWidth, LHeight}; // top, left, right, bottom - bool bW = SetConsoleWindowInfo(hConsole, TRUE, &coo); - // Change screen buffer to the screen buffer window size - COORD Co = {LWidth + 1, LBufHeight}; - bool bB = SetConsoleScreenBufferSize(hConsole, Co); + std::vector Str; + std::vector Attr; + // ReadConsoleOutputAttribute seems to have a limit at this level + const int MAX_BYTES = 1024 * 16; + int ReadBufferSize = MAX_BYTES - 32; + DWORD cAttrRead = ReadBufferSize; + int BytesRead = 0; + int i = 0; + int LastAttrRead = 0; + while(BytesRead < BufferSize) + { + Str.push_back(new char[MAX_BYTES]); + if (!ReadConsoleOutputCharacter(hConsole, Str[i], ReadBufferSize, coordScreen, &cCharsRead)) + SLog += StringFromFormat("WriteConsoleOutputCharacter error"); + Attr.push_back(new WORD[MAX_BYTES]); + if (!ReadConsoleOutputAttribute(hConsole, Attr[i], ReadBufferSize, coordScreen, &cAttrRead)) + SLog += StringFromFormat("WriteConsoleOutputAttribute error"); - // Redraw the text + // Break on error + if (cAttrRead == 0) break; + BytesRead += cAttrRead; + i++; + coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X); + LastAttrRead = cAttrRead; + } + // --------------------------------------------------------------------- + + + // --------------------------------------------------------------------- + // Modify the buffer proportions + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + // Letter space + int LWidth = floor((float)Width / 8.0) - 1.0; + int LHeight = floor((float)Height / 12.0) - 1.0; + int LBufWidth = LWidth + 1; + int LBufHeight = floor((float)BufferSize / (float)LBufWidth); + // Change screen buffer size + LetterSpace(LBufWidth, LBufHeight); + // --------------------------------------------------------------------- + + + // --------------------------------------------------------------------- + // Redraw the text + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + ClearScreen(true); + coordScreen.Y = 0; + coordScreen.X = 0; DWORD cCharsWritten = 0; - WriteConsoleOutputCharacter(hConsole, Str, cCharsRead, coordScreen, &cCharsWritten); + + int BytesWritten = 0; + DWORD cAttrWritten = 0; + for (int i = 0; i < Attr.size(); i++) + { + if (!WriteConsoleOutputCharacter(hConsole, Str[i], ReadBufferSize, coordScreen, &cCharsWritten)) + SLog += StringFromFormat("WriteConsoleOutputCharacter error"); + if (!WriteConsoleOutputAttribute(hConsole, Attr[i], ReadBufferSize, coordScreen, &cAttrWritten)) + SLog += StringFromFormat("WriteConsoleOutputAttribute error"); + + BytesWritten += cAttrWritten; + coordScreen = GetCoordinates(BytesWritten, LBufWidth); + } + // --------------------------------------------------------------------- + + + // --------------------------------------------------------------------- + // Update cursor + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; + COORD Coo = GetCoordinates(OldCursor, LBufWidth); + SetConsoleCursorPosition(hConsole, Coo); + // --------------------------------------------------------------------- + + if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str()); // Resize the window too - if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 50),(Height + 50), true); - - // Logging - //Log(LogTypes::LNOTICE, StringFromFormat("\n\n\n\nMaxBytes: %i, WxH:%ix%i, Consize: %i, Read: %i, Written: %i\n\n", MAX_BYTES, LWidth, LHeight, dwConSize, cCharsRead, cCharsWritten).c_str()); + if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true); #endif } //////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -226,7 +322,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) } // Clear console screen -void ConsoleListener::ClearScreen() +void ConsoleListener::ClearScreen(bool Cursor) { #if defined(_WIN32) COORD coordScreen = { 0, 0 }; @@ -243,7 +339,7 @@ void ConsoleListener::ClearScreen() GetConsoleScreenBufferInfo(hConsole, &csbi); FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); // Reset cursor - SetConsoleCursorPosition(hConsole, coordScreen); + if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); #endif } //////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Source/Core/Common/Src/Log.h b/Source/Core/Common/Src/Log.h index 21bbbbf1cc..bb58bc06fb 100644 --- a/Source/Core/Common/Src/Log.h +++ b/Source/Core/Common/Src/Log.h @@ -82,6 +82,7 @@ enum LOG_LEVELS { LWARNING = WARNING_LEVEL, LINFO = INFO_LEVEL, LDEBUG = DEBUG_LEVEL, + LCUSTOM = CUSTOM_LEVEL, }; } // namespace diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h index 28845ba054..d461390922 100644 --- a/Source/Core/Common/Src/LogManager.h +++ b/Source/Core/Common/Src/LogManager.h @@ -78,10 +78,14 @@ public: void Close(); bool IsOpen(); void LetterSpace(int Width, int Height); + void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst); void PixelSpace(int Left, int Top, int Width, int Height, bool); + #ifdef _WIN32 + COORD GetCoordinates(int BytesRead, int BufferWidth); + #endif void Log(LogTypes::LOG_LEVELS, const char *Text); //void Log(LogTypes::LOG_LEVELS, const char *Text, ...); - void ClearScreen(); + void ClearScreen(bool Cursor = true); const char *getName() const { return "Console"; } @@ -89,7 +93,6 @@ private: #ifdef _WIN32 HWND GetHwnd(void); HANDLE hConsole; - static const int MAX_BYTES = 1024 * 30; #endif }; diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index c88a617521..9980970238 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -82,6 +82,22 @@ extern "C" { }; +////////////////////////////////////////////////////////////////////////////////////////// +// Empty wxPanel +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +BEGIN_EVENT_TABLE(CEmptyPanel, wxPanel) +END_EVENT_TABLE() + +CEmptyPanel::CEmptyPanel( + wxWindow *parent, + wxWindowID id + ) + : wxPanel(parent, id) +{ +} +////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// /* Windows functions. Setting the cursor with wxSetCursor() did not work in this instance. Probably because it's somehow reset from the WndProc() in the child window */ diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index 5d12aaf4e3..f2ae784865 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -276,4 +276,17 @@ class CFrame : public wxFrame DECLARE_EVENT_TABLE(); }; + +class CEmptyPanel : public wxPanel +{ + public: + CEmptyPanel( + wxWindow* parent, + wxWindowID id = wxID_ANY + ); + + private: + DECLARE_EVENT_TABLE(); +}; + #endif // __FRAME_H_ diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 48fc991d0b..be1785641c 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -755,12 +755,49 @@ void CFrame::ResizeConsole() { if (m_NB[i]->GetPageText(j).IsSameAs(wxT("Console"))) { + #ifdef _WIN32 + // ---------------------------------------------------------- + // Get OS version + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + int wxBorder, Border, LowerBorder, MenuBar, ScrollBar, WidthReduction; + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + if (osvi.dwMajorVersion == 6) // Vista (same as 7?) + { + wxBorder = 2; + Border = 4; + LowerBorder = 6; + MenuBar = 30; // Including upper border + ScrollBar = 19; + } + else // XP + { + wxBorder = 2; + Border = 4; + LowerBorder = 6; + MenuBar = 30; + ScrollBar = 19; + } + WidthReduction = 30 - Border; + // -------------------------------- // Get the client size - int X = m_NB[i]->GetClientSize().GetX() - 35; - int Y = m_NB[i]->GetClientSize().GetY() - 70; + int X = m_NB[i]->GetClientSize().GetX(); + int Y = m_NB[i]->GetClientSize().GetY(); + int InternalWidth = X - wxBorder*2 - ScrollBar; + int InternalHeight = Y - wxBorder*2; + int WindowWidth = InternalWidth + Border*2; + int WindowHeight = InternalHeight; // Resize buffer ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener(); - Console->PixelSpace(0,0, X,Y, false); + Console->Log(LogTypes::LNOTICE, StringFromFormat("Window WxH:%i %i\n", X, Y).c_str()); + Console->PixelSpace(0,0, InternalWidth,InternalHeight, false); + // Move the window to hide the border + MoveWindow(GetConsoleWindow(), -Border-wxBorder,-MenuBar-wxBorder, WindowWidth + 100,WindowHeight, true); + // Move it to the bottom of the view order so that it doesn't hide the notebook tabs + // ... + #endif } } } @@ -1150,7 +1187,12 @@ void CFrame::ToggleConsole(bool Show, int i) // Can we remove the border? //Win->SetWindowStyleFlag(wxNO_BORDER); //SetWindowLong(GetConsoleWindow(), GWL_STYLE, WS_VISIBLE); - if (Win) m_NB[i]->AddPage(Win, wxT("Console"), true, aNormalFile ); + // Create parent window + CEmptyPanel * ConsoleParent = new CEmptyPanel(this); + ::SetParent(GetConsoleWindow(), (HWND)ConsoleParent->GetHWND()); + //Win->SetParent(ConsoleParent); + //if (Win) m_NB[i]->AddPage(Win, wxT("Console"), true, aNormalFile ); + if (Win) m_NB[i]->AddPage(ConsoleParent, wxT("Console"), true, aNormalFile ); #endif } else // hide