This a peice of public domain code designed to handle simple character oriented screen access.
You can consider it like curses, only without the swearing.
It has been implemented for DOS, DOS32 (32 bit DOS with CauseWay DOS Extender), 16 bit OS/2, 32 bit OS/2, Win32, various UNIXes (including Linux, AIX, HP-UX, Solaris, MacOSX and iPhone 1.x), Novell NetWare, EFI, and the Amiga.
It has been used by Andys Source Code Folding Editor, Andys Binary Folding Editor, and various other test tools.
Prior to using this code, be sure to call
This specifies the desired screen mode and size.
It returns 0 if it failed, or a non-0 value if it worked.
reflect the screen size.
th_deinit should be called to terminate use of this
In fact this call can be made even if no preceeding initialise call has
The screen mode
MODE_NORMAL is defined on all platforms.
This should be used, unless you have a very specific requirement.
On DOS, DOS32, OS/2 and Win32, TH attempts to save the existing screen mode and contents, so that it can restore them afterwards. On UNIXes, and the Amiga, this isn't possible. On NetWare this isn't worth doing as NetWare NLMs tend to be loaded into their own screen anyway. On EFI, there is no mechanism for this.
When initialising, the screen size desired is specified. Zeroes may be supplied, meaning whatever the current size is.
If you are requesting a screen size that cannot be supported, then
th_init will return 0 and fail.
On DOS and DOS32, a wide variety of screen sizes are supported, by recognising CGA, EGA, VGA and SVGA adapters of various types. There is a document which explains exactly what is supported.
On OS/2, TH is implemented in terms of the
KbdXxxx APIs, and so any size you can set with the MODE
command, TH can also support.
This includes 40 column, 132 column, 60 line etc..
On Win32, TH also supports assorted screen sizes. This can show up problems in Windows 95.
On EFI, a variety of screen modes are supported.
On the Amiga and UNIXes, TH will only run in the current screen size. It will fail any initialisation attempt with a different screen size.
It is very common for programs to simply initialise using the current screen size, and then check to see if the current size is acceptable. They can then fail if the screen is too small or too big. Some programs also give the user the option of invoking them with a desired screen size.
th_setcsr function can be used to set the cursor shape
to one of
CSR_ALT (typically half height), and
This call is fully supported under DOS, DOS32, OS/2, and Win32.
CSR_OFF positions the cursor at the bottom right
of the screen, and any of the others leave the cursor where it should be.
Under UNIX and EFI we have no control over the shape of the cursor.
th_setcol may be used to set the text colour for subsequent
How colours are constructed varies from platform to platform :-
#define ERROR_COLOUR COL(COL_YELLOW,COL_RED,TRUE,FALSE) /* Produces yellow on red, bright yellow, and not flashing. Works for DOS, DOS32, OS/2 and NetWare. */ #define ERROR_COLOUR COL(COL_YELLOW,COL_RED,TRUE,FALSE) /* Produces yellow on red, bright yellow, not bright red. Works on Win32. There are no flashing colours in the Windows Console API. */ #define ERROR_COLOUR COL(COL_YELLOW,COL_RED,COL_STAND) /* Under UNIX says, use yellow on red if the version of curses and the current terminal type supports it. Failing that, revert to using standout mode. */ #define ERROR_COLOUR COL(COL_YELLOW,COL_RED,TRUE) /* Produces yellow on red, bright yellow. Works for EFI. */ #define ERROR_COLOUR COL_3 /* Selects colour 3. Works on Amiga running under Intuition. The Amiga simply provides 4 arbitrary colours. */
COL_RED etc. on any platform that
COL_ALT on UNIX systems.
These mean normal, standout, underlined and alternate-character-set.
On many systems, underline and alternate-character-set do not work.
On all systems
K_CTRL is defined, and provides a common
way of describing the control keys.
K_ESC are also defined.
On all platforms,
K_HOME are defined.
K_Fn are defined for the function keys.
On DOS, DOS32, OS/2, Win32 and UNIX,
K_ALT_c are supported.
K_END are supported,
along with some
Keys can be read using
th_key_read, which blocks until
a key is pressed.
TH for UNIX maps
Esc followed by a key into the
TH for EFI also maps
Esc followed by a key into the Alt+Key
combination, as there is no way to actually receive real Alt+Key keystrokes.
On DOS, DOS32, OS/2, Win32, NetWare and EFI,
This is also supported on Linux, AIX and HP/UX.
This takes a peek at the keyboard buffer and returns 0 if no key is
It returns a non-0 value otherwise,
th_key_read can be used
to retreive the value.
Programmers should avoid polling the keyboard by repeatedly calling
th_key_status, as this can swallow up large quantities of CPU.
th_key_break tests to see if 'break' has been pressed since
the last call to
th_key_break, and resets the flag ready for
the next call.
This is Ctrl+Break on DOS, DOS32, OS/2 and Win32.
On UNIX and NetWare, it is caused by a signal.
EFI does not support this call.
If not supported, this function will always return 0, which means no.
A non-0 value is returned if a 'break' has occurred.
An application might periodically call
during some long interruptable processing.
General text output is acheived using the following routines :-
void th_beep(void); void th_cls(void); void th_cxy(int x, int y); void th_cy(int y); void th_chome(void); void th_inslin(void); void th_dellin(void); void th_deleol(void); void th_isprint(int c); void th_p_raw_chr(int c); void th_p_raw_str(const char *s); void th_p_chr(int c); void th_p_str(const char *s); void th_sync_screen(void);
th_dellin insert and delete a line
at the current cursor position.
The raw print functions are fastest and don't understand things like carriage return and line feed.
th_isprint is fed a character value, in the range 0 to 255,
and it returns non-0 if the character is 'printable'.
Only standard ASCII printable characters (codes 32 to 126) are guaranteed
to be 'printable'.
With other characters, you take operating system specific pot luck.
Printable characters may be output using the raw print routines.
Printable characters and also '\n', '\r', '\t' and '\b' may be output using the non-raw print routines. '\n' moves to a new line, '\r' moves to the start of the current line, '\t' outputs spaces until the next 8 character tab stop is reached and '\b' backspaces. None of these special characters cause their glyph to be displayed - to do that they must be printable, and you must the raw print routines.
th_sync_screen entrypoint ensures the screen data
recently written is flushed and is therefore visible on the screen.
This call is rarely necessary, as a call to
th_key_status implicitly causes this to happen also.
On UNIXes it is often the case that the bottom right hand character cannot be written to (because this would cause an unwanted screen scroll).
On EFI, the bottom right hand character cannot be written to.
When writing simple windowing layers using TH, it becomes necessary to save an area of the screen for later restore. Under DOS, DOS32, OS/2, Win32, NetWare and EFI, support for this has been implemented.
Support for saving and restoring is currently only present in the AIX Extended Curses variant of UNIX.
If the symbol
TH_SAVE_RESTORE_CELL is defined, it states
how many bytes are needed per character when saving a part of the screen.
th_save can be used to save some characters on display.
The format of data saved is platform specific, and may only be used to restored to an area of the screen of the same length.
th_restore is used to restore the screen.
Some imaginary, simplified, sample code :-
#ifdef TH_SAVE_RESTORE_CELL char *buf = malloc(21*TH_SAVE_RESTORE_CELL); th_save(5,4,21,buf); th_cxy(5,4); th_p_raw_str("This won't last long!"); th_restore(5,4,21,buf); free(buf); #else #error Can't support saving and restoring on this platform - yet #endif
The DOS versions set screen modes using BIOS Int-16h calls, and do direct screen memory access. Keyboard access is done via BIOS Int-10h calls. The 16 bit real mode DOS version supports VESA modes, but the 32 bit protected mode DOS32 version does not.
The OS/2 versions use the OS/2
The Win32 version uses the Win32 Console API. It works around a number of bugs present only in the Windows 95 version of this API.
The NetWare version uses the windowing API provided by the NetWare
The EFI version uses the simple text input and output protocols, and they certainly live down to their name.
The Linux version uses ncurses.
The AIX version of TH can be compiled to use AIX Extended Curses which is is supported on AIX 4.x and AIX 5.x (32 bit compilation mode only). Or, it can be compiled using AIX Curses (which is now much in line with other UNIXes implementation of Curses) which is supported on AIX 4.3 and later, including AIX 5.x in both 32 bit and 64 bit modes.
The HP-UX version uses Color Curses.
Other UNIXes just use vanilla curses.
The iPhone or iPod Touch use MacOSX Mobile, which is a kind of stripped
down MacOSX, which is derived from Darwin, which in turn comes from BSD.
On this platform
TERM is set to
If you change this, you can cause programs to crash, or even the whole
iPhone to hang so badly a power-off/on isneeded.
This is thought to be because the iPhone doesn't deliver a terminfo database
The curses implementation appears to have a hard coded understanding of the
network terminal type.
As a consequence, despite the Terminal application running on the iPhone
supporting ANSI color escape sequences, applications using TH (which uses
curses) will not use color.
This is also true when someone using a local terminal with color support
ssh to enter an iPhone, and runs a program there.
A program simply includes
th.h, and links to the
|C compiler flags
|TH Library name, link flags
|16 bit OS/2
|32 bit OS/2
|AIX Extended Curses
-DUNIX -DAIX -DAIX_EXTENDED_CURSES
th.a, -lcur -lcurses
-DUNIX -DAIX -DAIX_CURSES
th.a, -lcurses -ltermcap
Note that the compiler flags are used both when compiling TH, and programs that use it.