diff --git a/src/reactor_sim/dashboard.py b/src/reactor_sim/dashboard.py index 2fc16a8..15b79fd 100644 --- a/src/reactor_sim/dashboard.py +++ b/src/reactor_sim/dashboard.py @@ -457,18 +457,32 @@ class ReactorDashboard: self._draw_health_bars(right_win, right_y) def _draw_help_panel(self, win: "curses._CursesWindow") -> None: + def _add_safe(row: int, col: int, text: str, attr: int = 0) -> bool: + max_y, max_x = win.getmaxyx() + if row >= max_y - 1 or col >= max_x - 1: + return False + clipped = text[: max(0, max_x - col - 1)] + try: + win.addstr(row, col, clipped, attr) + except curses.error: + return False + return True + win.erase() win.box() - win.addstr(0, 2, " Controls ", curses.color_pair(1) | curses.A_BOLD) + _add_safe(0, 2, " Controls ", curses.color_pair(1) | curses.A_BOLD) y = 2 for title, entries in self.help_sections: - win.addstr(y, 2, title, curses.color_pair(1) | curses.A_BOLD) + if not _add_safe(y, 2, title, curses.color_pair(1) | curses.A_BOLD): + return y += 1 for entry in entries: - win.addstr(y, 4, f"{entry.key:<8} {entry.description}") + if not _add_safe(y, 4, f"{entry.key:<8} {entry.description}"): + return y += 1 y += 1 - win.addstr(y, 2, "Tips:", curses.color_pair(2) | curses.A_BOLD) + if not _add_safe(y, 2, "Tips:", curses.color_pair(2) | curses.A_BOLD): + return tips = [ "Start pumps before withdrawing rods.", "Bring turbine and consumer online after thermal stabilization.", @@ -478,7 +492,8 @@ class ReactorDashboard: "Watch component health to avoid automatic trips.", ] for idx, tip in enumerate(tips, start=y + 2): - win.addstr(idx, 4, f"- {tip}") + if not _add_safe(idx, 4, f"- {tip}"): + break def _draw_status_panel(self, win: "curses._CursesWindow", state: PlantState) -> None: win.erase()