implement more crt stuff

This commit is contained in:
John Sennesael 2021-08-15 18:23:24 -05:00
parent 50b3029afa
commit eb4c9cdb85
5 changed files with 435 additions and 136 deletions

View File

@ -1105,7 +1105,18 @@ std::string MakeCssiSequence(const char sequence);
* @param sequence Sequence to compose.
* @return Returns the assembled sequence.
*/
std::string MakeCsiSequence(const std::string& sequence);
//std::string MakeCsiSequence(const std::string& sequence);
/**
* @brief Make CSI sequence (multiple parameters).
*
* Creates a string holding a CSI sequence with prefixes added.
* Inserts semi-colons between parameters automatically.
*
* @param sequenceItems csi control characters or parameters.
* @return Returns the assembled sequence.
*/
std::string MakeCsiSequence(const std::vector<std::string>& sequenceItems);
/**
* @brief Make DEC private mode Sequence.

View File

@ -8,6 +8,8 @@
namespace neovision {
// Classes/enums/structs/... ---------------------------------------------------
/**
* @brief Standard 16 color definitions.
*/
@ -35,101 +37,55 @@ enum class StandardColor {
*
* Holds the column (X) and row (Y) of a screen position.
*/
struct Position {
class Position {
std::int32_t m_x{};
std::int32_t m_y{};
public:
/**
* @brief column.
* Constructor with initial values.
*/
std::uint32_t X{0};
Position(std::int32_t x, std::int32_t y);
/**
* @brief row.
* Constructor with unsigned initial values.
*/
std::uint32_t Y{0};
Position(std::uint32_t x, std::uint32_t y);
/**
* @brief Get X.
* @return Returns the position x coordinate.
*/
std::int32_t X() const;
/**
* @brief Set X.
* @param n New x value.
*/
void X(std::int32_t n);
/**
* @brief Get Y.
* @return Returns the position y coordinate.
*/
std::int32_t Y() const;
/**
* @brief Set Y.
* @param New y value.
*/
void Y(std::int32_t n);
Position operator+(const Position& other) const;
Position operator+=(const Position& other);
void operator=(const Position& other);
bool operator==(const Position& other) const;
bool operator!=(const Position& other) const;
};
/**
* @brief Clear screen.
*
* Erases all characters on the screen.
*/
void ClearScreen();
/**
* @brief Get cursor position.
*
* Lets you determine where the cursor currently is on the screen.
*
* @note In order for this to function properly, Terminal::Unbuffer() must be
* called before calling this function, as it relies on a response from
* the terminal which we must be able to read without having to wait for
* a buffer flush (like when the user presses enter for instance). The
* Application class will already do this for you on stdin, but if you're
* using this directly, it's something to consider.
*
* @return Returns the current cursor's screen coordinates.
*/
Position GetCursorPos();
/**
* @brief Sets the cursor position.
*
* @param pos New cursor position.
* @param relative (optional, default false) Moves cursor relative to current
* position if true. Otherwise, absolute coordinates are used.
*/
void SetCursorPos(const Position& pos, bool relative = false);
/**
* @brief Sets background color (16 color version).
*
* Sets the current background color for any following output to the given
* color. This version uses standard 16 colors.
*
* @param color New output background color.
*/
void SetBackgroundColor(StandardColor color);
/**
* @brief Sets background color (rgb color version).
*
* Sets the current background color for any following output to the given
* color. This version uses red/green/blue values.
*
* Note that some terminals may round to the nearest color on a 256 color
* palette, whilst others might support true color.
*
* @param r New output background color red value.
* @param g New output background color green value.
* @param b New output background color blue value.
*/
void SetBackgroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b);
/**
* @brief Sets foreground color (16 color version).
*
* Sets the current foreground color for any following output to the given
* color. This version uses standard 16 colors.
*
* @param color New output foreground color.
*/
void SetForegroundColor(StandardColor color);
/**
* @brief Sets foreground color (rgb color version).
*
* Sets the current foreground color for any following output to the given
* color. This version uses red/green/blue values.
*
* Note that some terminals may round to the nearest color on a 256 color
* palette, whilst others might support true color.
*
* @param r New output foreground color red value.
* @param g New output foreground color green value.
* @param b New output foreground color blue value.
*/
void SetForegroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b);
/**
* @brief Input/Output.
*
@ -228,6 +184,17 @@ public:
*/
std::string Read(std::size_t bytes);
/**
* @brief Reads from the current input stream.
*
* Reads bytes until given character is encountered and returns the data
* read up until (and including) the given character.
*
* @param c Character to read up to.
* @return Returns the data read from the stream.
*/
std::string ReadUntil(char c);
/**
* @brief Sets the current input stream.
*
@ -276,4 +243,108 @@ public:
};
// Functions -------------------------------------------------------------------
/**
* @brief Clear screen.
*
* Erases all characters on the screen.
*/
void ClearScreen();
/**
* @brief Get cursor position.
*
* Lets you determine where the cursor currently is on the screen.
*
* @note In order for this to function properly, Terminal::Unbuffer() must be
* called before calling this function, as it relies on a response from
* the terminal which we must be able to read without having to wait for
* a buffer flush (like when the user presses enter for instance). The
* Application class will already do this for you on stdin, but if you're
* using this directly, it's something to consider.
*
* @return Returns the current cursor's screen coordinates.
*/
Position GetCursorPos();
/**
* @brief Sets the cursor position.
*
* @note When relative is true, this function uses GetCursorPos to get the
* current cursor position and as such, the same note as for that
* function applies in terms of calling Terminal::Unbuffer().
*
* @param pos New cursor position.
* @param relative (optional, default false) Moves cursor relative to current
* position if true. Otherwise, absolute coordinates are used.
*/
void SetCursorPos(const Position& pos, bool relative = false);
/**
* @brief Sets background color (16 color version).
*
* Sets the current background color for any following output to the given
* color. This version uses standard 16 colors.
*
* @param color New output background color.
*/
void SetBackgroundColor(StandardColor color);
/**
* @brief Sets background color (rgb color version).
*
* Sets the current background color for any following output to the given
* color. This version uses red/green/blue values.
*
* Note that some terminals may round to the nearest color on a 256 color
* palette, whilst others might support true color.
*
* @param r New output background color red value.
* @param g New output background color green value.
* @param b New output background color blue value.
*/
void SetBackgroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b);
/**
* @brief Sets foreground color (16 color version).
*
* Sets the current foreground color for any following output to the given
* color. This version uses standard 16 colors.
*
* @param color New output foreground color.
*/
void SetForegroundColor(StandardColor color);
/**
* @brief Sets foreground color (rgb color version).
*
* Sets the current foreground color for any following output to the given
* color. This version uses red/green/blue values.
*
* Note that some terminals may round to the nearest color on a 256 color
* palette, whilst others might support true color.
*
* @param r New output foreground color red value.
* @param g New output foreground color green value.
* @param b New output foreground color blue value.
*/
void SetForegroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b);
/**
* Convert Color enum to ANSI background color code.
*
* @param c Color to convert.
* @return Color as ansi background color SGR code.
*/
std::string ToAnsiBgColor(StandardColor c);
/**
* Convert Color enum to ANSI foreground color code.
*
* @param c Color to convert.
* @return Color as ansi foreground color SGR code.
*/
std::string ToAnsiFgColor(StandardColor c);
} // namespace neovision

View File

@ -16,14 +16,34 @@ std::string MakeCssiSequence(const char sequence)
return MakeEscapeSequence(EscapeSequence::CSSI + sequence);
}
/*
std::string MakeCsiSequence(const std::string& sequence)
{
return MakeEscapeSequence(EscapeSequence::CSI + sequence);
}
*/
std::string MakeCsiSequence(const std::vector<std::string>& sequenceItems)
{
std::string result;
if (!sequenceItems.empty())
{
for (const std::string& item: sequenceItems)
{
result += item + ";";
}
result.pop_back();
}
return MakeEscapeSequence(EscapeSequence::CSI + result);
}
std::string MakeDecPmSequence(const char sequence, const char suffix)
{
return MakeCsiSequence(CsiSequence::DECPM + sequence + suffix);
return MakeCsiSequence({
std::string{CsiSequence::DECPM},
std::string{sequence},
std::string{suffix}
});
}
std::string MakeSgrSequence(const std::vector<std::string>& sequenceItems)
@ -38,7 +58,7 @@ std::string MakeSgrSequence(const std::vector<std::string>& sequenceItems)
result.pop_back();
}
result += CsiSequence::SGR;
return MakeCsiSequence(result);
return MakeCsiSequence({result});
}
} // namespace ansi

View File

@ -13,63 +13,68 @@
namespace neovision {
void ClearScreen() {
IO::Get().Write(ansi::MakeEscapeSequence(ansi::EscapeSequence::RIS));
}
// Position struct -------------------------------------------------------------
Position GetCursorPos()
{
static const std::regex getCursorPosRegex{"^\x1b\\[(\\d+);(\\d+)R$"};
IO::Get().Write(
ansi::MakeCsiSequence(std::string{"6"} + ansi::CsiSequence::DSR)
);
std::string response = IO::Get().Read(6);
std::smatch responseMatches;
if (!std::regex_match(
response, responseMatches, getCursorPosRegex
)) return {0, 0};
if (responseMatches.size() != 3) return {0, 0};
const std::uint32_t x = std::stoi(responseMatches[1].str());
const std::uint32_t y = std::stoi(responseMatches[2].str());
return {x, y};
}
void SetCursorPos(const Position& pos, bool relative)
{
if (relative)
{
if (pos.X != 0)
{
/*
Output::Get().Write(
ansi::MakeCsiSequence(
std::to_string(x) + ansi::CsiSequence::
);
*/
}
}
else
{
}
}
void SetBackgroundColor(StandardColor color)
Position::Position(std::int32_t x, std::int32_t y): m_x{x}, m_y{y}
{
}
void SetBackgroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b)
Position::Position(std::uint32_t x, std::uint32_t y)
{
m_x = x;
m_y = y;
}
void SetForegroundColor(StandardColor color)
std::int32_t Position::X() const
{
return m_x;
}
void SetForegroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b)
void Position::X(std::int32_t n)
{
m_x = n;
}
std::int32_t Position::Y() const
{
return m_y;
}
void Position::Y(std::int32_t n)
{
m_y = n;
}
Position Position::operator+(const Position& other) const
{
return Position(m_x + other.m_x, m_y + other.m_y);
}
Position Position::operator+=(const Position& other)
{
m_x += other.m_x;
m_y += other.m_y;
return *this;
}
void Position::operator=(const Position& other)
{
m_x = other.m_x;
m_y = other.m_y;
}
bool Position::operator==(const Position& other) const
{
return (m_x == other.m_x) && (m_y == other.m_y);
}
bool Position::operator!=(const Position& other) const
{
return !((m_x == other.m_x) && (m_y == other.m_y));
}
// IO class --------------------------------------------------------------------
IO::IO(): m_inputStream{std::ref(std::cin)}, m_outputStream{std::ref(std::cout)}
{
}
@ -102,6 +107,7 @@ std::reference_wrapper<std::ostream> IO::OutputStream()
std::string IO::Read(std::size_t bytes)
{
const std::lock_guard<std::mutex> lock(m_inputMutex);
std::vector<char> buffer(bytes);
char charBuffer[bytes];
m_inputStream.get().rdbuf()->pubsetbuf(charBuffer, bytes);
@ -109,6 +115,19 @@ std::string IO::Read(std::size_t bytes)
return std::string(buffer.begin(), buffer.end());
}
std::string IO::ReadUntil(char c)
{
const std::lock_guard<std::mutex> lock(m_inputMutex);
char character;
std::string buffer;
while (m_inputStream.get().get(character))
{
buffer += character;
if (character == c) break;
}
return buffer;
}
void IO::SetInputStream(std::istream& stream)
{
const std::lock_guard<std::mutex> lock(m_inputMutex);
@ -137,4 +156,174 @@ void IO::Write(const std::string& str)
m_outputStream.get() << str;
}
// Functions -------------------------------------------------------------------
void ClearScreen() {
IO::Get().Write(ansi::MakeCsiSequence({
std::string{"2"}, std::string{ansi::CsiSequence::ED}
}));
}
Position GetCursorPos()
{
static const std::regex getCursorPosRegex{"^\x1b\\[(\\d+);(\\d+)R$"};
IO::Get().Write(ansi::MakeCsiSequence({
std::string{"6"}, std::string{ansi::CsiSequence::DSR}
}));
std::string response = IO::Get().ReadUntil('R');
std::smatch responseMatches;
if (!std::regex_match(
response, responseMatches, getCursorPosRegex
))
{
throw std::runtime_error(
"Could not parse GetCursorPos response from terminal. (1)"
);
}
if (responseMatches.size() != 3)
{
throw std::runtime_error(
"Could not parse GetCursorPos response from terminal. (2)"
);
}
const std::uint32_t x = std::stoi(responseMatches[1].str());
const std::uint32_t y = std::stoi(responseMatches[2].str());
return {x, y};
}
void SetCursorPos(const Position& pos, bool relative)
{
Position newPos(pos);
if (relative)
{
newPos += GetCursorPos();
if (newPos == pos) return;
}
IO::Get().Write(
ansi::MakeCsiSequence({
std::to_string(newPos.Y()),
std::to_string(newPos.X()),
ansi::CsiSequence::HVP
})
);
}
void SetBackgroundColor(StandardColor color)
{
IO::Get().Write(
ansi::MakeSgrSequence({ToAnsiBgColor(color)})
);
}
void SetBackgroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b)
{
IO::Get().Write(
ansi::MakeSgrSequence({
ansi::SgrSequence::SET_BG_COLOR,
"2",
std::to_string(r),
std::to_string(g),
std::to_string(b)
})
);
}
void SetForegroundColor(StandardColor color)
{
IO::Get().Write(
ansi::MakeSgrSequence({ToAnsiFgColor(color)})
);
}
void SetForegroundColor(std::uint8_t r, std::uint8_t g, std::uint8_t b)
{
IO::Get().Write(
ansi::MakeSgrSequence({
ansi::SgrSequence::SET_FG_COLOR,
"2",
std::to_string(r),
std::to_string(g),
std::to_string(b)
})
);
}
std::string ToAnsiBgColor(StandardColor c)
{
switch(c)
{
case StandardColor::BLACK:
return ansi::SgrSequence::BG_BLACK;
case StandardColor::RED:
return ansi::SgrSequence::BG_RED;
case StandardColor::GREEN:
return ansi::SgrSequence::BG_GREEN;
case StandardColor::YELLOW:
return ansi::SgrSequence::BG_YELLOW;
case StandardColor::BLUE:
return ansi::SgrSequence::BG_BLUE;
case StandardColor::MAGENTA:
return ansi::SgrSequence::BG_MAGENTA;
case StandardColor::CYAN:
return ansi::SgrSequence::BG_MAGENTA;
case StandardColor::WHITE:
return ansi::SgrSequence::BG_WHITE;
case StandardColor::BRIGHT_BLACK:
return ansi::SgrSequence::BG_BRIGHT_BLACK;
case StandardColor::BRIGHT_RED:
return ansi::SgrSequence::BG_BRIGHT_RED;
case StandardColor::BRIGHT_GREEN:
return ansi::SgrSequence::BG_BRIGHT_GREEN;
case StandardColor::BRIGHT_YELLOW:
return ansi::SgrSequence::BG_BRIGHT_YELLOW;
case StandardColor::BRIGHT_BLUE:
return ansi::SgrSequence::BG_BRIGHT_BLUE;
case StandardColor::BRIGHT_MAGENTA:
return ansi::SgrSequence::BG_BRIGHT_MAGENTA;
case StandardColor::BRIGHT_CYAN:
return ansi::SgrSequence::BG_BRIGHT_MAGENTA;
case StandardColor::BRIGHT_WHITE:
return ansi::SgrSequence::BG_BRIGHT_WHITE;
}
}
std::string ToAnsiFgColor(StandardColor c)
{
switch(c)
{
case StandardColor::BLACK:
return ansi::SgrSequence::FG_BLACK;
case StandardColor::RED:
return ansi::SgrSequence::FG_RED;
case StandardColor::GREEN:
return ansi::SgrSequence::FG_GREEN;
case StandardColor::YELLOW:
return ansi::SgrSequence::FG_YELLOW;
case StandardColor::BLUE:
return ansi::SgrSequence::FG_BLUE;
case StandardColor::MAGENTA:
return ansi::SgrSequence::FG_MAGENTA;
case StandardColor::CYAN:
return ansi::SgrSequence::FG_MAGENTA;
case StandardColor::WHITE:
return ansi::SgrSequence::FG_WHITE;
case StandardColor::BRIGHT_BLACK:
return ansi::SgrSequence::FG_BRIGHT_BLACK;
case StandardColor::BRIGHT_RED:
return ansi::SgrSequence::FG_BRIGHT_RED;
case StandardColor::BRIGHT_GREEN:
return ansi::SgrSequence::FG_BRIGHT_GREEN;
case StandardColor::BRIGHT_YELLOW:
return ansi::SgrSequence::FG_BRIGHT_YELLOW;
case StandardColor::BRIGHT_BLUE:
return ansi::SgrSequence::FG_BRIGHT_BLUE;
case StandardColor::BRIGHT_MAGENTA:
return ansi::SgrSequence::FG_BRIGHT_MAGENTA;
case StandardColor::BRIGHT_CYAN:
return ansi::SgrSequence::FG_BRIGHT_MAGENTA;
case StandardColor::BRIGHT_WHITE:
return ansi::SgrSequence::FG_BRIGHT_WHITE;
}
}
} // namespace neovision

View File

@ -22,8 +22,16 @@ int main(int argc, char* argv[])
ClearScreen();
Position p = GetCursorPos();
std::cout << "Cursor is at: " << p.X << ", " << p.Y << std::endl;
for (int y = 0; y != 21 ; ++y)
{
for (int x = 0 ; x != 80 ; ++x)
{
SetCursorPos({x, y});
SetBackgroundColor( x, 0, 0 );
SetForegroundColor( 0, y*5, y*5 );
IO::Get().Write("x");
}
}
std::vector<std::string> args(argv + 1, argv + argc);
pubnix::Application app(args);