Skip to content

Commit e5f34f1

Browse files
committed
Terminal: Fix Canvas with 0x0 size
1 parent 521d671 commit e5f34f1

4 files changed

Lines changed: 41 additions & 9 deletions

File tree

modules/Terminal/Canvas.mpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export namespace CppUtils::Terminal
3939
using namespace std::literals;
4040
const auto terminalSize = getTerminalSize();
4141
const auto viewportSize = m_viewport.getSize();
42-
const auto startLine = terminalSize.height() - viewportSize.height() - 1;
42+
const auto startLine = terminalSize.height() > viewportSize.height() ? terminalSize.height() - viewportSize.height() - 1 : 0;
4343
auto stringBuffer = ""s;
4444
auto needFlush = false;
4545
auto lastAttributes = CharAttributes{};
@@ -91,7 +91,10 @@ export namespace CppUtils::Terminal
9191
}
9292
if (needFlush)
9393
std::fflush(stdout);
94-
setCursorPosition({0, terminalSize.height() > 0 ? terminalSize.height() - 1 : 0});
94+
{
95+
const auto terminalHeight = getTerminalSize().height();
96+
setCursorPosition({0, terminalHeight > 0 ? terminalHeight - 1 : 0});
97+
}
9598
}
9699

97100
inline auto print() noexcept -> void

modules/Terminal/ProgressBar.mpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,20 @@ export namespace CppUtils::Terminal
2929
{
3030
const auto size = view.getViewport().getSize();
3131
const auto titleSize = std::size(m_title);
32-
const auto barWidth = size.width() - titleSize - 2 - 6;
32+
constexpr auto percentWidth = 5; // " 100%"
33+
const auto titleAndPercentSize = titleSize + percentWidth;
34+
if (size.width() < titleAndPercentSize)
35+
return;
36+
constexpr auto minBarWidth = 4; // " [#]"
37+
if (size.width() < titleAndPercentSize + minBarWidth)
38+
{
39+
const auto text = std::format("{} {:>3}% ", m_title, static_cast<std::size_t>(m_percent));
40+
view.printText({0, 0}, text);
41+
return;
42+
}
43+
const auto barWidth = size.width() - (titleAndPercentSize + minBarWidth - 1);
3344
const auto progress = static_cast<std::size_t>(static_cast<float>(barWidth) * m_percent / 100.f);
34-
35-
auto text = std::format("{} [{}{}] {:>3}% ", m_title, std::string(progress, '#'), std::string(barWidth - progress, ' '), static_cast<std::size_t>(m_percent));
45+
const auto text = std::format("{} [{}{}] {:>3}% ", m_title, std::string(progress, '#'), std::string(barWidth - progress, ' '), static_cast<std::size_t>(m_percent));
3646
view.printText({0, 0}, text);
3747
drawFinished();
3848
}

modules/Terminal/Size.mpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ export namespace CppUtils::Terminal
2626
#elif defined(OS_LINUX) or defined(OS_MACOS)
2727
[[nodiscard]] inline auto getTerminalSize() -> Container::Size2
2828
{
29-
auto windowsSize = winsize{};
30-
ioctl(STDOUT_FILENO, TIOCGWINSZ, std::addressof(windowsSize));
29+
auto terminalSize = winsize{};
30+
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, std::addressof(terminalSize)) == -1)
31+
return Container::Size2{0, 0};
3132
return Container::Size2{
32-
static_cast<std::size_t>(windowsSize.ws_col),
33-
static_cast<std::size_t>(windowsSize.ws_row)};
33+
static_cast<std::size_t>(terminalSize.ws_col),
34+
static_cast<std::size_t>(terminalSize.ws_row)};
3435
}
3536
#endif
3637
}

tests/Terminal/Canvas.mpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@ namespace CppUtils::UnitTest::Terminal::Canvas
99
using namespace std::literals;
1010
using namespace std::chrono_literals;
1111

12+
suite.addTest("Canvas with 0x0 size", [&] {
13+
auto canvas = CppUtils::Terminal::Canvas{CppUtils::Container::Size2{0, 0}};
14+
canvas.fill('.');
15+
canvas.print();
16+
});
17+
18+
suite.addTest("Canvas with 0 height", [&] {
19+
auto canvas = CppUtils::Terminal::Canvas{CppUtils::Container::Size2{10, 0}};
20+
canvas.fill('.');
21+
canvas.print();
22+
});
23+
24+
suite.addTest("Canvas with 0 width", [&] {
25+
auto canvas = CppUtils::Terminal::Canvas{CppUtils::Container::Size2{0, 10}};
26+
canvas.fill('.');
27+
canvas.print();
28+
});
29+
1230
suite.addTest("Size", [&] {
1331
{
1432
auto canvas = CppUtils::Terminal::Canvas{CppUtils::Container::Size2{10, 5}};

0 commit comments

Comments
 (0)