- Naming style migrated to camel-case - P7lib logger sources added - Vcpkg manifest, CMake presets and build moved to root - SDL2, Vulkan and RmlUi dependencies added - Logger LOG macro added - Logger configuration - SDL2 window configuration - Vulkan configuration - RmlUi configuration - SDL event loop
599 lines
21 KiB
C++
599 lines
21 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// 2012-2020 (c) Baical /
|
|
// /
|
|
// This library is free software; you can redistribute it and/or /
|
|
// modify it under the terms of the GNU Lesser General Public /
|
|
// License as published by the Free Software Foundation; either /
|
|
// version 3.0 of the License, or (at your option) any later version. /
|
|
// /
|
|
// This library is distributed in the hope that it will be useful, /
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
|
|
// Lesser General Public License for more details. /
|
|
// /
|
|
// You should have received a copy of the GNU Lesser General Public /
|
|
// License along with this library. /
|
|
// /
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#pragma once
|
|
|
|
#include <conio.h>
|
|
#include "AList.h"
|
|
#include "PString.h"
|
|
#include "IConsole.h"
|
|
#include "RBTree.h"
|
|
|
|
#pragma warning( disable : 4482 )
|
|
|
|
//http://invisible-island.net/ncurses/
|
|
//https://github.com/fffaraz/awesome-cpp
|
|
//http://www.leonerd.org.uk/code/libtickit/
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Is_Key_Hit
|
|
static tBOOL Is_Key_Hit(void)
|
|
{
|
|
return (_kbhit()) ? TRUE : FALSE;
|
|
}//Is_Key_Hit
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Get_Char
|
|
static tXCHAR Get_Char()
|
|
{
|
|
return _getwch();
|
|
}//Get_Char
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct stKeyMap
|
|
{
|
|
tUINT16 wKey;
|
|
tUINT16 wValue;
|
|
stKeyMap(tUINT16 i_wKey, tUINT16 i_wValue) : wKey(i_wKey), wValue(i_wValue) {}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//CDesc_Tree
|
|
class CKeysTree:
|
|
public CRBTree<stKeyMap*, tUINT16>
|
|
{
|
|
public:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//~CKeysTree
|
|
virtual ~CKeysTree()
|
|
{
|
|
Clear();
|
|
}//~CRBTree
|
|
|
|
protected:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
virtual tBOOL Data_Release(stKeyMap* i_pData)
|
|
{
|
|
delete i_pData;
|
|
return TRUE; //memory used from pool, not necessary to return
|
|
}// Data_Release
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Return
|
|
//TRUE - if (i_pKey < i_pData::key)
|
|
//FALSE - otherwise
|
|
tBOOL Is_Key_Less(tUINT16 i_pKey, stKeyMap *i_pData)
|
|
{
|
|
return (i_pKey < i_pData->wKey);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Return
|
|
//TRUE - if (i_pKey == i_pData::key)
|
|
//FALSE - otherwise
|
|
tBOOL Is_Qual(tUINT16 i_pKey, stKeyMap *i_pData)
|
|
{
|
|
return (i_pKey == i_pData->wKey);
|
|
}
|
|
};//CDesc_Tree
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
class CConsole
|
|
: public IConsole
|
|
{
|
|
tUINT16 m_pFg[IConsole::eColorsMax];
|
|
tUINT16 m_pBg[IConsole::eColorsMax];
|
|
size_t m_szText;
|
|
tXCHAR *m_pText;
|
|
HANDLE m_hStdOut;
|
|
HANDLE m_hStdIn;
|
|
tXCHAR *m_pEmpty;
|
|
size_t m_szEmpty;
|
|
CKeysTree m_pKeys;
|
|
public:
|
|
CConsole()
|
|
{
|
|
m_szText = 32768;
|
|
m_pText = (tXCHAR*)malloc(m_szText * sizeof(tXCHAR));
|
|
|
|
m_szEmpty = 0;
|
|
m_pEmpty = NULL;
|
|
AllocEmptyString(1024);
|
|
|
|
m_pFg[IConsole::eBlack] = 0;
|
|
m_pFg[IConsole::eBlue] = FOREGROUND_BLUE;
|
|
m_pFg[IConsole::eGreen] = FOREGROUND_GREEN;
|
|
m_pFg[IConsole::eCyan] = FOREGROUND_BLUE|FOREGROUND_GREEN;
|
|
m_pFg[IConsole::eRed] = FOREGROUND_RED;
|
|
m_pFg[IConsole::eMagenta] = FOREGROUND_BLUE|FOREGROUND_RED;
|
|
m_pFg[IConsole::eBrown] = FOREGROUND_GREEN|FOREGROUND_RED;
|
|
m_pFg[IConsole::eLightGray] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED;
|
|
m_pFg[IConsole::eDarkGray] = FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eLightBlue] = FOREGROUND_BLUE|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eLightGreen] = FOREGROUND_GREEN|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eLightCyan] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eLightRed] = FOREGROUND_RED|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eLightMagenta] = FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eYellow] = FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;
|
|
m_pFg[IConsole::eWhite] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;
|
|
|
|
m_pBg[IConsole::eBlack] = 0;
|
|
m_pBg[IConsole::eBlue] = BACKGROUND_BLUE;
|
|
m_pBg[IConsole::eGreen] = BACKGROUND_GREEN;
|
|
m_pBg[IConsole::eCyan] = BACKGROUND_BLUE|BACKGROUND_GREEN;
|
|
m_pBg[IConsole::eRed] = BACKGROUND_RED;
|
|
m_pBg[IConsole::eMagenta] = BACKGROUND_BLUE|BACKGROUND_RED;
|
|
m_pBg[IConsole::eBrown] = BACKGROUND_GREEN|BACKGROUND_RED;
|
|
m_pBg[IConsole::eLightGray] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED;
|
|
m_pBg[IConsole::eDarkGray] = BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eLightBlue] = BACKGROUND_BLUE|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eLightGreen] = BACKGROUND_GREEN|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eLightCyan] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eLightRed] = BACKGROUND_RED|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eLightMagenta] = BACKGROUND_BLUE|BACKGROUND_RED|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eYellow] = BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY;
|
|
m_pBg[IConsole::eWhite] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY;
|
|
|
|
m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
m_hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
|
SetConsoleMode(m_hStdIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
|
|
|
|
m_pKeys.Push(new stKeyMap(38, IConsole::eKeyArrowUp), 38);
|
|
m_pKeys.Push(new stKeyMap(40, IConsole::eKeyArrowDown), 40);
|
|
m_pKeys.Push(new stKeyMap(37, IConsole::eKeyArrowLeft), 37);
|
|
m_pKeys.Push(new stKeyMap(39, IConsole::eKeyArrowRight), 39);
|
|
m_pKeys.Push(new stKeyMap(35, IConsole::eKeyEnd), 35);
|
|
m_pKeys.Push(new stKeyMap(36, IConsole::eKeyHome), 36);
|
|
m_pKeys.Push(new stKeyMap(33, IConsole::eKeyPageUp), 33);
|
|
m_pKeys.Push(new stKeyMap(34, IConsole::eKeyPageDown), 34);
|
|
|
|
m_pKeys.Push(new stKeyMap(112, IConsole::eKeyF1), 112);
|
|
m_pKeys.Push(new stKeyMap(113, IConsole::eKeyF2), 113);
|
|
m_pKeys.Push(new stKeyMap(114, IConsole::eKeyF3), 114);
|
|
m_pKeys.Push(new stKeyMap(115, IConsole::eKeyF4), 115);
|
|
m_pKeys.Push(new stKeyMap(116, IConsole::eKeyF5), 116);
|
|
m_pKeys.Push(new stKeyMap(117, IConsole::eKeyF6), 117);
|
|
m_pKeys.Push(new stKeyMap(118, IConsole::eKeyF7), 118);
|
|
m_pKeys.Push(new stKeyMap(119, IConsole::eKeyF8), 119);
|
|
m_pKeys.Push(new stKeyMap(120, IConsole::eKeyF9), 120);
|
|
m_pKeys.Push(new stKeyMap(121, IConsole::eKeyF10), 121);
|
|
m_pKeys.Push(new stKeyMap(122, IConsole::eKeyF11), 122);
|
|
m_pKeys.Push(new stKeyMap(123, IConsole::eKeyF12), 123);
|
|
m_pKeys.Push(new stKeyMap(45, IConsole::eKeyInsert), 45);
|
|
m_pKeys.Push(new stKeyMap(46, IConsole::eKeyDel), 46);
|
|
m_pKeys.Push(new stKeyMap(9, IConsole::eKeyTab), 9);
|
|
m_pKeys.Push(new stKeyMap(8, IConsole::eKeyBackSpace), 8);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
virtual ~CConsole()
|
|
{
|
|
if (m_pText)
|
|
{
|
|
free(m_pText);
|
|
m_pText = NULL;
|
|
}
|
|
|
|
if (m_pEmpty)
|
|
{
|
|
free(m_pEmpty);
|
|
m_pEmpty = NULL;
|
|
}
|
|
|
|
m_pKeys.Clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL SetCursor(tUINT32 i_uX, tUINT32 i_uY)
|
|
{
|
|
COORD l_cCoord = {(SHORT)i_uX, (SHORT)i_uY};
|
|
return SetConsoleCursorPosition(m_hStdOut, l_cCoord);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tUINT32 GetCursorX()
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
|
|
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
|
|
{
|
|
return l_sCsbi.dwCursorPosition.X;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL GetInput(IConsole::sInput &o_rInput)
|
|
{
|
|
INPUT_RECORD l_stRecord = {};
|
|
DWORD l_dwRead = 0;
|
|
|
|
GetNumberOfConsoleInputEvents(m_hStdIn, &l_dwRead);
|
|
|
|
if (!l_dwRead)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ReadConsoleInput(m_hStdIn, &l_stRecord, 1, &l_dwRead);
|
|
|
|
if (!l_dwRead)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (FOCUS_EVENT == l_stRecord.EventType)
|
|
{
|
|
o_rInput.eEvent = IConsole::eEvent::eFocus;
|
|
o_rInput.stFocus.bFocus = l_stRecord.Event.FocusEvent.bSetFocus;
|
|
}
|
|
else if (KEY_EVENT == l_stRecord.EventType)
|
|
{
|
|
o_rInput.eEvent = IConsole::eEvent::eKey;
|
|
o_rInput.stKey.bDown = l_stRecord.Event.KeyEvent.bKeyDown;
|
|
o_rInput.stKey.uControls = l_stRecord.Event.KeyEvent.dwControlKeyState;
|
|
o_rInput.stKey.wCount = l_stRecord.Event.KeyEvent.wRepeatCount;
|
|
|
|
stKeyMap *l_pKey = m_pKeys.Find(l_stRecord.Event.KeyEvent.wVirtualKeyCode);
|
|
if (l_pKey)
|
|
{
|
|
o_rInput.stKey.wKey = l_pKey->wValue;
|
|
}
|
|
else
|
|
{
|
|
o_rInput.stKey.wKey = l_stRecord.Event.KeyEvent.wVirtualKeyCode;
|
|
}
|
|
}
|
|
else if (MOUSE_EVENT == l_stRecord.EventType)
|
|
{
|
|
o_rInput.eEvent = IConsole::eEvent::eMouse;
|
|
o_rInput.stMouse.uButton = l_stRecord.Event.MouseEvent.dwButtonState;
|
|
o_rInput.stMouse.uX = l_stRecord.Event.MouseEvent.dwMousePosition.X;
|
|
o_rInput.stMouse.uY = l_stRecord.Event.MouseEvent.dwMousePosition.Y;
|
|
}
|
|
else if (WINDOW_BUFFER_SIZE_EVENT == l_stRecord.EventType)
|
|
{
|
|
o_rInput.eEvent = IConsole::eEvent::eSize;
|
|
o_rInput.stSize.uW = l_stRecord.Event.WindowBufferSizeEvent.dwSize.X;
|
|
o_rInput.stSize.uH = l_stRecord.Event.WindowBufferSizeEvent.dwSize.Y;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tUINT32 GetCursorY()
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
|
|
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
|
|
{
|
|
return l_sCsbi.dwCursorPosition.Y;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tUINT32 GetWidth()
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
|
|
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
|
|
{
|
|
return l_sCsbi.srWindow.Right - l_sCsbi.srWindow.Left + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tUINT32 GetHeight()
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
|
|
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
|
|
{
|
|
return l_sCsbi.srWindow.Bottom - l_sCsbi.srWindow.Top + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL SetTextAttr(IConsole::eColor i_eFg, IConsole::eColor i_eBg)
|
|
{
|
|
if ( (i_eFg < 0)
|
|
|| (i_eFg >= IConsole::eColorsMax)
|
|
|| (i_eBg < 0)
|
|
|| (i_eBg >= IConsole::eColorsMax)
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return SetConsoleTextAttribute(m_hStdOut, m_pFg[i_eFg] | m_pBg[i_eBg]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL Clear()
|
|
{
|
|
COORD l_sCoordScreen = { 0, 0 }; // home for the cursor
|
|
DWORD l_dwCharsWritten = 0;
|
|
DWORD l_dwConSize = 0;
|
|
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
|
|
|
|
// Get the number of character cells in the current buffer.
|
|
if( !GetConsoleScreenBufferInfo( m_hStdOut, &l_sCsbi ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
l_dwConSize = l_sCsbi.dwSize.X * l_sCsbi.dwSize.Y;
|
|
|
|
// Fill the entire screen with blanks.
|
|
if( !FillConsoleOutputCharacterW( m_hStdOut, // Handle to console screen buffer
|
|
L' ', // Character to write to the buffer
|
|
l_dwConSize, // Number of cells to write
|
|
l_sCoordScreen, // Coordinates of first cell
|
|
&l_dwCharsWritten )) // Receive number of characters written
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the current text attribute.
|
|
if( !GetConsoleScreenBufferInfo( m_hStdOut, &l_sCsbi ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the buffer's attributes accordingly.
|
|
if( !FillConsoleOutputAttribute( m_hStdOut, // Handle to console screen buffer
|
|
l_sCsbi.wAttributes, // Character attributes to use
|
|
l_dwConSize, // Number of cells to set attribute
|
|
l_sCoordScreen, // Coordinates of first cell
|
|
&l_dwCharsWritten )) // Receive number of characters written
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Put the cursor at its home coordinates.
|
|
return SetConsoleCursorPosition( m_hStdOut, l_sCoordScreen );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL Clear(tUINT32 i_uX, tUINT32 i_uY, tUINT32 i_uW, tUINT32 i_uH, IConsole::eColor i_eBg)
|
|
{
|
|
tUINT32 l_uiW = GetWidth();
|
|
tUINT32 l_uiH = GetHeight();
|
|
|
|
if ( (i_uX > l_uiW)
|
|
|| (i_uY > l_uiH)
|
|
|| (!i_uW)
|
|
|| (!i_uH)
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ((i_uX + i_uW) > l_uiW)
|
|
{
|
|
i_uW = l_uiW - i_uX;
|
|
}
|
|
|
|
if ((i_uY + i_uH) > l_uiH)
|
|
{
|
|
i_uH = l_uiH - i_uY;
|
|
}
|
|
|
|
if (i_uW > m_szEmpty)
|
|
{
|
|
if (!AllocEmptyString((size_t)i_uW))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (!SetTextAttr(IConsole::eBlack, i_eBg))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
tUINT32 l_uiX = GetCursorX();
|
|
tUINT32 l_uiY = GetCursorY();
|
|
tUINT32 l_uiYOld = l_uiY;
|
|
while (i_uH--)
|
|
{
|
|
SetCursor(i_uX, i_uY++);
|
|
WriteTextB(m_pEmpty, i_uW);
|
|
}
|
|
|
|
SetCursor(l_uiX, l_uiYOld);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
size_t WriteTextB(const tXCHAR *i_pText, size_t i_szText)
|
|
{
|
|
DWORD l_dwWritten = 0;
|
|
return WriteConsole(m_hStdOut, i_pText, (DWORD)i_szText, &l_dwWritten, NULL);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
size_t WriteTextB(IConsole::eColor i_eFg,
|
|
IConsole::eColor i_eBg,
|
|
size_t i_szLenMin,
|
|
size_t i_szLenMax,
|
|
size_t i_szOffset,
|
|
tXCHAR *i_pText,
|
|
size_t i_szText,
|
|
size_t i_szTextMax
|
|
)
|
|
{
|
|
if ( (i_szLenMin > i_szLenMax)
|
|
|| (!i_pText)
|
|
|| (8 >= i_szTextMax)
|
|
|| (i_szText >= i_szTextMax)
|
|
)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (!SetTextAttr(i_eFg, i_eBg))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
tXCHAR *l_pText = i_pText;
|
|
|
|
if (!i_szText)
|
|
{
|
|
i_szText = PStrLen(i_pText);
|
|
}
|
|
|
|
//if there is offset, recalculate all inputs
|
|
if (i_szOffset)
|
|
{
|
|
if (i_szOffset < i_szText) //set sext offset and recalculate all
|
|
{
|
|
l_pText = l_pText + i_szOffset;
|
|
i_szText -= i_szOffset;
|
|
i_szTextMax -= i_szOffset;
|
|
i_szOffset = 0;
|
|
*l_pText = TM('<');
|
|
}
|
|
else //if (i_szOffset >= i_szText)
|
|
{
|
|
l_pText = m_pText;
|
|
*l_pText = TM('<');
|
|
i_szText = 1;
|
|
i_szTextMax= m_szText;
|
|
}
|
|
}
|
|
|
|
|
|
if (i_szText > i_szLenMax)
|
|
{
|
|
i_szText = i_szLenMax;
|
|
l_pText[i_szText-1] = TM('>');
|
|
}
|
|
else if (i_szText < i_szLenMin)
|
|
{
|
|
if (i_szTextMax < (i_szLenMin + 1))
|
|
{
|
|
PStrNCpy(m_pText, m_szText, l_pText, i_szText);
|
|
l_pText = m_pText;
|
|
i_szTextMax = m_szText;
|
|
}
|
|
|
|
tXCHAR *l_pIter = l_pText + i_szText;
|
|
|
|
while (i_szText < i_szLenMin)
|
|
{
|
|
*l_pIter = TM(' ');
|
|
l_pIter ++;
|
|
i_szText++;
|
|
}
|
|
}
|
|
|
|
if (i_szText < i_szTextMax)
|
|
{
|
|
l_pText[i_szText] = 0;
|
|
}
|
|
else
|
|
{
|
|
l_pText[i_szText-1] = 0;
|
|
}
|
|
|
|
DWORD l_dwWritten = 0;
|
|
if (!WriteConsole(m_hStdOut, l_pText, (DWORD)i_szText, &l_dwWritten, NULL))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return (size_t)l_dwWritten;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
size_t WriteTextF(IConsole::eColor i_eFg,
|
|
IConsole::eColor i_eBg,
|
|
size_t i_szLenMin,
|
|
size_t i_szLenMax,
|
|
size_t i_szOffset,
|
|
const tXCHAR *i_pFormat,
|
|
va_list i_pVA
|
|
)
|
|
{
|
|
int l_iReturn = PVsnprintf(m_pText, m_szText, i_pFormat, i_pVA);
|
|
|
|
if (0 > l_iReturn)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return WriteTextB(i_eFg, i_eBg, i_szLenMin, i_szLenMax, i_szOffset, m_pText, (size_t)l_iReturn, m_szText);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL Present()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
protected:
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
tBOOL AllocEmptyString(size_t i_szEmpty)
|
|
{
|
|
if (m_pEmpty)
|
|
{
|
|
free(m_pEmpty);
|
|
}
|
|
|
|
if (i_szEmpty > 4096)
|
|
{
|
|
i_szEmpty = 4096;
|
|
}
|
|
|
|
m_szEmpty = i_szEmpty;
|
|
m_pEmpty = (tXCHAR*)malloc(m_szEmpty * sizeof(tXCHAR));
|
|
|
|
if (!m_pEmpty)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
tXCHAR *l_pEmpty = m_pEmpty;
|
|
size_t l_szIterator = m_szEmpty;
|
|
|
|
while (l_szIterator--)
|
|
{
|
|
*l_pEmpty = TM(' ');
|
|
l_pEmpty++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
};
|