Download from
http://www.nyangau.org/th/th.zip
.
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 th_init
.
This specifies the desired screen mode and size.
It returns 0 if it failed, or a non-0 value if it worked.
Afterwards, the x_size
and y_size
variables
reflect the screen size.
th_deinit
should be called to terminate use of this
module.
In fact this call can be made even if no preceeding initialise call has
been done.
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 VioXxxx
and
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.
The th_setcsr
function can be used to set the cursor shape
to one of CSR_BLOCK
, CSR_ULINE
,
CSR_ALT
(typically half height), and CSR_OFF
(ie: invisible).
This call is fully supported under DOS, DOS32, OS/2, and Win32.
Under UNIX, 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
text output.
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. */
th.h
defines COL_RED
etc. on any platform that
supports colour.
It defines COL_NORM
, COL_STAND
,
COL_ULINE
and 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.
Typically K_BS
, K_TAB
. K_CR
,
K_LF
and K_ESC
are also defined.
On all platforms, K_LEFT
, K_RIGHT
,
K_UP
, K_DOWN
and K_HOME
are defined.
K_Fn
are defined for the function keys.
On DOS, DOS32, OS/2, Win32 and UNIX, K_SHIFT_Fn
,
K_CTRL_Fn
, K_ALT_Fn
, K_ALT_n
,
K_ALT_c
are supported.
Also K_PGUP
, K_PGDN
, K_INSERT
,
K_DELETE
and K_END
are supported,
along with some K_CTRL_
and K_ALT_
variants
of them.
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
Alt+key combination.
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, th_key_status
is
provided.
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
available.
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 th_key_break
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_inslin
and 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.
The 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_read
or 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 VioXxxx
and
KbdXxxx
APIs.
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
conio.h
header.
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 network
.
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
or library.
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
uses ssh
to enter an iPhone, and runs a program there.
A program simply includes th.h
, and links to the
TH library.
Operating System | C compiler flags | TH Library name, link flags |
---|---|---|
DOS | -DxxDOS | LTHR.LIB
|
DOS32 | -DDOS32 | TH.LIB
|
16 bit OS/2 | -DO16 | LTHP.LIB
|
32 bit OS/2 | -DOS2 | TH.LIB
|
Win32 | -DWIN32 | TH.LIB
|
NetWare | -DNW | TH.LIB
|
EFI | -DEFI | th.o
|
Linux | -DUNIX -DLINUX | th.a, -lncurses
|
AIX Extended Curses | -DUNIX -DAIX -DAIX_EXTENDED_CURSES | th.a, -lcur -lcurses
|
AIX Curses | -DUNIX -DAIX -DAIX_CURSES | th.a, -lcurses
|
HP-UX | -DUNIX -DHP | th.a, -lcur_colr
|
Solaris | -DUNIX -DSUN | th.a, -lcurses -ltermcap
|
Xenix | -DUNIX -DXNX | th.a, -ltermcap
|
Note that the compiler flags are used both when compiling TH, and programs that use it.