// Package display holds small rendering helpers, not an application framework. package display import ( "strings" "unicode" ) // BodyRows receives already-measured chrome heights, not guessed constants. func BodyRows(total, header, footer int) int { return max(0, max(0, total)-max(0, header)-max(0, footer)) } // Window keeps the current row visible and returns a half-open item range. // It only applies to fixed-height, one-line rows. func Window(total, cursor, top, height int) (int, int) { if total <= 0 || height <= 0 { return 0, 0 } cursor = min(max(0, cursor), total-1) top = min(max(0, top), max(0, total-height)) if cursor < top { top = cursor } if cursor >= top+height { top = cursor - height + 1 } return top, min(total, top+height) } // SingleLine accepts plain data, not trusted ANSI. It neutralizes terminal // controls by replacing every C0/C1 control with a space. Escape parameters // remain visible text. This is deliberately not an ANSI-preserving sanitizer // or a Unicode spoofing defense. Application styling is added AFTER this call. func SingleLine(s string) string { return strings.Map(func(r rune) rune { if unicode.IsControl(r) || r == '\u2028' || r == '\u2029' { return ' ' } return r }, strings.ToValidUTF8(s, "\uFFFD")) }