Skip to content

Commit

Permalink
Add position class
Browse files Browse the repository at this point in the history
  • Loading branch information
flagarde committed Dec 5, 2024
1 parent ce28a7d commit 30cbc02
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 29 deletions.
2 changes: 2 additions & 0 deletions cpp-terminal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ set(CPP_TERMINAL_PUBLIC_HEADERS
key.hpp
mouse.hpp
options.hpp
position.hpp
prompt.hpp
screen.hpp
stream.hpp
style.hpp
size.hpp
terminal_impl.hpp
terminal_initializer.hpp
terminal.hpp
Expand Down
12 changes: 4 additions & 8 deletions cpp-terminal/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,13 @@

#include "cpp-terminal/cursor.hpp"

Term::Cursor::Cursor(const std::size_t& row, const std::size_t& column) : m_position({row, column}) {}
Term::Cursor::Cursor(const Position& position) : m_position(position) {}

std::size_t Term::Cursor::row() const { return m_position.first; }
std::size_t Term::Cursor::row() const { return m_position.row(); }

std::size_t Term::Cursor::column() const { return m_position.second; }
std::size_t Term::Cursor::column() const { return m_position.column(); }

bool Term::Cursor::empty() const { return (0 == m_position.first) && (0 == m_position.second); }

void Term::Cursor::setRow(const std::size_t& row) { m_position.first = row; }

void Term::Cursor::setColum(const std::size_t& column) { m_position.second = column; }
bool Term::Cursor::empty() const { return (0 == m_position.row()) && (0 == m_position.column()); }

bool Term::Cursor::operator==(const Term::Cursor& cursor) const { return (this->row() == cursor.row()) && (this->column() == cursor.column()); }

Expand Down
10 changes: 4 additions & 6 deletions cpp-terminal/cursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

#pragma once

#include <cstddef>
#include <cstdint>
#include "cpp-terminal/position.hpp"

#include <string>

namespace Term
Expand All @@ -20,17 +20,15 @@ class Cursor
{
public:
Cursor() = default;
Cursor(const std::size_t& row, const std::size_t& column);
explicit Cursor(const Position& position);
std::size_t row() const;
std::size_t column() const;
void setRow(const std::size_t&);
void setColum(const std::size_t&);
bool empty() const;
bool operator==(const Term::Cursor& cursor) const;
bool operator!=(const Term::Cursor& cursor) const;

private:
std::pair<std::size_t, std::size_t> m_position;
Position m_position;
};

// returns the current cursor position (row, column) (Y, X)
Expand Down
2 changes: 1 addition & 1 deletion cpp-terminal/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ void Term::Event::parse(const std::string& str)
if(found != std::string::npos)
{
m_Type = Type::Cursor;
m_container.m_Cursor = Cursor(static_cast<std::uint16_t>(std::stoi(str.substr(2, found - 2))), static_cast<std::uint16_t>(std::stoi(str.substr(found + 1, str.size() - (found + 2)))));
m_container.m_Cursor = Cursor({Row(std::stoi(str.substr(2, found - 2))), Column(std::stoi(str.substr(found + 1, str.size() - (found + 2))))});
}
}
else if(str[0] == '\033' && str[1] == '[' && str[2] == '<')
Expand Down
4 changes: 2 additions & 2 deletions cpp-terminal/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

Term::Options::Options(const std::initializer_list<Term::Option>& option) : m_Options(option) { clean(); }

bool Term::Options::operator==(const Options& options) { return m_Options == options.m_Options; }
bool Term::Options::operator!=(const Options& options) { return !(m_Options == options.m_Options); }
bool Term::Options::operator==(const Options& options) const { return m_Options == options.m_Options; }
bool Term::Options::operator!=(const Options& options) const { return !(m_Options == options.m_Options); }

void Term::Options::clean()
{
Expand Down
4 changes: 2 additions & 2 deletions cpp-terminal/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class Options
Options(const std::initializer_list<Term::Option>& option);
template<typename... Args> explicit Options(const Args&&... args) : m_Options(std::initializer_list<Term::Option>{args...}) { clean(); }

bool operator==(const Options& options);
bool operator!=(const Options& options);
bool operator==(const Options& options) const;
bool operator!=(const Options& options) const;
bool has(const Option& option) const noexcept;

private:
Expand Down
54 changes: 54 additions & 0 deletions cpp-terminal/position.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* cpp-terminal
* C++ library for writing multi-platform terminal applications.
*
* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#include <cstddef>
#include <cstdint>

namespace Term
{

class Row
{
public:
Row() = default;
explicit Row(const std::uint16_t& row) : m_row(row) {}
operator std::size_t() const noexcept { return m_row; }

private:
std::uint16_t m_row{0};
};

class Column
{
public:
Column() = default;
explicit Column(const std::uint16_t& column) : m_column(column) {}
operator std::size_t() const noexcept { return m_column; }

private:
std::uint16_t m_column{0};
};

class Position
{
public:
Position() = default;
Position(const Row& row, const Column& column) : m_row(row), m_column(column) {};
Position(const Column& column, const Row& row) : m_row(row), m_column(column) {};
const Row& row() const noexcept { return m_row; }
const Column& column() const noexcept { return m_column; }

private:
Row m_row{1};
Column m_column{1};
};

} // namespace Term
6 changes: 3 additions & 3 deletions cpp-terminal/private/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ Term::Cursor Term::cursor_position()
if(Term::Private::in.null()) { return {}; }
#if defined(_WIN32)
CONSOLE_SCREEN_BUFFER_INFO inf;
if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Cursor(static_cast<std::size_t>(inf.dwCursorPosition.Y + 1), static_cast<std::size_t>(inf.dwCursorPosition.X + 1));
if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Cursor({Row(inf.dwCursorPosition.Y + 1), Column(inf.dwCursorPosition.X + 1)});
else
return Term::Cursor(0, 0);
return {}

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-11.1.0 (c++14)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-12.0.1 (c++11)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-12.0.1 (c++14)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-11.1.0 (c++20)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-11.1.0 (c++11)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 clang-11.1.0 (c++17)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang64 (c++17)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang64 (c++14)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / ucrt64 (c++14)

expected ';' before '}' token

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / ucrt64 (c++11)

expected ';' before '}' token

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang32 (c++17)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / ucrt64 (c++20)

expected ';' before '}' token

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang64 (c++11)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / ucrt64 (c++17)

expected ';' before '}' token

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang32 (c++11)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang32 (c++14)

expected ';' after return statement

Check failure on line 34 in cpp-terminal/private/cursor.cpp

View workflow job for this annotation

GitHub Actions / clang64 (c++20)

expected ';' after return statement
#else
std::string ret;
std::size_t nread{0};
Expand Down Expand Up @@ -64,7 +64,7 @@ Term::Cursor Term::cursor_position()
if(ret[0] == '\033' && ret[1] == '[' && ret[ret.size() - 1] == 'R')
{
std::size_t found = ret.find(';', 2);
if(found != std::string::npos) { return Cursor(std::stoi(ret.substr(2, found - 2)), std::stoi(ret.substr(found + 1, ret.size() - (found + 2)))); }
if(found != std::string::npos) { return Cursor({Row(std::stoi(ret.substr(2, found - 2))), Column(std::stoi(ret.substr(found + 1, ret.size() - (found + 2))))}); }
return {};
}
return {};
Expand Down
3 changes: 2 additions & 1 deletion cpp-terminal/prompt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "cpp-terminal/screen.hpp"
#include "cpp-terminal/terminal.hpp"
#include "cpp-terminal/tty.hpp"
#include "position.hpp"

#include <iostream>

Expand Down Expand Up @@ -357,7 +358,7 @@ std::string Term::prompt_multiline(const std::string& prompt_string, std::vector
std::cout << scr.render(1, cursor.row(), term_attached) << std::flush;
if(cursor.row() + scr.columns() - 1 > screen.rows())
{
cursor.setRow(static_cast<std::uint16_t>(screen.rows() - (scr.columns() - 1)));
cursor = Cursor({Row(static_cast<std::uint16_t>(screen.rows() - (scr.columns() - 1))), Column(cursor.column())});

Check warning on line 361 in cpp-terminal/prompt.cpp

View workflow job for this annotation

GitHub Actions / msvc2022 win32 (c++14)

'argument': conversion from 'size_t' to 'const uint16_t', possible loss of data [D:\a\cpp-terminal\cpp-terminal\build\cpp-terminal\cpp-terminal.vcxproj]

Check warning on line 361 in cpp-terminal/prompt.cpp

View workflow job for this annotation

GitHub Actions / msvc2022 win32 (c++11)

'argument': conversion from 'size_t' to 'const uint16_t', possible loss of data [D:\a\cpp-terminal\cpp-terminal\build\cpp-terminal\cpp-terminal.vcxproj]
std::cout << scr.render(1, cursor.row(), term_attached) << std::flush;
}
}
Expand Down
4 changes: 2 additions & 2 deletions cpp-terminal/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void Term::Window::set_bg(const std::size_t& column, const std::size_t& row, con

void Term::Window::set_style(const std::size_t& column, const std::size_t& row, const Style& style) { m_style[index(column, row)] = style; }

void Term::Window::set_cursor_pos(const std::size_t& column, const std::size_t& row) { m_cursor = {row, column}; }
void Term::Window::set_cursor_pos(const std::size_t& column, const std::size_t& row) { m_cursor = Cursor({Row(row), Column(column)}); }

Check warning on line 78 in cpp-terminal/window.cpp

View workflow job for this annotation

GitHub Actions / msvc2022 win32 (c++14)

'argument': conversion from 'size_t' to 'const uint16_t', possible loss of data [D:\a\cpp-terminal\cpp-terminal\build\cpp-terminal\cpp-terminal.vcxproj]

Check warning on line 78 in cpp-terminal/window.cpp

View workflow job for this annotation

GitHub Actions / msvc2022 win32 (c++11)

'argument': conversion from 'size_t' to 'const uint16_t', possible loss of data [D:\a\cpp-terminal\cpp-terminal\build\cpp-terminal\cpp-terminal.vcxproj]

void Term::Window::set_h(const std::size_t& new_h)
{
Expand Down Expand Up @@ -118,7 +118,7 @@ void Term::Window::print_str(const std::size_t& x, const std::size_t& y, const s
++xpos;
}
}
if(move_cursor) { m_cursor = {ypos, xpos}; }
if(move_cursor) { m_cursor = Cursor({Row(ypos), Column(xpos)}); }
}

void Term::Window::fill_fg(const std::size_t& x1, const std::size_t& y1, const std::size_t& x2, const std::size_t& y2, const Color& rgb)
Expand Down
2 changes: 1 addition & 1 deletion cpp-terminal/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Window
private:
std::size_t index(const std::size_t& column, const std::size_t& row) const;
Term::Size m_size;
Term::Cursor m_cursor{1, 1};
Term::Cursor m_cursor;
std::vector<char32_t> m_chars; // the characters in row first order
std::vector<Term::Color> m_fg;
std::vector<Term::Color> m_bg;
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cppterminal_example(SOURCE args)
cppterminal_example(SOURCE cin_cooked)
cppterminal_example(SOURCE cin_raw)
cppterminal_example(SOURCE colors)
cppterminal_example(SOURCE cursor)
cppterminal_example(SOURCE cout)
cppterminal_example(SOURCE events LIBRARIES Threads::Threads)
cppterminal_example(SOURCE keys)
Expand Down
69 changes: 69 additions & 0 deletions examples/cursor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* cpp-terminal
* C++ library for writing multi-platform terminal applications.
*
* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
*
* SPDX-License-Identifier: MIT
*/

#include "cpp-terminal/cursor.hpp"

#include "cpp-terminal/exception.hpp"
#include "cpp-terminal/input.hpp"
#include "cpp-terminal/iostream.hpp"
#include "cpp-terminal/options.hpp"
#include "cpp-terminal/terminal.hpp"

#include <ostream>

int main()
{
try
{
// check if the terminal is capable of handling input
Term::terminal.setOptions(Term::Option::ClearScreen, Term::Option::NoSignalKeys, Term::Option::Cursor, Term::Option::Raw);
Term::Cursor cursor{Term::cursor_position()};
Term::cout << "Cursor position : " << cursor.row() << " " << cursor.column() << std::endl;

Term::cout << "Press any key ( 3 time 'q' to quit):" << std::endl;
int quit{0};
while(quit != 3)
{
Term::Event event = Term::read_event();
switch(event.type())
{
case Term::Event::Type::Key:
{
Term::Key key(event);
if(key == Term::Key::q) { quit++; }
else
{
quit = 0;
Term::cout << key.name() << std::flush;
Term::cout << " " << Term::cursor_position_report() << std::flush;
}
break;
}
case Term::Event::Type::Cursor:
{
Term::Cursor cursor(event);
Term::cout << " [Column(X) : " << cursor.column() << " Row(Y) : " << cursor.row() << "]";
break;
}
default: break;
}
}
}
catch(const Term::Exception& re)
{
Term::cerr << "cpp-terminal error: " << re.what() << std::endl;
return 2;
}
catch(...)
{
Term::cerr << "Unknown error." << std::endl;
return 1;
}
return 0;
}
6 changes: 3 additions & 3 deletions tests/events.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ TEST_CASE("Event with Focus")

TEST_CASE("Event with Cursor")
{
Term::Cursor cursor(1, 5);
Term::Cursor cursor({Term::Row(1), Term::Column(5)});
Term::Event event(cursor);
CHECK(event.empty() == false);
CHECK(event.get_if_screen() == nullptr);
CHECK(event.get_if_focus() == nullptr);
CHECK(*event.get_if_cursor() == Term::Cursor(1, 5));
CHECK(*event.get_if_cursor() == Term::Cursor({Term::Row(1), Term::Column(5)}));
CHECK(event.get_if_key() == nullptr);
CHECK(event.get_if_mouse() == nullptr);
CHECK(event.get_if_copy_paste() == nullptr);
Expand All @@ -94,7 +94,7 @@ TEST_CASE("Event with Cursor")
CHECK(event2.empty() == false);
CHECK(event.get_if_screen() == nullptr);
CHECK(event2.get_if_focus() == nullptr);
CHECK(*event2.get_if_cursor() == Term::Cursor(1, 5));
CHECK(*event2.get_if_cursor() == Term::Cursor({Term::Row(1), Term::Column(5)}));
CHECK(event2.get_if_key() == nullptr);
CHECK(event2.get_if_mouse() == nullptr);
CHECK(event2.get_if_copy_paste() == nullptr);
Expand Down

0 comments on commit 30cbc02

Please sign in to comment.