Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file tui/pane.c
6 : * @brief Pane geometry and layout implementation (US-11 v2).
7 : */
8 :
9 : #include "tui/pane.h"
10 :
11 : #include <string.h>
12 :
13 38 : int pane_is_valid(const Pane *p) {
14 38 : return p && p->rows > 0 && p->cols > 0;
15 : }
16 :
17 0 : static void zero_layout(Layout *out) { memset(out, 0, sizeof(*out)); }
18 :
19 3 : void layout_compute(Layout *out, int screen_rows, int screen_cols,
20 : int left_width_hint) {
21 3 : if (!out) return;
22 3 : if (screen_rows < TUI_MIN_SCREEN_ROWS || screen_cols < TUI_MIN_SCREEN_COLS) {
23 0 : zero_layout(out);
24 0 : return;
25 : }
26 :
27 3 : int left = left_width_hint;
28 3 : if (left < TUI_MIN_LEFT_WIDTH) left = TUI_MIN_LEFT_WIDTH;
29 3 : if (left > TUI_MAX_LEFT_WIDTH) left = TUI_MAX_LEFT_WIDTH;
30 :
31 : /* History pane always needs at least 20 cols to be useful — shrink the
32 : * left pane if the terminal is too narrow to accommodate both. */
33 3 : int min_right = 20;
34 3 : if (screen_cols - left < min_right) {
35 0 : left = screen_cols - min_right;
36 0 : if (left < TUI_MIN_LEFT_WIDTH) left = TUI_MIN_LEFT_WIDTH;
37 : }
38 :
39 3 : int top_rows = screen_rows - 1; /* reserve last row for status line */
40 :
41 3 : out->dialogs.row = 0;
42 3 : out->dialogs.col = 0;
43 3 : out->dialogs.rows = top_rows;
44 3 : out->dialogs.cols = left;
45 :
46 3 : out->history.row = 0;
47 3 : out->history.col = left;
48 3 : out->history.rows = top_rows;
49 3 : out->history.cols = screen_cols - left;
50 :
51 3 : out->status.row = screen_rows - 1;
52 3 : out->status.col = 0;
53 3 : out->status.rows = 1;
54 3 : out->status.cols = screen_cols;
55 : }
56 :
57 9 : int pane_put_str(const Pane *p, Screen *s,
58 : int row, int col, const char *utf8, uint8_t attrs) {
59 9 : if (!pane_is_valid(p) || !s || !utf8) return 0;
60 9 : if (row < 0 || row >= p->rows || col < 0 || col >= p->cols) return 0;
61 9 : int remaining = p->cols - col;
62 9 : return screen_put_str_n(s, p->row + row, p->col + col, remaining,
63 : utf8, attrs);
64 : }
65 :
66 5 : void pane_fill(const Pane *p, Screen *s,
67 : int row, int col, int n, uint8_t attrs) {
68 5 : if (!pane_is_valid(p) || !s || n <= 0) return;
69 5 : if (row < 0 || row >= p->rows || col < 0 || col >= p->cols) return;
70 5 : if (col + n > p->cols) n = p->cols - col;
71 5 : screen_fill(s, p->row + row, p->col + col, n, attrs);
72 : }
73 :
74 6 : void pane_clear(const Pane *p, Screen *s) {
75 6 : if (!pane_is_valid(p) || !s) return;
76 144 : for (int r = 0; r < p->rows; r++) {
77 138 : screen_fill(s, p->row + r, p->col, p->cols, 0);
78 : }
79 : }
|