summaryrefslogtreecommitdiffstats
path: root/contrib/ncurses/doc/hackguide.doc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ncurses/doc/hackguide.doc')
-rw-r--r--contrib/ncurses/doc/hackguide.doc809
1 files changed, 402 insertions, 407 deletions
diff --git a/contrib/ncurses/doc/hackguide.doc b/contrib/ncurses/doc/hackguide.doc
index e9828d2..ddd7521 100644
--- a/contrib/ncurses/doc/hackguide.doc
+++ b/contrib/ncurses/doc/hackguide.doc
@@ -1,8 +1,7 @@
-
A Hacker's Guide to NCURSES
-
+
Contents
-
+
* Abstract
* Objective of the Package
+ Why System V Curses?
@@ -24,664 +23,660 @@
* Other Utilities
* Style Tips for Developers
* Porting Hints
-
+
Abstract
-
+
This document is a hacker's tour of the ncurses library and utilities.
- It discusses design philosophy, implementation methods, and the
- conventions used for coding and documentation. It is recommended
- reading for anyone who is interested in porting, extending or
+ It discusses design philosophy, implementation methods, and the
+ conventions used for coding and documentation. It is recommended
+ reading for anyone who is interested in porting, extending or
improving the package.
-
+
Objective of the Package
-
+
The objective of the ncurses package is to provide a free software API
for character-cell terminals and terminal emulators with the following
characteristics:
- * Source-compatible with historical curses implementations
+ * Source-compatible with historical curses implementations
(including the original BSD curses and System V curses.
- * Conformant with the XSI Curses standard issued as part of XPG4 by
+ * Conformant with the XSI Curses standard issued as part of XPG4 by
X/Open.
- * High-quality -- stable and reliable code, wide portability, good
+ * High-quality -- stable and reliable code, wide portability, good
packaging, superior documentation.
- * Featureful -- should eliminate as much of the drudgery of C
+ * Featureful -- should eliminate as much of the drudgery of C
interface programming as possible, freeing programmers to think at
a higher level of design.
-
- These objectives are in priority order. So, for example, source
- compatibility with older version must trump featurefulness -- we
- cannot add features if it means breaking the portion of the API
+
+ These objectives are in priority order. So, for example, source
+ compatibility with older version must trump featurefulness -- we
+ cannot add features if it means breaking the portion of the API
corresponding to historical curses versions.
-
+
Why System V Curses?
- We used System V curses as a model, reverse-engineering their API, in
+ We used System V curses as a model, reverse-engineering their API, in
order to fulfill the first two objectives.
-
- System V curses implementations can support BSD curses programs with
+
+ System V curses implementations can support BSD curses programs with
just a recompilation, so by capturing the System V API we also capture
BSD's.
-
- More importantly for the future, the XSI Curses standard issued by
- X/Open is explicitly and closely modeled on System V. So conformance
+
+ More importantly for the future, the XSI Curses standard issued by
+ X/Open is explicitly and closely modeled on System V. So conformance
with System V took us most of the way to base-level XSI conformance.
-
+
How to Design Extensions
- The third objective (standards conformance) requires that it be easy
- to condition source code using ncurses so that the absence of
+ The third objective (standards conformance) requires that it be easy
+ to condition source code using ncurses so that the absence of
nonstandard extensions does not break the code.
-
- Accordingly, we have a policy of associating with each nonstandard
- extension a feature macro, so that ncurses client code can use this
- macro to condition in or out the code that requires the ncurses
+
+ Accordingly, we have a policy of associating with each nonstandard
+ extension a feature macro, so that ncurses client code can use this
+ macro to condition in or out the code that requires the ncurses
extension.
-
- For example, there is a macro NCURSES_MOUSE_VERSION which XSI Curses
- does not define, but which is defined in the ncurses library header.
+
+ For example, there is a macro NCURSES_MOUSE_VERSION which XSI Curses
+ does not define, but which is defined in the ncurses library header.
You can use this to condition the calls to the mouse API calls.
-
+
Portability and Configuration
-
- Code written for ncurses may assume an ANSI-standard C compiler and
- POSIX-compatible OS interface. It may also assume the presence of a
+
+ Code written for ncurses may assume an ANSI-standard C compiler and
+ POSIX-compatible OS interface. It may also assume the presence of a
System-V-compatible select(2) call.
-
+
We encourage (but do not require) developers to make the code friendly
to less-capable UNIX environments wherever possible.
-
- We encourage developers to support OS-specific optimizations and
+
+ We encourage developers to support OS-specific optimizations and
methods not available under POSIX/ANSI, provided only that:
- * All such code is properly conditioned so the build process does
+ * All such code is properly conditioned so the build process does
not attempt to compile it under a plain ANSI/POSIX environment.
- * Adding such implementation methods does not introduce
+ * Adding such implementation methods does not introduce
incompatibilities in the ncurses API between platforms.
-
- We use GNU autoconf(1) as a tool to deal with portability issues. The
+
+ We use GNU autoconf(1) as a tool to deal with portability issues. The
right way to leverage an OS-specific feature is to modify the autoconf
- specification files (configure.in and aclocal.m4) to set up a new
+ specification files (configure.in and aclocal.m4) to set up a new
feature macro, which you then use to condition your code.
-
+
Documentation Conventions
-
- There are three kinds of documentation associated with this package.
+
+ There are three kinds of documentation associated with this package.
Each has a different preferred format:
* Package-internal files (README, INSTALL, TO-DO etc.)
* Manual pages.
* Everything else (i.e., narrative documentation).
-
+
Our conventions are simple:
1. Maintain package-internal files in plain text. The expected viewer
- for them more(1) or an editor window; there's no point in
+ for them more(1) or an editor window; there's no point in
elaborate mark-up.
- 2. Mark up manual pages in the man macros. These have to be viewable
+ 2. Mark up manual pages in the man macros. These have to be viewable
through traditional man(1) programs.
3. Write everything else in HTML.
-
- When in doubt, HTMLize a master and use lynx(1) to generate plain
+
+ When in doubt, HTMLize a master and use lynx(1) to generate plain
ASCII (as we do for the announcement document).
-
+
The reason for choosing HTML is that it's (a) well-adapted for on-line
browsing through viewers that are everywhere; (b) more easily readable
- as plain text than most other mark-ups, if you don't have a viewer;
- and (c) carries enough information that you can generate a
- nice-looking printed version from it. Also, of course, it make
+ as plain text than most other mark-ups, if you don't have a viewer;
+ and (c) carries enough information that you can generate a
+ nice-looking printed version from it. Also, of course, it make
exporting things like the announcement document to WWW pretty trivial.
-
+
How to Report Bugs
-
- The reporting address for bugs is bug-ncurses@gnu.org. This is a
- majordomo list; to join, write to bug-ncurses-request@gnu.org with a
+
+ The reporting address for bugs is bug-ncurses@gnu.org. This is a
+ majordomo list; to join, write to bug-ncurses-request@gnu.org with a
message containing the line:
subscribe <name>@<host.domain>
- The ncurses code is maintained by a small group of volunteers. While
- we try our best to fix bugs promptly, we simply don't have a lot of
- hours to spend on elementary hand-holding. We rely on intelligent
- cooperation from our users. If you think you have found a bug in
- ncurses, there are some steps you can take before contacting us that
+ The ncurses code is maintained by a small group of volunteers. While
+ we try our best to fix bugs promptly, we simply don't have a lot of
+ hours to spend on elementary hand-holding. We rely on intelligent
+ cooperation from our users. If you think you have found a bug in
+ ncurses, there are some steps you can take before contacting us that
will help get the bug fixed quickly.
-
- In order to use our bug-fixing time efficiently, we put people who
+
+ In order to use our bug-fixing time efficiently, we put people who
show us they've taken these steps at the head of our queue. This means
- that if you don't, you'll probably end up at the tail end and have to
+ that if you don't, you'll probably end up at the tail end and have to
wait a while.
1. Develop a recipe to reproduce the bug.
- Bugs we can reproduce are likely to be fixed very quickly, often
- within days. The most effective single thing you can do to get a
- quick fix is develop a way we can duplicate the bad behavior --
- ideally, by giving us source for a small, portable test program
- that breaks the library. (Even better is a keystroke recipe using
+ Bugs we can reproduce are likely to be fixed very quickly, often
+ within days. The most effective single thing you can do to get a
+ quick fix is develop a way we can duplicate the bad behavior --
+ ideally, by giving us source for a small, portable test program
+ that breaks the library. (Even better is a keystroke recipe using
one of the test programs provided with the distribution.)
2. Try to reproduce the bug on a different terminal type.
- In our experience, most of the behaviors people report as library
+ In our experience, most of the behaviors people report as library
bugs are actually due to subtle problems in terminal descriptions.
This is especially likely to be true if you're using a traditional
- asynchronous terminal or PC-based terminal emulator, rather than
+ asynchronous terminal or PC-based terminal emulator, rather than
xterm or a UNIX console entry.
It's therefore extremely helpful if you can tell us whether or not
- your problem reproduces on other terminal types. Usually you'll
- have both a console type and xterm available; please tell us
+ your problem reproduces on other terminal types. Usually you'll
+ have both a console type and xterm available; please tell us
whether or not your bug reproduces on both.
- If you have xterm available, it is also good to collect xterm
+ If you have xterm available, it is also good to collect xterm
reports for different window sizes. This is especially true if you
- normally use an unusual xterm window size -- a surprising number
+ normally use an unusual xterm window size -- a surprising number
of the bugs we've seen are either triggered or masked by these.
3. Generate and examine a trace file for the broken behavior.
- Recompile your program with the debugging versions of the
- libraries. Insert a trace() call with the argument set to
- TRACE_UPDATE. (See "Writing Programs with NCURSES" for details on
- trace levels.) Reproduce your bug, then look at the trace file to
+ Recompile your program with the debugging versions of the
+ libraries. Insert a trace() call with the argument set to
+ TRACE_UPDATE. (See "Writing Programs with NCURSES" for details on
+ trace levels.) Reproduce your bug, then look at the trace file to
see what the library was actually doing.
- Another frequent cause of apparent bugs is application coding
- errors that cause the wrong things to be put on the virtual
+ Another frequent cause of apparent bugs is application coding
+ errors that cause the wrong things to be put on the virtual
screen. Looking at the virtual-screen dumps in the trace file will
- tell you immediately if this is happening, and save you from the
- possible embarrassment of being told that the bug is in your code
+ tell you immediately if this is happening, and save you from the
+ possible embarrassment of being told that the bug is in your code
and is your problem rather than ours.
- If the virtual-screen dumps look correct but the bug persists,
- it's possible to crank up the trace level to give more and more
- information about the library's update actions and the control
- sequences it issues to perform them. The test directory of the
+ If the virtual-screen dumps look correct but the bug persists,
+ it's possible to crank up the trace level to give more and more
+ information about the library's update actions and the control
+ sequences it issues to perform them. The test directory of the
distribution contains a tool for digesting these logs to make them
less tedious to wade through.
Often you'll find terminfo problems at this stage by noticing that
- the escape sequences put out for various capabilities are wrong.
- If not, you're likely to learn enough to be able to characterize
+ the escape sequences put out for various capabilities are wrong.
+ If not, you're likely to learn enough to be able to characterize
any bug in the screen-update logic quite exactly.
4. Report details and symptoms, not just interpretations.
- If you do the preceding two steps, it is very likely that you'll
+ If you do the preceding two steps, it is very likely that you'll
discover the nature of the problem yourself and be able to send us
- a fix. This will create happy feelings all around and earn you
- good karma for the first time you run into a bug you really can't
+ a fix. This will create happy feelings all around and earn you
+ good karma for the first time you run into a bug you really can't
characterize and fix yourself.
- If you're still stuck, at least you'll know what to tell us.
- Remember, we need details. If you guess about what is safe to
+ If you're still stuck, at least you'll know what to tell us.
+ Remember, we need details. If you guess about what is safe to
leave out, you are too likely to be wrong.
- If your bug produces a bad update, include a trace file. Try to
- make the trace at the least voluminous level that pins down the
- bug. Logs that have been through tracemunch are OK, it doesn't
- throw away any information (actually they're better than
+ If your bug produces a bad update, include a trace file. Try to
+ make the trace at the least voluminous level that pins down the
+ bug. Logs that have been through tracemunch are OK, it doesn't
+ throw away any information (actually they're better than
un-munched ones because they're easier to read).
- If your bug produces a core-dump, please include a symbolic stack
+ If your bug produces a core-dump, please include a symbolic stack
trace generated by gdb(1) or your local equivalent.
Tell us about every terminal on which you've reproduced the bug --
- and every terminal on which you can't. Ideally, sent us terminfo
+ and every terminal on which you can't. Ideally, sent us terminfo
sources for all of these (yours might differ from ours).
- Include your ncurses version and your OS/machine type, of course!
+ Include your ncurses version and your OS/machine type, of course!
You can find your ncurses version in the curses.h file.
-
- If your problem smells like a logic error or in cursor movement or
- scrolling or a bad capability, there are a couple of tiny test frames
- for the library algorithms in the progs directory that may help you
- isolate it. These are not part of the normal build, but do have their
+
+ If your problem smells like a logic error or in cursor movement or
+ scrolling or a bad capability, there are a couple of tiny test frames
+ for the library algorithms in the progs directory that may help you
+ isolate it. These are not part of the normal build, but do have their
own make productions.
-
- The most important of these is mvcur, a test frame for the
- cursor-movement optimization code. With this program, you can see
- directly what control sequences will be emitted for any given cursor
+
+ The most important of these is mvcur, a test frame for the
+ cursor-movement optimization code. With this program, you can see
+ directly what control sequences will be emitted for any given cursor
movement or scroll/insert/delete operations. If you think you've got a
- bad capability identified, you can disable it and test again. The
+ bad capability identified, you can disable it and test again. The
program is command-driven and has on-line help.
-
- If you think the vertical-scroll optimization is broken, or just want
- to understand how it works better, build hashmap and read the header
- comments of hardscroll.c and hashmap.c; then try it out. You can also
+
+ If you think the vertical-scroll optimization is broken, or just want
+ to understand how it works better, build hashmap and read the header
+ comments of hardscroll.c and hashmap.c; then try it out. You can also
test the hardware-scrolling optimization separately with hardscroll.
-
- There's one other interactive tester, tctest, that exercises
- translation between termcap and terminfo formats. If you have a
- serious need to run this, you probably belong on our development team!
-
+
A Tour of the Ncurses Library
-
+
Library Overview
- Most of the library is superstructure -- fairly trivial convenience
- interfaces to a small set of basic functions and data structures used
- to manipulate the virtual screen (in particular, none of this code
- does any I/O except through calls to more fundamental modules
+ Most of the library is superstructure -- fairly trivial convenience
+ interfaces to a small set of basic functions and data structures used
+ to manipulate the virtual screen (in particular, none of this code
+ does any I/O except through calls to more fundamental modules
described below). The files
-
- lib_addch.c lib_bkgd.c lib_box.c lib_chgat.c lib_clear.c
- lib_clearok.c lib_clrbot.c lib_clreol.c lib_colorset.c lib_data.c
- lib_delch.c lib_delwin.c lib_echo.c lib_erase.c lib_gen.c
- lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c lib_insch.c
- lib_insdel.c lib_insstr.c lib_instr.c lib_isendwin.c lib_keyname.c
- lib_leaveok.c lib_move.c lib_mvwin.c lib_overlay.c lib_pad.c
- lib_printw.c lib_redrawln.c lib_scanw.c lib_screen.c lib_scroll.c
- lib_scrollok.c lib_scrreg.c lib_set_term.c lib_slk.c
- lib_slkatr_set.c lib_slkatrof.c lib_slkatron.c lib_slkatrset.c
- lib_slkattr.c lib_slkclear.c lib_slkcolor.c lib_slkinit.c
- lib_slklab.c lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c
+
+ lib_addch.c lib_bkgd.c lib_box.c lib_chgat.c lib_clear.c
+ lib_clearok.c lib_clrbot.c lib_clreol.c lib_colorset.c lib_data.c
+ lib_delch.c lib_delwin.c lib_echo.c lib_erase.c lib_gen.c
+ lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c lib_insch.c
+ lib_insdel.c lib_insstr.c lib_instr.c lib_isendwin.c lib_keyname.c
+ lib_leaveok.c lib_move.c lib_mvwin.c lib_overlay.c lib_pad.c
+ lib_printw.c lib_redrawln.c lib_scanw.c lib_screen.c lib_scroll.c
+ lib_scrollok.c lib_scrreg.c lib_set_term.c lib_slk.c
+ lib_slkatr_set.c lib_slkatrof.c lib_slkatron.c lib_slkatrset.c
+ lib_slkattr.c lib_slkclear.c lib_slkcolor.c lib_slkinit.c
+ lib_slklab.c lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c
lib_unctrl.c lib_vline.c lib_wattroff.c lib_wattron.c lib_window.c
-
- are all in this category. They are very unlikely to need change,
+
+ are all in this category. They are very unlikely to need change,
barring bugs or some fundamental reorganization in the underlying data
structures.
-
+
These files are used only for debugging support:
-
- lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c
+
+ lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c
lib_tracedmp.c lib_tracemse.c trace_buf.c
-
- It is rather unlikely you will ever need to change these, unless you
+
+ It is rather unlikely you will ever need to change these, unless you
want to introduce a new debug trace level for some reasoon.
-
- There is another group of files that do direct I/O via tputs(),
- computations on the terminal capabilities, or queries to the OS
- environment, but nevertheless have only fairly low complexity. These
+
+ There is another group of files that do direct I/O via tputs(),
+ computations on the terminal capabilities, or queries to the OS
+ environment, but nevertheless have only fairly low complexity. These
include:
-
- lib_acs.c lib_beep.c lib_color.c lib_endwin.c lib_initscr.c
- lib_longname.c lib_newterm.c lib_options.c lib_termcap.c lib_ti.c
+
+ lib_acs.c lib_beep.c lib_color.c lib_endwin.c lib_initscr.c
+ lib_longname.c lib_newterm.c lib_options.c lib_termcap.c lib_ti.c
lib_tparm.c lib_tputs.c lib_vidattr.c read_entry.c.
-
+
They are likely to need revision only if ncurses is being ported to an
environment without an underlying terminfo capability representation.
-
- These files have serious hooks into the tty driver and signal
+
+ These files have serious hooks into the tty driver and signal
facilities:
-
+
lib_kernel.c lib_baudrate.c lib_raw.c lib_tstp.c lib_twait.c
-
+
If you run into porting snafus moving the package to another UNIX, the
- problem is likely to be in one of these files. The file lib_print.c
+ problem is likely to be in one of these files. The file lib_print.c
uses sleep(2) and also falls in this category.
-
+
Almost all of the real work is done in the files
-
- hardscroll.c hashmap.c lib_addch.c lib_doupdate.c lib_getch.c
+
+ hardscroll.c hashmap.c lib_addch.c lib_doupdate.c lib_getch.c
lib_mouse.c lib_mvcur.c lib_refresh.c lib_setup.c lib_vidattr.c
-
- Most of the algorithmic complexity in the library lives in these
- files. If there is a real bug in ncurses itself, it's probably here.
+
+ Most of the algorithmic complexity in the library lives in these
+ files. If there is a real bug in ncurses itself, it's probably here.
We'll tour some of these files in detail below (see The Engine Room).
-
- Finally, there is a group of files that is actually most of the
- terminfo compiler. The reason this code lives in the ncurses library
+
+ Finally, there is a group of files that is actually most of the
+ terminfo compiler. The reason this code lives in the ncurses library
is to support fallback to /etc/termcap. These files include
-
- alloc_entry.c captoinfo.c comp_captab.c comp_error.c comp_hash.c
+
+ alloc_entry.c captoinfo.c comp_captab.c comp_error.c comp_hash.c
comp_parse.c comp_scan.c parse_entry.c read_termcap.c write_entry.c
-
+
We'll discuss these in the compiler tour.
-
+
The Engine Room
Keyboard Input
-
- All ncurses input funnels through the function wgetch(), defined in
- lib_getch.c. This function is tricky; it has to poll for keyboard and
- mouse events and do a running match of incoming input against the set
+
+ All ncurses input funnels through the function wgetch(), defined in
+ lib_getch.c. This function is tricky; it has to poll for keyboard and
+ mouse events and do a running match of incoming input against the set
of defined special keys.
-
- The central data structure in this module is a FIFO queue, used to
- match multiple-character input sequences against special-key
+
+ The central data structure in this module is a FIFO queue, used to
+ match multiple-character input sequences against special-key
capabilities; also to implement pushback via ungetch().
-
+
The wgetch() code distinguishes between function key sequences and the
- same sequences typed manually by doing a timed wait after each input
- character that could lead a function key sequence. If the entire
- sequence takes less than 1 second, it is assumed to have been
+ same sequences typed manually by doing a timed wait after each input
+ character that could lead a function key sequence. If the entire
+ sequence takes less than 1 second, it is assumed to have been
generated by a function key press.
-
- Hackers bruised by previous encounters with variant select(2) calls
- may find the code in lib_twait.c interesting. It deals with the
+
+ Hackers bruised by previous encounters with variant select(2) calls
+ may find the code in lib_twait.c interesting. It deals with the
problem that some BSD selects don't return a reliable time-left value.
The function timed_wait() effectively simulates a System V select.
-
+
Mouse Events
-
+
If the mouse interface is active, wgetch() polls for mouse events each
- call, before it goes to the keyboard for input. It is up to
+ call, before it goes to the keyboard for input. It is up to
lib_mouse.c how the polling is accomplished; it may vary for different
devices.
-
- Under xterm, however, mouse event notifications come in via the
- keyboard input stream. They are recognized by having the kmous
- capability as a prefix. This is kind of klugey, but trying to wire in
- recognition of a mouse key prefix without going through the
- function-key machinery would be just too painful, and this turns out
- to imply having the prefix somewhere in the function-key capabilities
+
+ Under xterm, however, mouse event notifications come in via the
+ keyboard input stream. They are recognized by having the kmous
+ capability as a prefix. This is kind of klugey, but trying to wire in
+ recognition of a mouse key prefix without going through the
+ function-key machinery would be just too painful, and this turns out
+ to imply having the prefix somewhere in the function-key capabilities
at terminal-type initialization.
-
- This kluge only works because kmous isn't actually used by any
+
+ This kluge only works because kmous isn't actually used by any
historic terminal type or curses implementation we know of. Best guess
- is it's a relic of some forgotten experiment in-house at Bell Labs
- that didn't leave any traces in the publicly-distributed System V
- terminfo files. If System V or XPG4 ever gets serious about using it
+ is it's a relic of some forgotten experiment in-house at Bell Labs
+ that didn't leave any traces in the publicly-distributed System V
+ terminfo files. If System V or XPG4 ever gets serious about using it
again, this kluge may have to change.
-
+
Here are some more details about mouse event handling:
-
+
The lib_mouse()code is logically split into a lower level that accepts
- event reports in a device-dependent format and an upper level that
+ event reports in a device-dependent format and an upper level that
parses mouse gestures and filters events. The mediating data structure
is a circular queue of event structures.
-
+
Functionally, the lower level's job is to pick up primitive events and
- put them on the circular queue. This can happen in one of two ways:
- either (a) _nc_mouse_event() detects a series of incoming mouse
- reports and queues them, or (b) code in lib_getch.c detects the kmous
- prefix in the keyboard input stream and calls _nc_mouse_inline to
+ put them on the circular queue. This can happen in one of two ways:
+ either (a) _nc_mouse_event() detects a series of incoming mouse
+ reports and queues them, or (b) code in lib_getch.c detects the kmous
+ prefix in the keyboard input stream and calls _nc_mouse_inline to
queue up a series of adjacent mouse reports.
-
+
In either case, _nc_mouse_parse() should be called after the series is
accepted to parse the digested mouse reports (low-level events) into a
gesture (a high-level or composite event).
-
+
Output and Screen Updating
-
+
With the single exception of character echoes during a wgetnstr() call
- (which simulates cooked-mode line editing in an ncurses window), the
+ (which simulates cooked-mode line editing in an ncurses window), the
library normally does all its output at refresh time.
-
- The main job is to go from the current state of the screen (as
- represented in the curscr window structure) to the desired new state
+
+ The main job is to go from the current state of the screen (as
+ represented in the curscr window structure) to the desired new state
(as represented in the newscr window structure), while doing as little
I/O as possible.
-
- The brains of this operation are the modules hashmap.c, hardscroll.c
- and lib_doupdate.c; the latter two use lib_mvcur.c. Essentially, what
+
+ The brains of this operation are the modules hashmap.c, hardscroll.c
+ and lib_doupdate.c; the latter two use lib_mvcur.c. Essentially, what
happens looks like this:
-
- The hashmap.c module tries to detect vertical motion changes between
- the real and virtual screens. This information is represented by the
- oldindex members in the newscr structure. These are modified by
- vertical-motion and clear operations, and both are re-initialized
+
+ The hashmap.c module tries to detect vertical motion changes between
+ the real and virtual screens. This information is represented by the
+ oldindex members in the newscr structure. These are modified by
+ vertical-motion and clear operations, and both are re-initialized
after each update. To this change-journalling information, the hashmap
- code adds deductions made using a modified Heckel algorithm on hash
+ code adds deductions made using a modified Heckel algorithm on hash
values generated from the line contents.
-
- The hardscroll.c module computes an optimum set of scroll, insertion,
- and deletion operations to make the indices match. It calls
+
+ The hardscroll.c module computes an optimum set of scroll, insertion,
+ and deletion operations to make the indices match. It calls
_nc_mvcur_scrolln() in lib_mvcur.c to do those motions.
-
- Then lib_doupdate.c goes to work. Its job is to do line-by-line
- transformations of curscr lines to newscr lines. Its main tool is the
- routine mvcur() in lib_mvcur.c. This routine does cursor-movement
- optimization, attempting to get from given screen location A to given
- location B in the fewest output characters posible.
-
- If you want to work on screen optimizations, you should use the fact
- that (in the trace-enabled version of the library) enabling the
- TRACE_TIMES trace level causes a report to be emitted after each
- screen update giving the elapsed time and a count of characters
- emitted during the update. You can use this to tell when an update
+
+ Then lib_doupdate.c goes to work. Its job is to do line-by-line
+ transformations of curscr lines to newscr lines. Its main tool is the
+ routine mvcur() in lib_mvcur.c. This routine does cursor-movement
+ optimization, attempting to get from given screen location A to given
+ location B in the fewest output characters possible.
+
+ If you want to work on screen optimizations, you should use the fact
+ that (in the trace-enabled version of the library) enabling the
+ TRACE_TIMES trace level causes a report to be emitted after each
+ screen update giving the elapsed time and a count of characters
+ emitted during the update. You can use this to tell when an update
optimization improves efficiency.
-
- In the trace-enabled version of the library, it is also possible to
+
+ In the trace-enabled version of the library, it is also possible to
disable and re-enable various optimizations at runtime by tweaking the
- variable _nc_optimize_enable. See the file include/curses.h.in for
+ variable _nc_optimize_enable. See the file include/curses.h.in for
mask values, near the end.
-
+
The Forms and Menu Libraries
-
- The forms and menu libraries should work reliably in any environment
- you can port ncurses to. The only portability issue anywhere in them
- is what flavor of regular expressions the built-in form field type
+
+ The forms and menu libraries should work reliably in any environment
+ you can port ncurses to. The only portability issue anywhere in them
+ is what flavor of regular expressions the built-in form field type
TYPE_REGEXP will recognize.
-
- The configuration code prefers the POSIX regex facility, modeled on
- System V's, but will settle for BSD regexps if the former isn't
+
+ The configuration code prefers the POSIX regex facility, modeled on
+ System V's, but will settle for BSD regexps if the former isn't
available.
-
- Historical note: the panels code was written primarily to assist in
- porting u386mon 2.0 (comp.sources.misc v14i001-4) to systems lacking
- panels support; u386mon 2.10 and beyond use it. This version has been
+
+ Historical note: the panels code was written primarily to assist in
+ porting u386mon 2.0 (comp.sources.misc v14i001-4) to systems lacking
+ panels support; u386mon 2.10 and beyond use it. This version has been
slightly cleaned up for ncurses.
-
+
A Tour of the Terminfo Compiler
-
+
The ncurses implementation of tic is rather complex internally; it has
- to do a trying combination of missions. This starts with the fact
- that, in addition to its normal duty of compiling terminfo sources
- into loadable terminfo binaries, it has to be able to handle termcap
+ to do a trying combination of missions. This starts with the fact
+ that, in addition to its normal duty of compiling terminfo sources
+ into loadable terminfo binaries, it has to be able to handle termcap
syntax and compile that too into terminfo entries.
-
- The implementation therefore starts with a table-driven, dual-mode
+
+ The implementation therefore starts with a table-driven, dual-mode
lexical analyzer (in comp_scan.c). The lexer chooses its mode (termcap
or terminfo) based on the first `,' or `:' it finds in each entry. The
- lexer does all the work of recognizing capability names and values;
- the grammar above it is trivial, just "parse entries till you run out
+ lexer does all the work of recognizing capability names and values;
+ the grammar above it is trivial, just "parse entries till you run out
of file".
-
+
Translation of Non-use Capabilities
- Translation of most things besides use capabilities is pretty
- straightforward. The lexical analyzer's tokenizer hands each
- capability name to a hash function, which drives a table lookup. The
+ Translation of most things besides use capabilities is pretty
+ straightforward. The lexical analyzer's tokenizer hands each
+ capability name to a hash function, which drives a table lookup. The
table entry yields an index which is used to look up the token type in
another table, and controls interpretation of the value.
-
- One possibly interesting aspect of the implementation is the way the
- compiler tables are initialized. All the tables are generated by
- various awk/sed/sh scripts from a master table include/Caps; these
- scripts actually write C initializers which are linked to the
+
+ One possibly interesting aspect of the implementation is the way the
+ compiler tables are initialized. All the tables are generated by
+ various awk/sed/sh scripts from a master table include/Caps; these
+ scripts actually write C initializers which are linked to the
compiler. Furthermore, the hash table is generated in the same way, so
- it doesn't have to be generated at compiler startup time (another
- benefit of this organization is that the hash table can be in
+ it doesn't have to be generated at compiler startup time (another
+ benefit of this organization is that the hash table can be in
shareable text space).
-
+
Thus, adding a new capability is usually pretty trivial, just a matter
- of adding one line to the include/Caps file. We'll have more to say
+ of adding one line to the include/Caps file. We'll have more to say
about this in the section on Source-Form Translation.
-
+
Use Capability Resolution
- The background problem that makes tic tricky isn't the capability
- translation itself, it's the resolution of use capabilities. Older
+ The background problem that makes tic tricky isn't the capability
+ translation itself, it's the resolution of use capabilities. Older
versions would not handle forward use references for this reason (that
is, a using terminal always had to follow its use target in the source
- file). By doing this, they got away with a simple implementation
- tactic; compile everything as it blows by, then resolve uses from
+ file). By doing this, they got away with a simple implementation
+ tactic; compile everything as it blows by, then resolve uses from
compiled entries.
-
- This won't do for ncurses. The problem is that that the whole
- compilation process has to be embeddable in the ncurses library so
+
+ This won't do for ncurses. The problem is that that the whole
+ compilation process has to be embeddable in the ncurses library so
that it can be called by the startup code to translate termcap entries
- on the fly. The embedded version can't go promiscuously writing
- everything it translates out to disk -- for one thing, it will
+ on the fly. The embedded version can't go promiscuously writing
+ everything it translates out to disk -- for one thing, it will
typically be running with non-root permissions.
-
- So our tic is designed to parse an entire terminfo file into a
- doubly-linked circular list of entry structures in-core, and then do
- use resolution in-memory before writing everything out. This design
+
+ So our tic is designed to parse an entire terminfo file into a
+ doubly-linked circular list of entry structures in-core, and then do
+ use resolution in-memory before writing everything out. This design
has other advantages: it makes forward and back use-references equally
- easy (so we get the latter for free), and it makes checking for name
+ easy (so we get the latter for free), and it makes checking for name
collisions before they're written out easy to do.
-
- And this is exactly how the embedded version works. But the
- stand-alone user-accessible version of tic partly reverts to the
+
+ And this is exactly how the embedded version works. But the
+ stand-alone user-accessible version of tic partly reverts to the
historical strategy; it writes to disk (not keeping in core) any entry
with no use references.
-
- This is strictly a core-economy kluge, implemented because the
- terminfo master file is large enough that some core-poor systems swap
+
+ This is strictly a core-economy kluge, implemented because the
+ terminfo master file is large enough that some core-poor systems swap
like crazy when you compile it all in memory...there have been reports
- of this process taking three hours, rather than the twenty seconds or
+ of this process taking three hours, rather than the twenty seconds or
less typical on the author's development box.
-
+
So. The executable tic passes the entry-parser a hook that immediately
- writes out the referenced entry if it has no use capabilities. The
- compiler main loop refrains from adding the entry to the in-core list
- when this hook fires. If some other entry later needs to reference an
- entry that got written immediately, that's OK; the resolution code
+ writes out the referenced entry if it has no use capabilities. The
+ compiler main loop refrains from adding the entry to the in-core list
+ when this hook fires. If some other entry later needs to reference an
+ entry that got written immediately, that's OK; the resolution code
will fetch it off disk when it can't find it in core.
-
- Name collisions will still be detected, just not as cleanly. The
- write_entry() code complains before overwriting an entry that
- postdates the time of tic's first call to write_entry(), Thus it will
- complain about overwriting entries newly made during the tic run, but
+
+ Name collisions will still be detected, just not as cleanly. The
+ write_entry() code complains before overwriting an entry that
+ postdates the time of tic's first call to write_entry(), Thus it will
+ complain about overwriting entries newly made during the tic run, but
not about overwriting ones that predate it.
-
+
Source-Form Translation
Another use of tic is to do source translation between various termcap
and terminfo formats. There are more variants out there than you might
think; the ones we know about are described in the captoinfo(1) manual
page.
-
- The translation output code (dump_entry() in ncurses/dump_entry.c) is
- shared with the infocmp(1) utility. It takes the same internal
- representation used to generate the binary form and dumps it to
+
+ The translation output code (dump_entry() in ncurses/dump_entry.c) is
+ shared with the infocmp(1) utility. It takes the same internal
+ representation used to generate the binary form and dumps it to
standard output in a specified format.
-
- The include/Caps file has a header comment describing ways you can
- specify source translations for nonstandard capabilities just by
+
+ The include/Caps file has a header comment describing ways you can
+ specify source translations for nonstandard capabilities just by
altering the master table. It's possible to set up capability aliasing
- or tell the compiler to plain ignore a given capability without
+ or tell the compiler to plain ignore a given capability without
writing any C code at all.
-
- For circumstances where you need to do algorithmic translation, there
- are functions in parse_entry.c called after the parse of each entry
+
+ For circumstances where you need to do algorithmic translation, there
+ are functions in parse_entry.c called after the parse of each entry
that are specifically intended to encapsulate such translations. This,
- for example, is where the AIX box1 capability get translated to an
+ for example, is where the AIX box1 capability get translated to an
acsc string.
-
+
Other Utilities
-
- The infocmp utility is just a wrapper around the same entry-dumping
- code used by tic for source translation. Perhaps the one interesting
- aspect of the code is the use of a predicate function passed in to
- dump_entry() to control which capabilities are dumped. This is
+
+ The infocmp utility is just a wrapper around the same entry-dumping
+ code used by tic for source translation. Perhaps the one interesting
+ aspect of the code is the use of a predicate function passed in to
+ dump_entry() to control which capabilities are dumped. This is
necessary in order to handle both the ordinary De-compilation case and
entry difference reporting.
-
- The tput and clear utilities just do an entry load followed by a
+
+ The tput and clear utilities just do an entry load followed by a
tputs() of a selected capability.
-
+
Style Tips for Developers
-
- See the TO-DO file in the top-level directory of the source
+
+ See the TO-DO file in the top-level directory of the source
distribution for additions that would be particularly useful.
-
- The prefix _nc_ should be used on library public functions that are
- not part of the curses API in order to prevent pollution of the
- application namespace. If you have to add to or modify the function
- prototypes in curses.h.in, read ncurses/MKlib_gen.sh first so you can
- avoid breaking XSI conformance. Please join the ncurses mailing list.
- See the INSTALL file in the top level of the distribution for details
+
+ The prefix _nc_ should be used on library public functions that are
+ not part of the curses API in order to prevent pollution of the
+ application namespace. If you have to add to or modify the function
+ prototypes in curses.h.in, read ncurses/MKlib_gen.sh first so you can
+ avoid breaking XSI conformance. Please join the ncurses mailing list.
+ See the INSTALL file in the top level of the distribution for details
on the list.
-
- Look for the string FIXME in source files to tag minor bugs and
+
+ Look for the string FIXME in source files to tag minor bugs and
potential problems that could use fixing.
-
- Don't try to auto-detect OS features in the main body of the C code.
+
+ Don't try to auto-detect OS features in the main body of the C code.
That's the job of the configuration system.
-
+
To hold down complexity, do make your code data-driven. Especially, if
- you can drive logic from a table filtered out of include/Caps, do it.
- If you find you need to augment the data in that file in order to
- generate the proper table, that's still preferable to ad-hoc code --
+ you can drive logic from a table filtered out of include/Caps, do it.
+ If you find you need to augment the data in that file in order to
+ generate the proper table, that's still preferable to ad-hoc code --
that's why the fifth field (flags) is there.
-
+
Have fun!
-
+
Porting Hints
-
- The following notes are intended to be a first step towards DOS and
+
+ The following notes are intended to be a first step towards DOS and
Macintosh ports of the ncurses libraries.
-
- The following library modules are `pure curses'; they operate only on
- the curses internal structures, do all output through other curses
- calls (not including tputs() and putp()) and do not call any other
- UNIX routines such as signal(2) or the stdio library. Thus, they
+
+ The following library modules are `pure curses'; they operate only on
+ the curses internal structures, do all output through other curses
+ calls (not including tputs() and putp()) and do not call any other
+ UNIX routines such as signal(2) or the stdio library. Thus, they
should not need to be modified for single-terminal ports.
-
- lib_addch.c lib_addstr.c lib_bkgd.c lib_box.c lib_clear.c
- lib_clrbot.c lib_clreol.c lib_delch.c lib_delwin.c lib_erase.c
- lib_inchstr.c lib_insch.c lib_insdel.c lib_insstr.c lib_keyname.c
- lib_move.c lib_mvwin.c lib_newwin.c lib_overlay.c lib_pad.c
- lib_printw.c lib_refresh.c lib_scanw.c lib_scroll.c lib_scrreg.c
- lib_set_term.c lib_touch.c lib_tparm.c lib_tputs.c lib_unctrl.c
+
+ lib_addch.c lib_addstr.c lib_bkgd.c lib_box.c lib_clear.c
+ lib_clrbot.c lib_clreol.c lib_delch.c lib_delwin.c lib_erase.c
+ lib_inchstr.c lib_insch.c lib_insdel.c lib_insstr.c lib_keyname.c
+ lib_move.c lib_mvwin.c lib_newwin.c lib_overlay.c lib_pad.c
+ lib_printw.c lib_refresh.c lib_scanw.c lib_scroll.c lib_scrreg.c
+ lib_set_term.c lib_touch.c lib_tparm.c lib_tputs.c lib_unctrl.c
lib_window.c panel.c
-
+
This module is pure curses, but calls outstr():
-
+
lib_getstr.c
-
- These modules are pure curses, except that they use tputs() and
+
+ These modules are pure curses, except that they use tputs() and
putp():
-
- lib_beep.c lib_color.c lib_endwin.c lib_options.c lib_slk.c
+
+ lib_beep.c lib_color.c lib_endwin.c lib_options.c lib_slk.c
lib_vidattr.c
-
+
This modules assist in POSIX emulation on non-POSIX systems:
-
+
sigaction.c
signal calls
-
- The following source files will not be needed for a
+
+ The following source files will not be needed for a
single-terminal-type port.
-
- alloc_entry.c captoinfo.c clear.c comp_captab.c comp_error.c
- comp_hash.c comp_main.c comp_parse.c comp_scan.c dump_entry.c
+
+ alloc_entry.c captoinfo.c clear.c comp_captab.c comp_error.c
+ comp_hash.c comp_main.c comp_parse.c comp_scan.c dump_entry.c
infocmp.c parse_entry.c read_entry.c tput.c write_entry.c
-
- The following modules will use open()/read()/write()/close()/lseek()
+
+ The following modules will use open()/read()/write()/close()/lseek()
on files, but no other OS calls.
-
+
lib_screen.c
used to read/write screen dumps
-
+
lib_trace.c
used to write trace data to the logfile
-
+
Modules that would have to be modified for a port start here:
-
- The following modules are `pure curses' but contain assumptions
+
+ The following modules are `pure curses' but contain assumptions
inappropriate for a memory-mapped port.
-
+
lib_longname.c
assumes there may be multiple terminals
-
+
lib_acs.c
assumes acs_map as a double indirection
-
+
lib_mvcur.c
assumes cursor moves have variable cost
-
+
lib_termcap.c
assumes there may be multiple terminals
-
+
lib_ti.c
assumes there may be multiple terminals
-
+
The following modules use UNIX-specific calls:
-
+
lib_doupdate.c
input checking
-
+
lib_getch.c
read()
-
+
lib_initscr.c
getenv()
-
+
lib_newterm.c
lib_baudrate.c
lib_kernel.c
various tty-manipulation and system calls
-
+
lib_raw.c
various tty-manipulation calls
-
+
lib_setup.c
various tty-manipulation calls
-
+
lib_restart.c
various tty-manipulation calls
-
+
lib_tstp.c
signal-manipulation calls
-
+
lib_twait.c
gettimeofday(), select().
_________________________________________________________________
-
-
+
+
Eric S. Raymond <esr@snark.thyrsus.com>
-
+
(Note: This is not the bug address!)
OpenPOWER on IntegriCloud