@@ -891,6 +891,70 @@ Terminal::jump_cursor(int xPos_, int yOffset_)
891891#endif
892892}
893893
894+ #if defined(_WIN32)
895+ bool
896+ Terminal::is_at_beginning_of_the_line (void )
897+ {
898+ CONSOLE_SCREEN_BUFFER_INFO inf;
899+ HANDLE consoleOut (
900+ _consoleOut != INVALID_HANDLE_VALUE ? _consoleOut : GetStdHandle (STD_OUTPUT_HANDLE));
901+ if (!GetConsoleScreenBufferInfo (consoleOut, &inf)) {
902+ return false ;
903+ }
904+ return (inf.dwCursorPosition .X == 0 );
905+ }
906+ #else
907+ bool
908+ Terminal::is_at_beginning_of_the_line (void )
909+ {
910+ // Request cursor position report (DSR) and parse response: ESC [ row ; col R
911+ const char request[] = " \033 [6n" ;
912+ write8 (request, sizeof (request) - 1 );
913+
914+ fd_set rfds;
915+ struct timeval tv;
916+ tv.tv_sec = 0 ;
917+ tv.tv_usec = 200000 ; // 200 ms
918+
919+ std::string resp;
920+ int fd = _in_fd;
921+ char buf[32 ];
922+
923+ while (true ) {
924+ FD_ZERO (&rfds);
925+ FD_SET (fd, &rfds);
926+ int ret = select (fd + 1 , &rfds, nullptr , nullptr , &tv);
927+ if (ret <= 0 ) {
928+ break ; // timeout or error
929+ }
930+ ssize_t n = read (fd, buf, sizeof (buf));
931+ if (n <= 0 ) {
932+ break ;
933+ }
934+ resp.append (buf, buf + n);
935+ if (resp.find (' R' ) != std::string::npos) {
936+ break ;
937+ }
938+ // small additional delay for more data
939+ tv.tv_sec = 0 ;
940+ tv.tv_usec = 50000 ; // 50ms
941+ }
942+
943+ size_t p1 = resp.find (' [' );
944+ size_t p2 = resp.find (' R' );
945+ if (p1 == std::string::npos || p2 == std::string::npos || p2 <= p1) {
946+ return false ;
947+ }
948+ std::string inside = resp.substr (p1 + 1 , p2 - p1 - 1 );
949+ size_t sep = inside.find (' ;' );
950+ if (sep == std::string::npos) {
951+ return false ;
952+ }
953+ int col = atoi (inside.c_str () + sep + 1 );
954+ return (col == 1 ); // DSR is 1-based
955+ }
956+ #endif
957+
894958#ifdef _WIN32
895959void
896960Terminal::set_cursor_visible (bool visible_)
0 commit comments