text, $width - 4, cut_long_words:true)); if ($height == 0) $height = count($wrapped) + 4; $maxScroll = (count($wrapped) > $height) ? count($wrapped) - $height + 4 : 0; $this->redraw($left, $top, $width, $height, $wrapped, $this->title, $maxScroll); $showing = true; while ($showing) { while (null === ($ch = $this->terminal->readKey())) { usleep(10000); } if (mb_strlen($ch) == 1) { if ($ch == "\x03") { $showing = false; } } else { if ($ch == "k{UP}") { $this->scroll--; if ($this->scroll < 0) $this->scroll = 0; $this->redraw($left, $top, $width, $height, $wrapped, $this->title, $maxScroll); } elseif ($ch == "k{DOWN}") { $this->scroll++; if ($this->scroll > $maxScroll) $this->scroll = $maxScroll; $this->redraw($left, $top, $width, $height, $wrapped, $this->title, $maxScroll); } } } return; } private function redraw(int $left, int $top, int $width, int $height, array $wrapped, string $title, int $maxScroll) { $visibleItems = $height - 4; // calculate scrollbar thumb positions $scrollTop = ($this->scroll / ($maxScroll + $visibleItems)); $scrollVisible = $visibleItems / count($wrapped); // / $visibleItems; $scrollBottom = $scrollTop + $scrollVisible; $thumbTop = round($scrollTop * $visibleItems); $thumbBottom = round($visibleItems * $scrollBottom); echo "\e[40;37m"; $this->terminal ->writeAt($left, $top + 0, self::U_CORNER_ROUNDED_TOPLEFT.str_repeat(self::U_EDGE_HORIZONTAL,$width - 2).self::U_CORNER_ROUNDED_TOPRIGHT) ->writeAt($left, $top + 1, self::U_EDGE_VERTICAL.str_repeat(" ",$width - 2).self::U_EDGE_VERTICAL) ->writeAt($left + 2, $top + 1, "\e[1m" . $this->title . "\e[22m") ->writeAt($left, $top + 2, self::U_EDGE_VERTICAL_RIGHT.str_repeat(self::U_EDGE_HORIZONTAL,$width - 2).self::U_EDGE_VERTICAL_LEFT) ->writeAt($left, $top + $height - 1, self::U_CORNER_BOTTOMLEFT.str_repeat(self::U_EDGE_HORIZONTAL,$width - 2).self::U_CORNER_BOTTOMRIGHT) ; for ($n = 0; $n < $visibleItems; $n++) { if (isset($wrapped[$n+$this->scroll])) { $line = $wrapped[$n+$this->scroll]??null; if (str_starts_with($line, "# ")) { $item = " " . mb_substr($line, 2); $pre = "\e[1;4m"; $post = "\e[22;24m"; } elseif (str_starts_with($line, "## ")) { $item = " " . mb_substr($line, 3); $pre = "\e[1m"; $post = "\e[22m"; } elseif (str_starts_with($line, "### ")) { $item = " " . mb_substr($line, 4); $pre = "\e[1;3m"; $post = "\e[23m"; } else { $item = " " . $line; $pre = null; $post = null; } $item = $item . str_repeat(" ", $width - 2 - mb_strlen($item)) . "\e[40;37m"; } else { $item = str_repeat(" ", $width - 2)."\e[40;37m"; } $item = $pre . $item . $post; if ($n >= $thumbTop && $n <= $thumbBottom) { $scrollbar = "\e[97;1m".self::U_EDGE_VERTICAL_THUMB."\e[40;37;22m"; } else { $scrollbar = "\e[37;2m".self::U_EDGE_VERTICAL_SCROLL."\e[40;37;22m"; } $this->terminal ->writeAt($left, $top + 3 + $n, self::U_EDGE_VERTICAL.$item.$scrollbar); } echo "\e[0m"; } }