How to get coordinates of first displayed line in windows relatively to DATA-BUFFER ? #23503

Closed
opened 2026-01-31 08:44:06 +00:00 by claunia · 2 comments
Owner

Originally created by @schlebe on GitHub (Aug 5, 2025).

Description of the new feature

where DATA-BUFFER contains all rows displayed and all rows that has been displayed before and that are currently only visible in scrolling console vertically.

My question with more explanation can be found on StackOverflow on https://stackoverflow.com/questions/79725603/on-windows-terminal-in-visual-c-how-can-i-overwrite-previous-lines

Proposed technical implementation details

No response

Originally created by @schlebe on GitHub (Aug 5, 2025). ### Description of the new feature where DATA-BUFFER contains all rows displayed and all rows that has been displayed before and that are currently only visible in scrolling console vertically. My question with more explanation can be found on StackOverflow on [https://stackoverflow.com/questions/79725603/on-windows-terminal-in-visual-c-how-can-i-overwrite-previous-lines ](https://stackoverflow.com/questions/79725603/on-windows-terminal-in-visual-c-how-can-i-overwrite-previous-lines ) ### Proposed technical implementation details _No response_
claunia added the Issue-FeatureNeeds-TriageNeeds-Tag-Fix labels 2026-01-31 08:44:06 +00:00
Author
Owner

@DHowett commented on GitHub (Aug 5, 2025):

I see that you are combining the Windows Console APIs with the use of Virtual Terminal sequences.

I wonder if you would be able to use the Virtual Terminal sequences for cursor positioning, rather than trying to move the cursor directly in the coordinate system.

You can move the cursor up one line relative to the current position (X stays the same, Y decrements) with \x1b[1A.

CSI Ps A Cursor Up Ps Times (default = 1) (CUU).

You can move the cursor to the beginning of the previous line (X = 0, Y decrements) with \x1b[1F

CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL).

Does that help?

@DHowett commented on GitHub (Aug 5, 2025): I see that you are combining the Windows Console APIs with the use of Virtual Terminal sequences. I wonder if you would be able to use the Virtual Terminal sequences for cursor positioning, rather than trying to move the cursor directly in the coordinate system. You can move the cursor up one line relative to the current position (X stays the same, Y decrements) with `\x1b[1A`. > `CSI Ps A Cursor Up Ps Times (default = 1) (CUU).` You can move the cursor to the beginning of the previous line (X = 0, Y decrements) with `\x1b[1F` > `CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL).` Does that help?
Author
Owner

@schlebe commented on GitHub (Aug 5, 2025):

No !
Using proposed Virtual Terminal sequences don't help me.

Why ?

Because some times length of filename is greater than 1 row !
CSI Ps A or CSI Ps F don't move the cursor 1 line as written in documentation but only 1 row !

I think that there exists some confusion in documentation that use "Line" word to describe "Row" objects !
For me, a line is a string of character terminated by "\n" or "\r\n".

I have also tested using Save/Restore ANSI and not ANSI cursor position but this doesn't work correclty.

Here is a part of my test code

    COORD oCurrentCoord;
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    int iPreviousLineLen; 
    
    // clear screen
    wprintf(L"\x1b[2J");
    // set cursor on first line
    wprintf(L"\x1b[0;0H");

    PrintToConsole("// BS2EDT.Sources");
    PrintToConsole("//   Commands");
    PrintToConsole("//     LineCommands");

    oCurrentCoord = GetConsoleCursorPositionx();
    PrintToConsole("++ CmdDeleteLine.cpp");

    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSplitLine.cpp");

    oCurrentCoord = GetConsoleCursorPositionx();
    oCurrentCoord.Y -= 1;
    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSwitchLine.cpp");

    // print one line upper
    wprintf(L"\x1b[1F");
    // save cursor position for next file
    wprintf(L"\x1b7");
    PrintToConsole("++ CmdWriteFile.cpp");

    // save cursor position
    wprintf(L"\x1b8");
    PrintToConsole("++ CmdWriteText.cpp");

    PrintToConsole("");
    PrintToConsole("// BS2EDT.Sources");
    PrintToConsole("//   Commands");
    PrintToConsole("//     LineCommands");

    oCurrentCoord = GetConsoleCursorPositionx();
    PrintToConsole("++ CmdDeleteLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp");

    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSplitLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp");

    oCurrentCoord = GetConsoleCursorPositionx();
    oCurrentCoord.Y -= 1;
    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSwitchLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp");

    // print one line upper
    wprintf(L"\x1b[1F");
    // save cursor position for next file
    //wprintf(L"\x1b7");
    wprintf(L"\x1b[s");
    PrintToConsole("++ CmdWriteLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp");

    // save cursor position
    //wprintf(L"\x1b8");
    wprintf(L"\x1b[u");
    PrintToConsole("++ CmdWriteText.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp");

    // set cursor on last line
    wprintf(L"\x1b[28;0H");

    PrintToConsole("// BS2EDT.Sources");
    PrintToConsole("//   Commands");
    PrintToConsole("//     LineCommands");

    oCurrentCoord = GetConsoleCursorPositionx();
    PrintToConsole("++ CmdDeleteLine.cpp");

    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSplitLine.cpp");

    oCurrentCoord = GetConsoleCursorPositionx();
    oCurrentCoord.Y -= 1;
    SetConsoleCursorPositionx(oCurrentCoord);
    PrintToConsole("++ CmdSwitchLine.cpp");

    // print one line upper
    wprintf(L"\x1b[1F");
    // save cursor position for next file
    //wprintf(L"\x1b7");
    wprintf(L"\x1b[s");
    PrintToConsole("++ CmdWriteFile.cpp");

    // save cursor position
    //wprintf(L"\x1b8");
    wprintf(L"\x1b[u");
    PrintToConsole("++ CmdWriteText.cpp");

and the result

Image

The code of functions used in my test is following

int PrintToConsole(const char* szLine)
    {
    //Clear line completetly before overwriting it with new line
    wprintf(L"\x1b[100K");
    cout << szLine << endl;
    return strlen(szLine);
    }

COORD GetConsoleCursorPositionx()
    {
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO infoConsole;

    GetConsoleScreenBufferInfo(
        hStdout,
        &infoConsole);

    return infoConsole.dwCursorPosition;
    }

void SetConsoleCursorPositionx(COORD dwCursorPosition)
    {
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleCursorPosition(hStdout, dwCursorPosition);
    }


@schlebe commented on GitHub (Aug 5, 2025): No ! Using proposed Virtual Terminal sequences don't help me. Why ? Because some times length of filename is greater than 1 row ! CSI Ps A or CSI Ps F don't move the cursor 1 line as written in documentation but only 1 row ! I think that there exists some confusion in documentation that use "Line" word to describe "Row" objects ! For me, a line is a string of character terminated by "\n" or "\r\n". I have also tested using `Save/Restore` ANSI and not ANSI cursor position but this doesn't work correclty. Here is a part of my test code ```cpp COORD oCurrentCoord; HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); int iPreviousLineLen; // clear screen wprintf(L"\x1b[2J"); // set cursor on first line wprintf(L"\x1b[0;0H"); PrintToConsole("// BS2EDT.Sources"); PrintToConsole("// Commands"); PrintToConsole("// LineCommands"); oCurrentCoord = GetConsoleCursorPositionx(); PrintToConsole("++ CmdDeleteLine.cpp"); SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSplitLine.cpp"); oCurrentCoord = GetConsoleCursorPositionx(); oCurrentCoord.Y -= 1; SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSwitchLine.cpp"); // print one line upper wprintf(L"\x1b[1F"); // save cursor position for next file wprintf(L"\x1b7"); PrintToConsole("++ CmdWriteFile.cpp"); // save cursor position wprintf(L"\x1b8"); PrintToConsole("++ CmdWriteText.cpp"); PrintToConsole(""); PrintToConsole("// BS2EDT.Sources"); PrintToConsole("// Commands"); PrintToConsole("// LineCommands"); oCurrentCoord = GetConsoleCursorPositionx(); PrintToConsole("++ CmdDeleteLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp"); SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSplitLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp"); oCurrentCoord = GetConsoleCursorPositionx(); oCurrentCoord.Y -= 1; SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSwitchLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp"); // print one line upper wprintf(L"\x1b[1F"); // save cursor position for next file //wprintf(L"\x1b7"); wprintf(L"\x1b[s"); PrintToConsole("++ CmdWriteLine.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp"); // save cursor position //wprintf(L"\x1b8"); wprintf(L"\x1b[u"); PrintToConsole("++ CmdWriteText.Very-Long-File-Name.Very-Long-File-Name.Very-Long-File-Name.Very-Long-FileName.Very-Long-FileName.Very-Long-FileName.cpp"); // set cursor on last line wprintf(L"\x1b[28;0H"); PrintToConsole("// BS2EDT.Sources"); PrintToConsole("// Commands"); PrintToConsole("// LineCommands"); oCurrentCoord = GetConsoleCursorPositionx(); PrintToConsole("++ CmdDeleteLine.cpp"); SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSplitLine.cpp"); oCurrentCoord = GetConsoleCursorPositionx(); oCurrentCoord.Y -= 1; SetConsoleCursorPositionx(oCurrentCoord); PrintToConsole("++ CmdSwitchLine.cpp"); // print one line upper wprintf(L"\x1b[1F"); // save cursor position for next file //wprintf(L"\x1b7"); wprintf(L"\x1b[s"); PrintToConsole("++ CmdWriteFile.cpp"); // save cursor position //wprintf(L"\x1b8"); wprintf(L"\x1b[u"); PrintToConsole("++ CmdWriteText.cpp"); ``` and the result <img width="1115" height="723" alt="Image" src="https://github.com/user-attachments/assets/fb91851f-cfd8-46a5-8c8f-60639fc25541" /> The code of functions used in my test is following ```ccp int PrintToConsole(const char* szLine) { //Clear line completetly before overwriting it with new line wprintf(L"\x1b[100K"); cout << szLine << endl; return strlen(szLine); } COORD GetConsoleCursorPositionx() { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO infoConsole; GetConsoleScreenBufferInfo( hStdout, &infoConsole); return infoConsole.dwCursorPosition; } void SetConsoleCursorPositionx(COORD dwCursorPosition) { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hStdout, dwCursorPosition); } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#23503