Skip to content

Commit 30cbc02

Browse files
committed
Add position class
1 parent ce28a7d commit 30cbc02

File tree

14 files changed

+150
-29
lines changed

14 files changed

+150
-29
lines changed

cpp-terminal/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ set(CPP_TERMINAL_PUBLIC_HEADERS
1515
key.hpp
1616
mouse.hpp
1717
options.hpp
18+
position.hpp
1819
prompt.hpp
1920
screen.hpp
2021
stream.hpp
2122
style.hpp
23+
size.hpp
2224
terminal_impl.hpp
2325
terminal_initializer.hpp
2426
terminal.hpp

cpp-terminal/cursor.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,13 @@
99

1010
#include "cpp-terminal/cursor.hpp"
1111

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

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

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

18-
bool Term::Cursor::empty() const { return (0 == m_position.first) && (0 == m_position.second); }
19-
20-
void Term::Cursor::setRow(const std::size_t& row) { m_position.first = row; }
21-
22-
void Term::Cursor::setColum(const std::size_t& column) { m_position.second = column; }
18+
bool Term::Cursor::empty() const { return (0 == m_position.row()) && (0 == m_position.column()); }
2319

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

cpp-terminal/cursor.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
#pragma once
1111

12-
#include <cstddef>
13-
#include <cstdint>
12+
#include "cpp-terminal/position.hpp"
13+
1414
#include <string>
1515

1616
namespace Term
@@ -20,17 +20,15 @@ class Cursor
2020
{
2121
public:
2222
Cursor() = default;
23-
Cursor(const std::size_t& row, const std::size_t& column);
23+
explicit Cursor(const Position& position);
2424
std::size_t row() const;
2525
std::size_t column() const;
26-
void setRow(const std::size_t&);
27-
void setColum(const std::size_t&);
2826
bool empty() const;
2927
bool operator==(const Term::Cursor& cursor) const;
3028
bool operator!=(const Term::Cursor& cursor) const;
3129

3230
private:
33-
std::pair<std::size_t, std::size_t> m_position;
31+
Position m_position;
3432
};
3533

3634
// returns the current cursor position (row, column) (Y, X)

cpp-terminal/event.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ void Term::Event::parse(const std::string& str)
235235
if(found != std::string::npos)
236236
{
237237
m_Type = Type::Cursor;
238-
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)))));
238+
m_container.m_Cursor = Cursor({Row(std::stoi(str.substr(2, found - 2))), Column(std::stoi(str.substr(found + 1, str.size() - (found + 2))))});
239239
}
240240
}
241241
else if(str[0] == '\033' && str[1] == '[' && str[2] == '<')

cpp-terminal/options.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

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

16-
bool Term::Options::operator==(const Options& options) { return m_Options == options.m_Options; }
17-
bool Term::Options::operator!=(const Options& options) { return !(m_Options == options.m_Options); }
16+
bool Term::Options::operator==(const Options& options) const { return m_Options == options.m_Options; }
17+
bool Term::Options::operator!=(const Options& options) const { return !(m_Options == options.m_Options); }
1818

1919
void Term::Options::clean()
2020
{

cpp-terminal/options.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class Options
3838
Options(const std::initializer_list<Term::Option>& option);
3939
template<typename... Args> explicit Options(const Args&&... args) : m_Options(std::initializer_list<Term::Option>{args...}) { clean(); }
4040

41-
bool operator==(const Options& options);
42-
bool operator!=(const Options& options);
41+
bool operator==(const Options& options) const;
42+
bool operator!=(const Options& options) const;
4343
bool has(const Option& option) const noexcept;
4444

4545
private:

cpp-terminal/position.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* cpp-terminal
3+
* C++ library for writing multi-platform terminal applications.
4+
*
5+
* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
6+
*
7+
* SPDX-License-Identifier: MIT
8+
*/
9+
10+
#pragma once
11+
12+
#include <cstddef>
13+
#include <cstdint>
14+
15+
namespace Term
16+
{
17+
18+
class Row
19+
{
20+
public:
21+
Row() = default;
22+
explicit Row(const std::uint16_t& row) : m_row(row) {}
23+
operator std::size_t() const noexcept { return m_row; }
24+
25+
private:
26+
std::uint16_t m_row{0};
27+
};
28+
29+
class Column
30+
{
31+
public:
32+
Column() = default;
33+
explicit Column(const std::uint16_t& column) : m_column(column) {}
34+
operator std::size_t() const noexcept { return m_column; }
35+
36+
private:
37+
std::uint16_t m_column{0};
38+
};
39+
40+
class Position
41+
{
42+
public:
43+
Position() = default;
44+
Position(const Row& row, const Column& column) : m_row(row), m_column(column) {};
45+
Position(const Column& column, const Row& row) : m_row(row), m_column(column) {};
46+
const Row& row() const noexcept { return m_row; }
47+
const Column& column() const noexcept { return m_column; }
48+
49+
private:
50+
Row m_row{1};
51+
Column m_column{1};
52+
};
53+
54+
} // namespace Term

cpp-terminal/private/cursor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ Term::Cursor Term::cursor_position()
2929
if(Term::Private::in.null()) { return {}; }
3030
#if defined(_WIN32)
3131
CONSOLE_SCREEN_BUFFER_INFO inf;
32-
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));
32+
if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Cursor({Row(inf.dwCursorPosition.Y + 1), Column(inf.dwCursorPosition.X + 1)});
3333
else
34-
return Term::Cursor(0, 0);
34+
return {}
3535
#else
3636
std::string ret;
3737
std::size_t nread{0};
@@ -64,7 +64,7 @@ Term::Cursor Term::cursor_position()
6464
if(ret[0] == '\033' && ret[1] == '[' && ret[ret.size() - 1] == 'R')
6565
{
6666
std::size_t found = ret.find(';', 2);
67-
if(found != std::string::npos) { return Cursor(std::stoi(ret.substr(2, found - 2)), std::stoi(ret.substr(found + 1, ret.size() - (found + 2)))); }
67+
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))))}); }
6868
return {};
6969
}
7070
return {};

cpp-terminal/prompt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "cpp-terminal/screen.hpp"
2121
#include "cpp-terminal/terminal.hpp"
2222
#include "cpp-terminal/tty.hpp"
23+
#include "position.hpp"
2324

2425
#include <iostream>
2526

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

cpp-terminal/window.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void Term::Window::set_bg(const std::size_t& column, const std::size_t& row, con
7575

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

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

8080
void Term::Window::set_h(const std::size_t& new_h)
8181
{
@@ -118,7 +118,7 @@ void Term::Window::print_str(const std::size_t& x, const std::size_t& y, const s
118118
++xpos;
119119
}
120120
}
121-
if(move_cursor) { m_cursor = {ypos, xpos}; }
121+
if(move_cursor) { m_cursor = Cursor({Row(ypos), Column(xpos)}); }
122122
}
123123

124124
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)

cpp-terminal/window.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class Window
7979
private:
8080
std::size_t index(const std::size_t& column, const std::size_t& row) const;
8181
Term::Size m_size;
82-
Term::Cursor m_cursor{1, 1};
82+
Term::Cursor m_cursor;
8383
std::vector<char32_t> m_chars; // the characters in row first order
8484
std::vector<Term::Color> m_fg;
8585
std::vector<Term::Color> m_bg;

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ cppterminal_example(SOURCE args)
3131
cppterminal_example(SOURCE cin_cooked)
3232
cppterminal_example(SOURCE cin_raw)
3333
cppterminal_example(SOURCE colors)
34+
cppterminal_example(SOURCE cursor)
3435
cppterminal_example(SOURCE cout)
3536
cppterminal_example(SOURCE events LIBRARIES Threads::Threads)
3637
cppterminal_example(SOURCE keys)

examples/cursor.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* cpp-terminal
3+
* C++ library for writing multi-platform terminal applications.
4+
*
5+
* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
6+
*
7+
* SPDX-License-Identifier: MIT
8+
*/
9+
10+
#include "cpp-terminal/cursor.hpp"
11+
12+
#include "cpp-terminal/exception.hpp"
13+
#include "cpp-terminal/input.hpp"
14+
#include "cpp-terminal/iostream.hpp"
15+
#include "cpp-terminal/options.hpp"
16+
#include "cpp-terminal/terminal.hpp"
17+
18+
#include <ostream>
19+
20+
int main()
21+
{
22+
try
23+
{
24+
// check if the terminal is capable of handling input
25+
Term::terminal.setOptions(Term::Option::ClearScreen, Term::Option::NoSignalKeys, Term::Option::Cursor, Term::Option::Raw);
26+
Term::Cursor cursor{Term::cursor_position()};
27+
Term::cout << "Cursor position : " << cursor.row() << " " << cursor.column() << std::endl;
28+
29+
Term::cout << "Press any key ( 3 time 'q' to quit):" << std::endl;
30+
int quit{0};
31+
while(quit != 3)
32+
{
33+
Term::Event event = Term::read_event();
34+
switch(event.type())
35+
{
36+
case Term::Event::Type::Key:
37+
{
38+
Term::Key key(event);
39+
if(key == Term::Key::q) { quit++; }
40+
else
41+
{
42+
quit = 0;
43+
Term::cout << key.name() << std::flush;
44+
Term::cout << " " << Term::cursor_position_report() << std::flush;
45+
}
46+
break;
47+
}
48+
case Term::Event::Type::Cursor:
49+
{
50+
Term::Cursor cursor(event);
51+
Term::cout << " [Column(X) : " << cursor.column() << " Row(Y) : " << cursor.row() << "]";
52+
break;
53+
}
54+
default: break;
55+
}
56+
}
57+
}
58+
catch(const Term::Exception& re)
59+
{
60+
Term::cerr << "cpp-terminal error: " << re.what() << std::endl;
61+
return 2;
62+
}
63+
catch(...)
64+
{
65+
Term::cerr << "Unknown error." << std::endl;
66+
return 1;
67+
}
68+
return 0;
69+
}

tests/events.test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ TEST_CASE("Event with Focus")
8080

8181
TEST_CASE("Event with Cursor")
8282
{
83-
Term::Cursor cursor(1, 5);
83+
Term::Cursor cursor({Term::Row(1), Term::Column(5)});
8484
Term::Event event(cursor);
8585
CHECK(event.empty() == false);
8686
CHECK(event.get_if_screen() == nullptr);
8787
CHECK(event.get_if_focus() == nullptr);
88-
CHECK(*event.get_if_cursor() == Term::Cursor(1, 5));
88+
CHECK(*event.get_if_cursor() == Term::Cursor({Term::Row(1), Term::Column(5)}));
8989
CHECK(event.get_if_key() == nullptr);
9090
CHECK(event.get_if_mouse() == nullptr);
9191
CHECK(event.get_if_copy_paste() == nullptr);
@@ -94,7 +94,7 @@ TEST_CASE("Event with Cursor")
9494
CHECK(event2.empty() == false);
9595
CHECK(event.get_if_screen() == nullptr);
9696
CHECK(event2.get_if_focus() == nullptr);
97-
CHECK(*event2.get_if_cursor() == Term::Cursor(1, 5));
97+
CHECK(*event2.get_if_cursor() == Term::Cursor({Term::Row(1), Term::Column(5)}));
9898
CHECK(event2.get_if_key() == nullptr);
9999
CHECK(event2.get_if_mouse() == nullptr);
100100
CHECK(event2.get_if_copy_paste() == nullptr);

0 commit comments

Comments
 (0)