From 68462d00cb2b083edcc544af4f86b6604a40f830 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 17 Aug 2026 02:26:04 -0400 Subject: [PATCH] Fixed crash bug. Wide characters were sometimes causing an index out of range error. Now they are just treated as spaces. --- src/fenrirscreenreader/fenrirVersion.py | 2 +- .../screenDriver/ptyDriver.py | 17 ++++++++++++++++ tests/unit/test_pty_terminal_sequences.py | 20 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/fenrirscreenreader/fenrirVersion.py b/src/fenrirscreenreader/fenrirVersion.py index 75a6ecff..2343604f 100644 --- a/src/fenrirscreenreader/fenrirVersion.py +++ b/src/fenrirscreenreader/fenrirVersion.py @@ -4,5 +4,5 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. -version = "2026.08.14" +version = "2026.08.17" code_name = "testing" diff --git a/src/fenrirscreenreader/screenDriver/ptyDriver.py b/src/fenrirscreenreader/screenDriver/ptyDriver.py index 0de1b0fc..2b16c419 100644 --- a/src/fenrirscreenreader/screenDriver/ptyDriver.py +++ b/src/fenrirscreenreader/screenDriver/ptyDriver.py @@ -49,6 +49,23 @@ class PTYConstants: class FenrirScreen(pyte.Screen): + @property + def display(self): + def render(line): + skip_stub = False + for x in range(self.columns): + if skip_stub: + skip_stub = False + continue + char = line[x].data + if not char: + yield " " + continue + skip_stub = pyte.screens.wcwidth(char[0]) == 2 + yield char + + return ["".join(render(self.buffer[y])) for y in range(self.lines)] + def set_margins(self, *args, **kwargs): kwargs.pop("private", None) super(FenrirScreen, self).set_margins(*args, **kwargs) diff --git a/tests/unit/test_pty_terminal_sequences.py b/tests/unit/test_pty_terminal_sequences.py index 706412f1..9c37882f 100644 --- a/tests/unit/test_pty_terminal_sequences.py +++ b/tests/unit/test_pty_terminal_sequences.py @@ -39,6 +39,26 @@ def test_private_sgr_sequence_from_fullscreen_apps_does_not_crash(): assert screen["text"].splitlines()[0] == "X " +@pytest.mark.unit +def test_overwritten_wide_character_stub_renders_as_space(): + terminal = Terminal(4, 1, DummyProcessInput()) + + terminal.feed("界\rX".encode()) + screen = terminal.get_screen_content() + + assert screen["text"] == "X " + + +@pytest.mark.unit +def test_wide_character_and_stub_keep_terminal_width(): + terminal = Terminal(4, 1, DummyProcessInput()) + + terminal.feed("界".encode()) + screen = terminal.get_screen_content() + + assert screen["text"] == "界 " + + @pytest.mark.unit def test_optional_float_setting_uses_default_when_missing(): settings_manager = type(