package app import ( "fmt" "strings" "github.com/harrybrwn/patterm/internal/vt" ) func renderScreenSnapshot(text string, cursor vt.CursorState, layout terminalLayout) []byte { lines := strings.Split(strings.ReplaceAll(text, "\r\n", "\n"), "\n") cols := int(layout.childCols()) rows := int(layout.childRows()) var b strings.Builder b.WriteString("\x1b[?25l") for r := 0; r < rows; r++ { line := "" if r < len(lines) { line = truncateCells(lines[r], cols) } fmt.Fprintf(&b, "\x1b[%d;%dH%s", int(layout.mainTop)+r, int(layout.mainLeft), padRight(line, cols)) } if cursor.Visible { row := int(layout.mainTop) + int(cursor.Row) col := int(layout.mainLeft) + int(cursor.Col) if row < int(layout.mainTop) { row = int(layout.mainTop) } maxRow := int(layout.mainTop) + rows - 1 if row > maxRow { row = maxRow } if col < int(layout.mainLeft) { col = int(layout.mainLeft) } maxCol := int(layout.mainLeft) + cols - 1 if col > maxCol { col = maxCol } fmt.Fprintf(&b, "\x1b[?25h\x1b[%d;%dH", row, col) } return []byte(b.String()) } func renderCursor(cursor vt.CursorState, layout terminalLayout) []byte { cols := int(layout.childCols()) rows := int(layout.childRows()) row := int(layout.mainTop) + int(cursor.Row) col := int(layout.mainLeft) + int(cursor.Col) if row < int(layout.mainTop) { row = int(layout.mainTop) } maxRow := int(layout.mainTop) + rows - 1 if row > maxRow { row = maxRow } if col < int(layout.mainLeft) { col = int(layout.mainLeft) } maxCol := int(layout.mainLeft) + cols - 1 if col > maxCol { col = maxCol } return []byte(fmt.Sprintf("\x1b[?25h\x1b[%d;%dH", row, col)) } func truncateCells(s string, width int) string { if width <= 0 { return "" } if visibleLen(s) <= width { return s } var b strings.Builder n := 0 for _, r := range s { if n >= width { break } b.WriteRune(r) n++ } return b.String() }