From b84c87ef820976cc541586a09ec6f845726580f2 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Sat, 17 Oct 2026 03:54:06 +0800 Subject: feat(tui): add Unicode text service and document layout --- ricochet/src/tui/layout.hh | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 ricochet/src/tui/layout.hh (limited to 'ricochet/src/tui/layout.hh') diff --git a/ricochet/src/tui/layout.hh b/ricochet/src/tui/layout.hh new file mode 100644 index 0000000..5feb0cd --- /dev/null +++ b/ricochet/src/tui/layout.hh @@ -0,0 +1,98 @@ +/* + * Ricochet - A minimalist CLI web browser for fast, distraction-free navigation. + * Copyright (C) 2026 Richard Qin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "paint.hh" +#include "ricochet/tui/view.hh" +#include "text.hh" + +#include +#include +#include +#include +#include +#include + +namespace ricochet::tui::detail { + +using HitTarget = std::variant; + +struct LayoutPoint +{ + std::size_t row { 0 }; + std::int64_t column { 0 }; +}; + +struct LayoutHit +{ + DisplayPosition position {}; + DocumentRange unit {}; + std::optional target {}; +}; + +struct LayoutGlyph +{ + LayoutPoint position {}; + int columns { 0 }; + std::wstring text {}; + TextStyle style {}; + DocumentRange source {}; + std::optional target {}; + // Clip bounds are in document-layout columns and also constrain hit testing. + std::int64_t clip_left { 0 }; + std::int64_t clip_right { 0 }; + // Structural boundaries locate anchors but do not displace nearby text hits. + bool boundary_only { false }; + std::int64_t line_start { 0 }; + bool decoration { false }; + bool line_break { false }; + bool fill { false }; +}; + +struct LayoutData +{ + // Reading order, including table cells in row/cell order; not screen order. + std::vector glyphs {}; + std::size_t rows { 1 }; + std::int64_t extent { 0 }; +}; + +// A derived snapshot for one Document + initial control values + width/scrolls. +// Editing will supply a separate draft snapshot; this stage uses revision zero. +// No ncurses headers, terminal objects or business-module dependencies. +class DocumentLayout +{ +public: + DocumentLayout( const Document& document, + const TextService& text, + int columns, + std::span scrolls ); + + int columns() const; + std::size_t rows() const; + std::optional locate( const DisplayPosition& position ) const; + std::optional hit( LayoutPoint point ) const; + void append_frame( Frame& frame, std::size_t first_row, CellPoint origin, ScreenSize viewport ) const; + +private: + int columns_; + LayoutData data_; +}; + +} // namespace ricochet::tui::detail -- cgit v1.2.3