Clear the Screen

Difficulty: ★ ☆ ☆ ☆

If you’ve studied the terminal window at any length, you probably know about the clear command, which clears the screen. Under MS-DOS, and on my old TRS-80, the command is cls. Same thing.

Clearing the screen is a visual effect for a modern terminal window. Those terminals with a scroll-back buffer retain all the previous text output. But the visible screen is wiped clear of all text, the cursor flown to the upper left corner, with only the command prompt visible.

In my programming travels, I’ve witnessed a few dorky ways to clear the screen. Perhaps the most stupid was a program that just output a series of blank newlines. While this effect removed text from the screen, it didn’t “home” the cursor. No, the cursor remained squat in the lower left corner where I didn’t wanted it.

C uses streaming I/O, so it doesn’t care about clearing the screen. When you think about streaming I/O historically, how would you clear the “screen” on a teletype? The answer is that you can’t, though a command was available to eject a page: Ctrl+L. ASCII code 12 still ejects a page on modern printers. On some terminals, outputting a Ctrl+L character clears the terminal screen — but not all.

To clear the screen on a Linux terminal, you can output one or more ANSI escape codes. I’ve covered ANSI codes a few times in this blog, for example to output inverse text. You can use similar codes to clear the screen.

Rather than have you hunt for ANSI codes to output, I’ve included a few screen and cursor manipulation codes for your reference in the following table.

Code Description
\f Form feed / New Page
\e[H Move cursor to home position (0,0)
\e[0J Erase from cursor to the end of the screen
\e[1J Erase from cursor to the beginning of the screen
\e[2J Erase the entire screen
\e[3J Erase saved lines
\e[0K Erase from the cursor to the end of the line
\e[2K Erase the entire line

Your task for this month’s exercise, is to output one or more ANSI codes to clear the screen. Put your solution into a function called cls(), in honor of MS-DOS. Here is a code skeleton to get you started:

2024_07_01-Lesson.c

#include <stdio.h>

void cls(void)
{
    /* output ANSI code(s) here */
}

int main()
{
    printf("Prepare to clear the screen!");
    getchar();
    cls();

    return 0;
}

Please try this exercise on your own before you check out my solution.

3 thoughts on “Clear the Screen

  1. Having been busy the last couple of weeks, I followed your blog posts but didnʼt comment on them… now that I have a little more free time, I thought I might as well try the above exercise.

    After some further investigation it looked like this should be relatively easy to do—for example like so:

      printf("\x1B[39;49m"); // Set default foreground & background color
      printf("\x1B[2J");     // Clear the visible window
      printf("\x1B[3J");     // Clear the scroll back
      printf("\x1B[H");      // Reposition cursor to left upper corner.

    Or, alternatively, to simply reset the terminal:

      printf("\x1B%c", 'c'); // Terminal reset

    Turns out that since Windows 10, version 1511 (public release on November 12, 2015) Windows also supports ANSI escape sequences, once the ENABLE_VIRTUAL_TERMINAL_PROCESSING console mode flag is enabled—on a per-process basis—like so:

      DWORD console_mode;
      HANDLE hConsole = GetStdHandle (STD_OUTPUT_HANDLE);
      GetConsoleMode (hConsole, &console_mode);
      SetConsoleMode (hConsole, console_mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    The above, however, will fail if the user has redirected ‘stdout’… for example:

      $ ./myclear > /dev/null

    To take this possibility into account, my solution relies on isatty(stdout); to check if ‘stdout’ is, in fact, connected to the controlling terminal… otherwise, I use the following code to open a FILE * that can be used to write to the screen even if I/O redirections are in effect:

      [__linux__] stdout_file = fopen("/dev/tty", "w");
      [_WIN32]    stdout_file = fopen("CONOUT$", "w");

    Now, because I have a PC that refuses to die, I too am one of those people who still run Windows 8.1 on their home computer: what about there?

    To support older Windows clients as well I wrote code that relies on ntdll.dllʼs RtlGetVersion() function to populate the Windows APIʼs OSVERSIONINFOEX structure with the major and minor version number (as well as build number) of the running operating system.

    If dwMajorVersion.dwMinorVersion.dwBuildNumber is less than 10.0.10586, then the console window is cleared by invoking the following 4 functions (as outlined in this Microsoft Learn article):

      GetConsoleScreenBufferInfo();
      FillConsoleOutputCharacter();
      FillConsoleOutputAttribute();
      SetConsoleCursorPosition();

    … with the added complication that the "DefaultColor" value of the "SOFTWARE\\Microsoft\\Command Processor" key in the Windows registry has to be queried for the default color the user wants cmd.exe windows to be cleared with.

    I uploaded project files for Codelite (Linux) as well as Visual Studio (Windows) on GitHub (should anyone be interested): https://tinyurl.com/bdez3f9y

  2. Pretty cool stuff – as usual!

    I was going to do a series on Windows Console Programming. I may still do it.

  3. A series on Windows Console Programming sounds interesting!

    Especially, since the new conhost driver not only supports ANSI escape sequences but (with that) also complete RGB values for foreground as well as background.

    If one wanted to really stretch things, this should make it possible to even develop quite respectable ASCII image viewers and movie players 😉

    Also, while I havenʼt really looked into any of this, it could be interesting to know how the “new” Windows Pseudo Console plays into all of this.

Leave a Reply