If you want to see more Frequently Given Answers then enable the navigation bar support in your WWW browser, and hit your WWW browser's "Up" button. You can navigate all around this WWW site with your navigation bar. Your navigation bar will also enable you to more easily navigate to a specific section on this page, as all of the sections are listed on it.

How one goes about clearing the screen in a TUI program.

There's a lot of incorrect or misleading information on how to perform what is on the face of it a very simple task: clearing the screen in a TUI program. This is the Frequently Given Answer to the question:

How do I clear the screen (in a C or C++ TUI program)?

(You can find a different approach to this answer written by Michael Thomas Greer.)

This Frequently Given Answer only addresses TUI programs. Clearing the screen in a GUI program is a very different kettle of fish, and one that doesn't even exist at all as a concept in several GUI systems.

Common mistakes to avoid

There are several widely-touted ways of clearing the screen that are, quite simply, wrongheaded. They won't work in the general case, and are fragile. There's lots of advice handed around that involves them, but in the main this is advice given by people who didn't actually read their programmers' documentation to find out the right ways to clear the screen, but instead found a quick bodge that just happened to work on the one or two machines that they tried.

Common mistake: Running a CLS command

One common mistake to avoid is using the system() standard library function to clear the screen, executing either of:

There are a large number of things wrong with this approach:

Moreover: All of the aforementioned is to gloss over the fact that this is a grossly inefficient way of clearing the screen, an operation that, as we shall see, can be done quite simply, in-process with system API or library function calls, without the overhead of spawning one — possibly two — entirely separate processes, with all of their setup and teardown overheads, to achieve the goal.

Common mistake: Writing ANSI escape sequences or lots of newlines

One common mistake to avoid is writing strings of characters to standard output (or some other appropriate I/O stream) that are simply hardwired into the program code. The simplest form of this is writing the ASCII FF (Form Feed) character:

fputc('\x0C', stdout) ;

But there are several variations, such as hardwiring the escape sequence for ANSI terminals:

fputs("\x1B[2J", stdout) ;

Or writing large numbers of newlines:

for ( unsigned i = 100 ; i > 0 ; --i )
    puts("") ;

These approaches suffer from four fundamental errors:

By the way: If one reads the C standard one finds that it makes no real guarantees about the '\f' escape sequence. It merely states the intention that it have the display semantics, if written to a C stream attached to a display device, of moving "to the initial position at the start of the next logical page". The C standard is deliberately vague as to the semantics of, and even the execution character set value represented by, '\f'. This is for many of the same reasons as laid out above. There's no guarantee that there's a way to clear a screen. There's no guarantee that if there is a way that it will be a single control character. And there's no guarantee that that control character is even the same for all terminal communications protocols on the target platform.

Common mistake: Mistaking the DOS API for a general API

One common mistake to avoid is mistaking the the DOS system API for a general API. The symptom of this mistake is using the <conio.h> header and thinking that one has a clrscr() function:

#include <conio.h>
…
clrscr() ;

The <conio.h> header properly forms one part of the C and C++ language bindings to the DOS system API. It isn't a standard library facility, and shouldn't be mistaken for one. It's part of the language bindings for a specific platform's API.

Ironically, the clrscr() function that is declared in the <conio.h> header in some DOS C and C++ language compilers isn't even a DOS API facility in the first place. As will be shown later, clearing the screen on PC/MS/DR-DOS isn't done through an operating system API function at all. The operating system has no functions for doing this, and no guaranteed capability in its CON: device for supporting ANSI standard control character sequences, either.

The clrscr() function is one of Borland's extensions to the DOS API bindings. They don't exist in all DOS C and C++ compilers, and don't necessarily exist in porting libraries for compilers that target other platforms. It's a mistake to think that a clrscr() function will be always available on every DOS compiler. It's a mistake to think that it will be available on compilers that aren't targetting PC/MS/DR-DOS. It's even a mistake to think that it's better to write new code that uses a porting library aimed at providing source-level compatibility with Borland C/C++ for DOS programs, than to just write that new code to directly use the native mechanisms provided on the platform that one is targetting.

The correct way to clear the screen

The correct way to clear the screen varies from platform to platform. Operating systems have differing paradigms for TUI programs. Clearing the screen involves platform-specific code, that is not general across multiple platforms. Any program that expects to clear the screen on multiple platforms will either contain conditional compilation or platform-specific libraries.

Platforms can be grouped into two broad categories, platforms with "consoles" and platforms with "terminals", according to the paradigms that they present to TUI programs. These are not firm divisions, and several platforms are admixtures of the two approaches. The procedures for clearing the screen on each of the paradigms are:

Clearing the screen on OS/2

OS/2 primarily provides a "console" paradigm to applications softwares. The 16-bit console API is the so-called KBD/VIO/MOU API. There's no IBM-provided 32-bit console API, but there is an add-on 32-bit Unicode Console API that pure 32-bit programs can use. Whatever the API, as mentioned earlier, the procedures for clearing the screen follow two basic patterns, scrolling or filling.

For the 32-bit Unicode Console API, clearing the screen involves the DosQueryConsoleWindow(), DosScrollConsoleUp(), DosWriteConsoleOutputNCell(), and DosSetConsoleCursorPos() API functions, as follows:

Note that the above code clears the console window, not the entire screen buffer. On current versions of OS/2, the two are effectively coterminous, and clearing the console window will clear the entire screen. However, it is possible that in a future API the two will be separated, as they are in Win32 (more on which later), in which case the above code is future-proof.

For the 16-bit KBD/VIO/MOU API, clearing the screen involves the VioGetMode(), VioScrollUp(), VioWrtNCell(), and VioSetCurPos() API functions, as follows:

Note that this code is not future-proof, as the 32-bit Unicode Console API code is. It will always clear the entire screen buffer.

OS/2 also provides a "dumb TTY" interface to consoles, with a terminal communications protocol that follows a limited subset of the ANSI standard, including the ESC+'['+'2'+'J' escape sequence for clearing the screen. However, ANSI support can be turned on and off for OS/2 consoles. In order to detect whether it is currently on or off one calls the DosQueryConsoleMode() (32-bit API) or the VioGetAnsi() (16-bit API) functions, in which case one is invoking the platform-specific API anyway, and might as well use that API itself, rather than mucking around with escape sequences at all.

Clearing the screen on Win32

Win32 primarily provides a "console" paradigm to applications softwares. As mentioned earlier, the procedures for clearing the screen follow two basic patterns, scrolling or filling. Clearing the screen involves the GetConsoleScreenBufferInfo(), FillConsoleOutputCharacter(), FillConsoleOutputAttribute(), ScrollConsoleScreenBuffer(), and SetConsoleCursorPosition() API functions, as follows:

Note that the above code clears the console window, not the entire screen buffer. This accomodates TUI programs with "scroll back" capabilities. Under the scroll back conventions, the console window is always at the bottom of the console screen buffer, and the area of the screen buffer that is above the window is the "scroll back" area. Alternative clear screen procedures, that don't enable "scroll back" areas and that clear the entire screen buffer, are described in Microsoft KnowledgeBase article 99261.

Clearing the screen on POSIX systems

POSIX provides a "terminal" paradigm to applications softwares. As standard, this includes a set of "terminfo" library functions, for accessing a database of terminal information, indexed by terminal type and function. Many POSIX systems also include the older "termcap" library, which does the same thing except in a slightly different way. It is the "terminfo" library that is standardized.

The procedure is very simple and involves the setupterm(), tigetstr(), and putp() API functions:

  1. Ensure that the program has initialized the "terminfo" library, by executing the following at some point before one needs to clear the screen:

    #include <term.h>
    …
    setupterm(NULL, fileno(stdout), NULL) ;
  2. Read and output the appropriate control character sequence:

    #include <term.h>
    …
    putp(tigetstr("clear")) ;

Usually, TUI applications on POSIX systems employ some form of "curses" library, which is layered on top of the raw "terminfo" library. Clearing the screen with curses is simply a matter of obtaining a full-screen window (such as the result of the initscr() function) and calling:

#include <curses.h>
…
wclear(window) ;
wrefresh(window) ;

Technically, it's possible to gain direct access to terminal screen buffers on GNU Hurd and Linux, and use the "console" paradigm. On Hurd, for example, the /hurd/console dæmon provides device files that allow direct access, via read() and write(), to the character cells of a virtual console's screen buffer. However, these mechanisms are very much non-portable, and not even general-purpose. Several platforms, most notably the BSDs and Solaris, don't have them; they differ in their exact mechanics from platform to platform; and even within any given single platform they only apply to the terminal devices that are actually displayed on the machine's display adapter. (They don't exist at all for serial terminal devices, for pseudo-terminals as used by xterm and the like, or for the "raw", non-virtualized, terminal device provided by Hurd's /hurd/term dæmon on /dev/console.)

Clearing the screen on PC/MS/DR-DOS

PC/MS/DR-DOS provides no system API function for clearing the screen. Although it has a "CON:" device that is capable of responding to ANSI escape sequences, that device is contained within an optional installable device driver, ANSI.SYS. This installable device driver usurps the built-in "CON:" that PC/MS/DR-DOS contains by default, which does not support ANSI escape sequences. Unlike OS/2, which has one "CON:" device whose support for ANSI escape sequences can be turned on and off at run-time by applications, with (vanilla) PC/MS/DR-DOS one fixes the support for ANSI escape sequences at operating system IPL time. (There are several after-market TSR programs that can load and unload ANSI escape sequence support. But even they cannot switch it on and off whilst a single applications program is running; and they don't come as standard with the operating system.)

PC/MS/DR-DOS programs therefore have two avenues of approach for clearing the screen: directly accessing the video RAM or using firmware API functions. These two approaches are built into the Borland C/C++ for DOS clrscr() function, mentioned earlier, which in fact selects between these very two approaches, according to the setting of the directvideo global variable. Both approaches have their disadvantages.

Direct access to video RAM in PC/MS/DR-DOS involves far more complexities than direct access to a console screen buffer does on OS/2 or Win32. Whilst OS/2 and Win32 consoles provide an abstraction of an array of character cells, direct access to video RAM hardware on PC/MS/DR-DOS does not. An application performing direct access therefore has to be aware of whether the display adapter is in text or graphics mode, and which particular mode that is. The mode selection determines both the exact mechanism for writing to video RAM and where in the system memory map the video RAM even is. PC/MS/DR-DOS programs have to accommodate monochrome display adapters (and (S)VGA display adapters emulating them), Hercules display adapters, CGA display adapters, EGA adapters in graphics mode, and (S)VGA display adapters in graphics mode, all of which have subtly or indeed blatantly different mechanisms for direct access to the video hardware.

The subject of direct video access by PC/MS/DR-DOS softwares is too extensive for this Frequently Given Answer. There are books on PC/MS/DR-DOS applications programming that devote entire chapters to just this, including lengthy source listings of how to detect what display adapter hardware is present and how to access it in the several modes that it is possible for the hardware to be in. Two of the better ones are:

Of course, the PC/AT firmware was intended to abstract all of this away in the first place. And as long as one doesn't worry too much about graphics modes, it can and does when it comes to clearing the screen. Clearing the screen using the PC/AT firmware API is done in much the same way as with the "console" APIs in OS/2 and Win32, as a matter of fact. One either scrolls the screen buffer by as many lines as it contains, or fills the screen buffer with a single given character and attribute pair; in both cases setting the cursor position, maintained by the firmware, to the top-left-hand corner of the screen as well.

How one accesses the PC/AT firmware API from the C and C++ languages when targetting PC/MS/DR-DOS is entirely compiler-dependent. The API is not designed to be directly callable as a high-level language function. That idea came later on in the world of the IBM PC/AT compatible. Here's a version of the cls() and gotoxy() functions, taken from chapter 5 of the aforementioned DOS Programmer's Reference and adapted to OpenWatcom C/C++, which in combination implement the "Scrolling" method of clearing the screen:

void cls () ;
#pragma aux cls =               \
    "push ds"                   \
    "push es"                   \
    "mov ax, 0600h"             \
    "mov bh, 07h"               \
    "mov cx, 0000h"             \
    "mov dx, 1950h"             \
    "int 10h"                   \
    "pop es"                    \
    "pop ds"                    \
    parm []                     \
    value []                    \
    modify [ax bx cd dx]        ;

void gotoxy(uint8_t x, uint8_t y) ;
#pragma aux gotoxy =            \
    "push ds"                   \
    "push es"                   \
    "mov ah, 02h"               \
    "mov bh, 00h"               \
    "int 10h"                   \
    "pop es"                    \
    "pop ds"                    \
    parm [dl] [dh]              \
    value []                    \
    modify [ax bx cd dx]        ;

Note that this code is hardwired for writing the space character, in white on black, for 80 columns and 25 rows. Parameterizing it is left as an exercise for the reader. Note also that, as with OS/2, the PC/AT firmware API makes no provision for separating the concepts of a screen buffer from a console window, and thus there is no standard "scroll back" convention in PC/MS/DR-DOS programs.


© Copyright 2010 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.