home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncurses-1.9.9e-src.tgz / tar.out / fsf / ncurses / misc / hackguide.doc next >
Text File  |  1996-09-28  |  34KB  |  730 lines

  1.  
  2.                           A HACKER'S GUIDE TO NCURSES
  3.                                        
  4.                                    CONTENTS
  5.                                        
  6.      * Abstract
  7.        
  8.      * Objective of the Package
  9.           + Why System V Curses?
  10.           + How to Design Extensions
  11.      * Portability and Configuration
  12.           +
  13.           + If autoconf Fails
  14.      * Documentation Conventions
  15.        
  16.      * How to Report Bugs
  17.        
  18.      * A Tour of the Ncurses Library
  19.           + Library Overview
  20.           + The Engine Room
  21.           + Keyboard Input
  22.           + Mouse Events
  23.           + Output and Screen Updating
  24.      * The Forms and Menu Libraries
  25.        
  26.      * A Tour of the Terminfo Compiler
  27.           + Translation of Non-_use_ Capabilities
  28.           + Use Capability Resolution
  29.           + Source-Form Translation
  30.      * Other Utilities
  31.        
  32.      * Style Tips for Developers
  33.        
  34.      * Porting Hints
  35.        
  36.                                    ABSTRACT
  37.                                        
  38.    This document is a hacker's tour of the _ncurses_ library and
  39.    utilities. It discusses design philosophy, implementation methods, and
  40.    the conventions used for coding and documentation. It is recommended
  41.    reading for anyone who is interested in porting, extending or
  42.    improving the package.
  43.    
  44.                            OBJECTIVE OF THE PACKAGE
  45.                                        
  46.    The objective of the _ncurses_ package is to provide a freeware API
  47.    for character-cell terminals and terminal emulators with the following
  48.    characteristics:
  49.    
  50.      * Source-compatible with historical curses implementations
  51.        (including the original BSD curses and System V curses.
  52.        
  53.      * Conformant with the XSI Curses standard issued as part of XPG4 by
  54.        X/Open.
  55.        
  56.      * High-quality -- stable and reliable code, wide portability, good
  57.        packaging, superior documentation.
  58.        
  59.      * Featureful -- should eliminate as much of the drudgery of C
  60.        interface programming as possible, freeing programmers to think at
  61.        a higher level of design.
  62.        
  63.    These objectives are in priority order. So, for example, source
  64.    compatibility with older version must trump featurefulness -- we
  65.    cannot add features if it means breaking the portion of the API
  66.    corresponding to historical curses versions.
  67.    
  68. Why System V Curses?
  69.  
  70.    We used System V curses as a model, reverse-engineering their API, in
  71.    order to fulfill the first two objectives.
  72.    
  73.    System V curses implementations can support BSD curses programs with
  74.    just a recompilation, so by capturing the System V API we also capture
  75.    BSD's.
  76.    
  77.    More importantly for the future, the XSI Curses standard issued by
  78.    X/Open is explicitly and closely modeled on System V. So conformance
  79.    with System V took us most of the way to base-level XSI conformance.
  80.    
  81. How to Design Extensions
  82.  
  83.    The third objective (standards conformance) requires that it be easy
  84.    to condition source code using _ncurses_ so that the absence of
  85.    nonstandard extensions does not break the code.
  86.    
  87.    Accordingly, we have a policy of associating with each nonstandard
  88.    extension a feature macro, so that ncurses client code can use this
  89.    macro to condition in or out the code that requires the _ncurses_
  90.    extension.
  91.    
  92.    For example, there is a macro NCURSES_MOUSE_VERSION which XSI Curses
  93.    does not define, but which is defined in the _ncurses_ library header.
  94.    You can use this to condition the calls to the mouse API calls.
  95.    
  96.                          PORTABILITY AND CONFIGURATION
  97.                                        
  98.    Code written for _ncurses_ may assume an ANSI-standard C compiler and
  99.    POSIX-compatible OS interface. It may also assume the presence of a
  100.    System-V-compatible _select(2)_ call.
  101.    
  102.    We encourage (but do not require) developers to make the code friendly
  103.    to less-capable UNIX environments wherever possible.
  104.    
  105.    We encourage developers to support OS-specific optimizations and
  106.    methods not available under POSIX/ANSI, provided only that:
  107.    
  108.      * All such code is properly conditioned so the build process does
  109.        not attempt to compile it under a plain ANSI/POSIX environment.
  110.        
  111.      * Adding such implementation methods does not introduce
  112.        incompatibilities in the _ncurses_ API between platforms.
  113.        
  114.    We use GNU autoconf(1) as a tool to deal with portability issues. The
  115.    right way to leverage an OS-specific feature is to modify the autoconf
  116.    specification files (configure.in and aclocal.m4) to set up a new
  117.    feature macro, which you then use to condition your code.
  118.    
  119. If autoconf Fails
  120.  
  121.    The 'configure' script usually gets your system environment right
  122.    automatically. Here are some -D options you might need to compile with
  123.    if it fails:
  124.    
  125.    -DHAVE_UNISTD_H
  126.           if is present
  127.           
  128.    -DHAVE_SIGACTION
  129.           if the sigaction function is present
  130.           
  131.    -DHAVE_USLEEP
  132.           if the usleep function is present
  133.           
  134.    -DSVR4_ACTION
  135.           if (e.g., svr4) you need _POSIX_SOURCE to have sigaction
  136.           
  137.    -DHAVE_TERMIOS_H
  138.           if you have ; otherwise it uses
  139.           
  140.    -DBROKEN_TIOCGETWINSZ
  141.           on SVR4 and HPUX, the get window size ioctl is broken.
  142.           
  143.    -DHAVE_SYS_SELECT_H
  144.           if (e.g., AIX) you have
  145.           
  146.                            DOCUMENTATION CONVENTIONS
  147.                                        
  148.    There are three kinds of documentation associated with this package.
  149.    Each has a different preferred format:
  150.    
  151.      * Package-internal files (README, INSTALL, TO-DO etc.)
  152.      * Manual pages.
  153.      * Everything else (i.e., narrative documentation).
  154.        
  155.    Our conventions are simple:
  156.    
  157.     1. _Maintain package-internal files in plain text._ The expected
  158.        viewer for them _more(1)_ or an editor window; there's no point in
  159.        elaborate mark-up.
  160.        
  161.     2. _Mark up manual pages in the man macros._ These have to be
  162.        viewable through traditional _man(1)_ programs.
  163.        
  164.     3. _Write everything else in HTML._
  165.        
  166.    When in doubt, HTMLize a master and use _lynx(1)_ to generate plain
  167.    ASCII (as we do for the announcement document).
  168.    
  169.    The reason for choosing HTML is that it's (a) well-adapted for on-line
  170.    browsing through viewers that are everywhere; (b) more easily readable
  171.    as plain text than most other mark-ups, if you don't have a viewer;
  172.    and (c) carries enough information that you can generate a
  173.    nice-looking printed version from it. Also, of course, it make
  174.    exporting things like the announcement document to WWW pretty trivial.
  175.    
  176.                               HOW TO REPORT BUGS
  177.                                        
  178.    The ncurses code is maintained by a small group of volunteers. While
  179.    we try our best to fix bugs promptly, we simply don't have a lot of
  180.    hours to spend on elementary hand-holding. We rely on intelligent
  181.    cooperation from our users. If you think you have found a bug in
  182.    ncurses, there are some steps you can take before contacting us that
  183.    will help get the bug fixed quickly.
  184.    
  185.    In order to use our bug-fixing time efficiently, we put people who
  186.    show us they've taken these steps at the head of our queue. This means
  187.    that if you don't, you'll probably end up at the tail end and have to
  188.    wait a while.
  189.    
  190.     1. Develop a recipe to reproduce the bug.
  191.        
  192.        Bugs we can reproduce are likely to be fixed very quickly, often
  193.        within days. The most effective single thing you can do to get a
  194.        quick fix is develop a way we can duplicate the bad behavior --
  195.        ideally, by giving us source for a small, portable test program
  196.        that breaks the library. (Even better is a keystroke recipe using
  197.        one of the test programs provided with the distribution.)
  198.        
  199.     2. Try to reproduce the bug on a different terminal type.
  200.        
  201.        In our experience, most of the behaviors people report as library
  202.        bugs are actually due to subtle problems in terminal descriptions.
  203.        This is especially likely to be true if you're using a traditional
  204.        asynchronous terminal or PC-based terminal emulator, rather than
  205.        xterm or a UNIX console entry.
  206.        
  207.        It's therefore extremely helpful if you can tell us whether or not
  208.        your problem reproduces on other terminal types. Usually you'll
  209.        have both a console type and xterm available; please tell us
  210.        whether or not your bug reproduces on both.
  211.        
  212.        If you have xterm available, it is also good to collect xterm
  213.        reports for different window sizes. This is especially true if you
  214.        normally use an unusual xterm window size -- a surprising number
  215.        of the bugs we've seen are either triggered or masked by these.
  216.        
  217.     3. Generate and examine a trace file for the broken behavior.
  218.        
  219.        Recompile your program with the debugging versions of the
  220.        libraries. Insert a trace() call with the argument set to
  221.        TRACE_UPDATE. (See "Writing Programs with NCURSES" for details on
  222.        trace levels.) Reproduce your bug, then look at the trace file to
  223.        see what the library was actually doing.
  224.        
  225.        Another frequent cause of apparent bugs is application coding
  226.        errors that cause the wrong things to be put on the virtual
  227.        screen. Looking at the virtual-screen dumps in the trace file will
  228.        tell you immediately if this is happening, and save you from the
  229.        possible embarrassment of being told that the bug is in your code
  230.        and is your problem rather than ours.
  231.        
  232.        If the virtual-screen dumps look correct but the bug persists,
  233.        it's possible to crank up the trace level to give more and more
  234.        information about the library's update actions and the control
  235.        sequences it issues to perform them. The test directory of the
  236.        distribution contains a tool for digesting these logs to make them
  237.        less tedious to wade through.
  238.        
  239.        Often you'll find terminfo problems at this stage by noticing that
  240.        the escape sequences put out for various capabilities are wrong.
  241.        If not, you're likely to learn enough to be able to characterize
  242.        any bug in the screen-update logic quite exactly.
  243.        
  244.     4. Report details and symptoms, not just interpretations.
  245.        
  246.        If you do the preceding two steps, it is very likely that you'll
  247.        discover the nature of the problem yourself and be able to send us
  248.        a fix. This will create happy feelings all around and earn you
  249.        good karma for the first time you run into a bug you really can't
  250.        characterize and fix yourself.
  251.        
  252.        If you're still stuck, at least you'll know what to tell us.
  253.        Remember, we need details. If you guess about what is safe to
  254.        leave out, you are too likely to be wrong.
  255.        
  256.        If your bug produces a bad update, include a trace file. Try to
  257.        make the trace at the _least_ voluminous level that pins down the
  258.        bug. Logs that have been through tracemunch are OK, it doesn't
  259.        throw away any information (actually they're better than
  260.        un-munched ones because they're easier to read).
  261.        
  262.        If your bug produces a core-dump, please include a symbolic stack
  263.        trace generated by gdb(1) or your local equivalent.
  264.        
  265.        Tell us about every terminal on which you've reproduced the bug --
  266.        and every terminal on which you can't. Ideally, sent us terminfo
  267.        sources for all of these (yours might differ from ours).
  268.        
  269.        Include your ncurses version and your OS/machine type, of course!
  270.        You can find your ncurses version in the curses.h file.
  271.        
  272.    If your problem smells like a logic error or in cursor movement or
  273.    scrolling or a bad capability, there are a couple of tiny test frames
  274.    for the library algorithms in the progs directory that may help you
  275.    isolate it. These are not part of the normal build, but do have their
  276.    own make productions.
  277.    
  278.    The most important of these is mvcur, a test frame for the
  279.    cursor-movement optimization code. With this program, you can see
  280.    directly what control sequences will be emitted for any given cursor
  281.    movement or scroll/insert/delete operations. If you think you've got a
  282.    bad capability identified, you can disable it and test again. The
  283.    program is command-driven and has on-line help.
  284.    
  285.    If you think the vertical-scroll optimization is broken, or just want
  286.    to understand how it works better, build hardscroll and read the
  287.    header comment of hardscroll.c; then try it out.
  288.    
  289.    There's one other interactive tester, tctest, that exercises
  290.    translation between termcap and terminfo formats. If you have a
  291.    serious need to run this, you probably belong on our development team!
  292.    
  293.    
  294.                          A TOUR OF THE NCURSES LIBRARY
  295.                                        
  296. Library Overview
  297.  
  298.    Most of the library is superstructure -- fairly trivial convenience
  299.    interfaces to a small set of basic functions and data structures used
  300.    to manipulate the virtual screen (in particular, none of this code
  301.    does any I/O except through calls to more fundamental modules
  302.    described below). The files lib_addch.c, lib_bkgnd.c, lib_box.c,
  303.    lib_clear.c, lib_clrbot.c, lib_clreol.c, lib_data.c, lib_delch.c,
  304.    lib_delwin.c, lib_erase.c, lib_getstr.c, lib_inchstr.c, lib_insch.c,
  305.    lib_insdel.c, lib_insstr.c, lib_instr.c, lib_isendwin.c,
  306.    lib_keyname.c, lib_move.c, lib_mvwin.c, lib_overlay.c, lib_pad.c,
  307.    lib_printw.c, lib_scanw.c, lib_screen.c, lib_scroll.c, lib_scrreg.c,
  308.    lib_set_term.c, lib_slk.c, lib_touch.c, lib_unctrl.c, and lib_window.c
  309.    are all in this category. They are very unlikely to need change,
  310.    barring bugs or some fundamental reorganization in the underlying data
  311.    structures.
  312.    
  313.    The lib_trace.c, lib_traceatr.c, and lib_tracechr.c file are used only
  314.    for debugging support. It is rather unlikely you will ever need to
  315.    change these, unless you want to introduce a new debug trace level for
  316.    some reasoon.
  317.    
  318.    There is another group of files that do direct I/O via _tputs()_,
  319.    computations on the terminal capabilities, or queries to the OS
  320.    environment, but nevertheless have only fairly low complexity. These
  321.    include: lib_acs.c, lib_beep.c, lib_color.c, lib_endwin.c,
  322.    lib_initscr.c, lib_longname.c, lib_newterm.c, lib_options.c,
  323.    lib_termcap.c, lib_ti.c, lib_tparm.c, lib_tputs.c, lib_vidattr.c, and
  324.    read_entry.c. These are likely to need revision only if ncurses is
  325.    being ported to an environment without an underlying terminfo
  326.    capability representation.
  327.    
  328.    The files lib_kernel.c, lib_raw.c, lib_tstp.c, and lib_twait.c have
  329.    serious hooks into the tty driver and signal facilities. If you run
  330.    into porting snafus moving the package to another UNIX, the problem is
  331.    likely to be in one of these files.
  332.    
  333.    Almost all of the real work is done in the files hardscroll.c,
  334.    lib_addch.c, lib_doupdate.c, lib_mvcur.c, lib_getch.c, lib_mouse.c,
  335.    lib_refresh.c, and lib_setup.c. Most of the algorithmic complexity in
  336.    the library lives in these files. If there is a real bug in _ncurses_
  337.    itself, it's probably here. We'll tour some of these files in detail
  338.    below (see The Engine Room).
  339.    
  340.    Finally, there is a group of files that is actually most of the
  341.    terminfo compiler. The reason this code lives in the _ncurses_ library
  342.    is to support fallback to /etc/termcap. These files include
  343.    alloc_entry.c, captoinfo.c, comp_captab.c, comp_error.c, comp_hash.c,
  344.    comp_parse.c, comp_scan.c, and parse_entry.c, read_termcap.c, and
  345.    write_entry.c. We'll discuss these in the compiler tour.
  346.    
  347. The Engine Room
  348.  
  349.   KEYBOARD INPUT
  350.   
  351.    All ncurses input funnels through the function wgetch(), defined in
  352.    lib_getch.c. This function is tricky; it has to poll for keyboard and
  353.    mouse events and do a running match of incoming input against the set
  354.    of defined special keys.
  355.    
  356.    The central data structure in this module is a FIFO queue, used to
  357.    match multiple-character input sequences against special-key
  358.    capabilities; also to implement pushback via ungetch().
  359.    
  360.    The wgetch() code distinguishes between function key sequences and the
  361.    same sequences typed manually by doing a timed wait after each input
  362.    character that could lead a function key sequence. If the entire
  363.    sequence takes less than 1 second, it is assumed to have been
  364.    generated by a function key press.
  365.    
  366.    Hackers bruised by previous encounters with variant select(2) calls
  367.    may find the code in lib_twait.c interesting. It deals with the
  368.    problem that some BSD selects don't return a reliable time-left value.
  369.    The function timed_wait() effectively simulates a System V select.
  370.    
  371.   MOUSE EVENTS
  372.   
  373.    If the mouse interface is active, wgetch() polls for mouse events each
  374.    call, before it goes to the keyboard for input. It is up to
  375.    lib_mouse.c how the polling is accomplished; it may vary for different
  376.    devices.
  377.    
  378.    Under xterm, however, mouse event notifications come in via the
  379.    keyboard input stream. They are recognized by having the _kmous_
  380.    capability as a prefix. This is kind of klugey, but trying to wire in
  381.    recognition of a mouse key prefix without going through the
  382.    function-key machinery would be just too painful, and this turns out
  383.    to imply having the prefix somewhere in the function-key capabilities
  384.    at terminal-type initialization.
  385.    
  386.    This kluge only works because _kmous_ isn't actually used by any
  387.    historic terminal type or curses implementation we know of. Best guess
  388.    is it's a relic of some forgotten experiment in-house at Bell Labs
  389.    that didn't leave any traces in the publicly-distributed System V
  390.    terminfo files. If System V or XPG4 ever gets serious about using it
  391.    again, this kluge may have to change.
  392.    
  393.    Here are some more details about mouse event handling:
  394.    
  395.    The lib_mouse()code is logically split into a lower level that accepts
  396.    event reports in a device-dependent format and an upper level that
  397.    parses mouse gestures and filters events. The mediating data structure
  398.    is a circular queue of event structures.
  399.    
  400.    Functionally, the lower level's job is to pick up primitive events and
  401.    put them on the circular queue. This can happen in one of two ways:
  402.    either (a) _nc_mouse_event() detects a series of incoming mouse
  403.    reports and queues them, or (b) code in lib_getch.c detects the
  404.    _kmous_ prefix in the keyboard input stream and calls _nc_mouse_inline
  405.    to queue up a series of adjacent mouse reports.
  406.    
  407.    In either case, _nc_mouse_parse() should be called after the series is
  408.    accepted to parse the digested mouse reports (low-level events) into a
  409.    gesture (a high-level or composite event).
  410.    
  411.   OUTPUT AND SCREEN UPDATING
  412.   
  413.    With the single exception of character echoes during a wgetnstr() call
  414.    (which simulates cooked-mode line editing in an ncurses window), the
  415.    library normally does all its output at refresh time.
  416.    
  417.    The main job is to go from the current state of the screen (as
  418.    represented in the curscr window structure) to the desired new state
  419.    (as represented in the newscr window structure), while doing as little
  420.    I/O as possible.
  421.    
  422.    The brains of this operation are the modules hardscroll.c and
  423.    lib_doupdate.c; both use lib_mvcur.c. Essentially, what happens looks
  424.    like this:
  425.    
  426.    The hardscroll.c module tries to detect vertical motion changes
  427.    between the real and virtual screens. It does so by comparing line
  428.    number vectors between curscr and newscr; both are modified by
  429.    vertical-motion and clear operations, and both are re-initialized
  430.    after each update.
  431.    
  432.    The hardscroll.c module computes an optimum set of scroll, insertion,
  433.    and deletion operations to make the vectors match. It calls
  434.    _nc_mvcur_scrolln() in lib_mvcur.c to do those motions.
  435.    
  436.    Then lib_doupdate.c goes to work. Its job is to do line-by-line
  437.    transformations of curscr lines to newscr lines. Its main tool is the
  438.    routine mvcur() in lib_mvcur.c. This routine does cursor-movement
  439.    optimization, attempting to get from given screen location A to given
  440.    location B in the fewest output characters posible.
  441.    
  442.                          THE FORMS AND MENU LIBRARIES
  443.                                        
  444.    The forms and menu libraries should work reliably in any environment
  445.    you can port ncurses to. The only portability issue anywhere in them
  446.    is what flavor of regular expressions the built-in form field type
  447.    TYPE_REGEXP will recognize.
  448.    
  449.    The configuration code prefers the POSIX regex facility, modeled on
  450.    System V's, but will settle for BSD regexps if the former isn't
  451.    available.
  452.    
  453.    Historical note: the panels code was written primarily to assist in
  454.    porting u386mon 2.0 (comp.sources.misc v14i001-4) to systems lacking
  455.    panels support; u386mon 2.10 and beyond use it. This version has been
  456.    slightly cleaned up for ncurses.
  457.    
  458.                         A TOUR OF THE TERMINFO COMPILER
  459.                                        
  460.    The _ncurses_ implementation of _tic_ is rather complex internally; it
  461.    has to do a trying combination of missions. This starts with the fact
  462.    that, in addition to its normal duty of compiling terminfo sources
  463.    into loadable terminfo binaries, it has to be able to handle termcap
  464.    syntax and compile that too into terminfo entries.
  465.    
  466.    The implementation therefore starts with a table-driven, dual-mode
  467.    lexical analyzer (in comp_scan.c). The lexer chooses its mode (termcap
  468.    or terminfo) based on the first `,' or `:' it finds in each entry. The
  469.    lexer does all the work of recognizing capability names and values;
  470.    the grammar above it is trivial, just "parse entries till you run out
  471.    of file".
  472.    
  473. Translation of Non-_use_ Capabilities
  474.  
  475.    Translation of most things besides _use_ capabilities is pretty
  476.    straightforward. The lexical analyzer's tokenizer hands each
  477.    capability name to a hash function, which drives a table lookup. The
  478.    table entry yields an index which is used to look up the token type in
  479.    another table, and controls interpretation of the value.
  480.    
  481.    One possibly interesting aspect of the implementation is the way the
  482.    compiler tables are initialized. All the tables are generated by
  483.    various awk/sed/sh scripts from a master table include/Caps; these
  484.    scripts actually write C initializers which are linked to the
  485.    compiler. Furthermore, the hash table is generated in the same way, so
  486.    it doesn't have to be generated at compiler startup time (another
  487.    benefit of this organization is that the hash table can be in
  488.    shareable text space).
  489.    
  490.    Thus, adding a new capability is usually pretty trivial, just a matter
  491.    of adding one line to the include/Caps file. We'll have more to say
  492.    about this in the section on Source-Form Translation.
  493.    
  494. Use Capability Resolution
  495.  
  496.    The background problem that makes _tic_ tricky isn't the capability
  497.    translation itself, it's the resolution of _use_ capabilities. Older
  498.    versions would not handle forward _use_ references for this reason
  499.    (that is, a using terminal always had to follow its use target in the
  500.    source file). By doing this, they got away with a simple
  501.    implementation tactic; compile everything as it blows by, then resolve
  502.    uses from compiled entries.
  503.    
  504.    This won't do for _ncurses_. The problem is that that the whole
  505.    compilation process has to be embeddable in the _ncurses_ library so
  506.    that it can be called by the startup code to translate termcap entries
  507.    on the fly. The embedded version can't go promiscuously writing
  508.    everything it translates out to disk -- for one thing, it will
  509.    typically be running with non-root permissions.
  510.    
  511.    So our _tic_ is designed to parse an entire terminfo file into a
  512.    doubly-linked circular list of entry structures in-core, and then do
  513.    _use_ resolution in-memory before writing everything out. This design
  514.    has other advantages: it makes forward and back use-references equally
  515.    easy (so we get the latter for free), and it makes checking for name
  516.    collisions before they're written out easy to do.
  517.    
  518.    And this is exactly how the embedded version works. But the
  519.    stand-alone user-accessible version of _tic_ partly reverts to the
  520.    historical strategy; it writes to disk (not keeping in core) any entry
  521.    with no _use_ references.
  522.    
  523.    This is strictly a core-economy kluge, implemented because the
  524.    terminfo master file is large enough that some core-poor systems swap
  525.    like crazy when you compile it all in memory...there have been reports
  526.    of this process taking _three hours_, rather than the twenty seconds
  527.    or less typical on the author's development box.
  528.    
  529.    So. The executable _tic_ passes the entry-parser a hook that
  530.    _immediately_ writes out the referenced entry if it has no use
  531.    capabilities. The compiler main loop refrains from adding the entry to
  532.    the in-core list when this hook fires. If some other entry later needs
  533.    to reference an entry that got written immediately, that's OK; the
  534.    resolution code will fetch it off disk when it can't find it in core.
  535.    
  536.    Name collisions will still be detected, just not as cleanly. The
  537.    write_entry() code complains before overwriting an entry that
  538.    postdates the time of _tic_'s first call to write_entry(), Thus it
  539.    will complain about overwriting entries newly made during the _tic_
  540.    run, but not about overwriting ones that predate it.
  541.    
  542. Source-Form Translation
  543.  
  544.    Another use of _tic_ is to do source translation between various
  545.    termcap and terminfo formats. There are more variants out there than
  546.    you might think; the ones we know about are described in the
  547.    _captoinfo(1)_ manual page.
  548.    
  549.    The translation output code (dump_entry() in ncurses/dump_entry.c) is
  550.    shared with the _infocmp(1)_ utility. It takes the same internal
  551.    representation used to generate the binary form and dumps it to
  552.    standard output in a specified format.
  553.    
  554.    The include/Caps file has a header comment describing ways you can
  555.    specify source translations for nonstandard capabilities just by
  556.    altering the master table. It's possible to set up capability aliasing
  557.    or tell the compiler to plain ignore a given capability without
  558.    writing any C code at all.
  559.    
  560.    For circumstances where you need to do algorithmic translation, there
  561.    are functions in parse_entry.c called after the parse of each entry
  562.    that are specifically intended to encapsulate such translations. This,
  563.    for example, is where the AIX _box1_ capability get translated to an
  564.    _acsc_ string.
  565.    
  566.                                 OTHER UTILITIES
  567.                                        
  568.    The _infocmp_ utility is just a wrapper around the same entry-dumping
  569.    code used by _tic_ for source translation. Perhaps the one interesting
  570.    aspect of the code is the use of a predicate function passed in to
  571.    dump_entry() to control which capabilities are dumped. This is
  572.    necessary in order to handle both the ordinary De-compilation case and
  573.    entry difference reporting.
  574.    
  575.    The _tput_ and _clear_ utilities just do an entry load followed by a
  576.    tputs() of a selected capability.
  577.    
  578.                            STYLE TIPS FOR DEVELOPERS
  579.                                        
  580.    See the TO-DO file in the top-level directory of the source
  581.    distribution for additions that would be particularly useful.
  582.    
  583.    The prefix _nc_ should be used on library public functions that are
  584.    not part of the curses API in order to prevent pollution of the
  585.    application namespace. If you have to add to or modify the function
  586.    prototypes in curses.h.in, read ncurses/MKlib_gen.sh first so you can
  587.    avoid breaking XSI conformance. Please join the ncurses mailing list.
  588.    See the INSTALL file in the top level of the distribution for details
  589.    on the list.
  590.    
  591.    Look for the string FIXME in source files to tag minor bugs and
  592.    potential problems that could use fixing.
  593.    
  594.    Don't try to auto-detect OS features in the main body of the C code.
  595.    That's the job of the configuration system.
  596.    
  597.    To hold down complexity, do make your code data-driven. Especially, if
  598.    you can drive logic from a table filtered out of include/Caps, do it.
  599.    If you find you need to augment the data in that file in order to
  600.    generate the proper table, that's still preferable to ad-hoc code --
  601.    that's why the fifth field (flags) is there.
  602.    
  603.    Have fun!
  604.    
  605.                                  PORTING HINTS
  606.                                        
  607.    The following notes are intended to be a first step towards DOS and
  608.    Macintosh ports of the ncurses libraries.
  609.    
  610.    The following library modules are `pure curses'; they operate only on
  611.    the curses internal structures, do all output through other curses
  612.    calls (not including tputs() and putp()) and do not call any other
  613.    UNIX routines such as signal(2) or the stdio library. Thus, they
  614.    should not need to be modified for single-terminal ports.
  615.    
  616.    lib_addch.c lib_addstr.c lib_bkgd.c lib_box.c lib_clear.c lib_clrbot.c
  617.    lib_clreol.c lib_delch.c lib_delwin.c lib_erase.c lib_inchstr.c
  618.    lib_insch.c lib_insdel.c lib_insstr.c lib_keyname.c lib_move.c
  619.    lib_mvwin.c lib_newwin.c lib_overlay.c lib_pad.c lib_printw.c
  620.    lib_refresh.c lib_scanw.c lib_scroll.c lib_scrreg.c lib_set_term.c
  621.    lib_touch.c lib_tparm.c lib_tputs.c lib_unctrl.c lib_window.c panel.c
  622.    
  623.    This module is pure curses, but calls outstr():
  624.    
  625.    lib_getstr.c
  626.    
  627.    These modules are pure curses, except that they use tputs() and
  628.    putp():
  629.    
  630.    lib_beep.c lib_endwin.c lib_color.c lib_options.c lib_slk.c
  631.    lib_vidattr.c
  632.    
  633.    This modules assist in POSIX emulation on non-POSIX systems:
  634.    
  635.    sigaction.c
  636.           signal calls
  637.           
  638.    The following source files will not be needed for a
  639.    single-terminal-type port.
  640.    
  641.    captoinfo.c clear.c comp_captab.c comp_error.c comp_hash.c comp_main.c
  642.    comp_parse.c comp_scan.c alloc_entry.c dump_entry.c parse_entry.c
  643.    read_entry.c write_entry.c infocmp.c tput.c
  644.    
  645.    The following modules will use open()/read()/write()/close()/lseek()
  646.    on files, but no other OS calls.
  647.    
  648.    lib_screen.c
  649.           used to read/write screen dumps
  650.           
  651.    lib_trace.c
  652.           used to write trace data to the logfile
  653.           
  654.    Modules that would have to be modified for a port start here:
  655.    
  656.    The following modules are `pure curses' but contain assumptions
  657.    inappropriate for a memory-mapped port.
  658.    
  659.  
  660. lib_longname.c  -- assumes there may be multiple terminals
  661.         longname()              -- return long name of terminal
  662. lib_acs.c       -- assumes acs_map as a double indirection
  663.         init_acs()              -- initialize acs map
  664. lib_mvcur.c     -- assumes cursor moves have variable cost
  665.         mvcur_init()            -- initialize
  666.         mvcur()                 -- do physical cursor move
  667.         mvcur_wrap()            -- wrap
  668.         scrolln()               -- do physical scrolling
  669. lib_termcap.c   -- assumes there may be multiple terminals
  670.         tgetent()               -- load entry
  671.         tgetflag()              -- get boolean capability
  672.         tgetnum()               -- get numeric capability
  673.         tgetstr()               -- get string capability
  674. lib_ti.c        -- assumes there may be multiple terminals
  675.         tigetent()              -- load entry
  676.         tigetflag()             -- get boolean capability
  677.         tigetnum()              -- get numeric capability
  678.         tigetstr()              -- get string capability
  679.  
  680. The following modules use UNIX-specific calls:
  681.  
  682. lib_doupdate.c  -- input checking
  683.         doupdate()              -- repaint real screen to match virtual
  684.         _nc_outch()             -- put out a single character
  685. lib_getch.c     -- read()
  686.         wgetch()                -- get single character
  687.         wungetch()              -- push back single character
  688. lib_initscr.c   -- getenv()
  689.         initscr()               -- initialize curses functions
  690. lib_newterm.c
  691.         newterm()               -- set up new terminal screen
  692. lib_kernel.c    -- various tty-manipulation and system calls
  693.         reset_prog_mode()       -- reset ccurses-raw mode
  694.         reset_shell_mode()      -- reset cooked mode
  695.         baudrate()              -- return the baudrate
  696.         erasechar()             -- return the erase char
  697.         killchar()              -- return the kill character
  698.         flushinp()              -- flush pending input
  699.         savetty()               -- save tty state
  700.         resetty()               -- reset tty to state at last savetty()
  701. lib_raw.c       -- various tty-manipulation calls
  702.         raw()
  703.         echo()
  704.         nl()
  705.         qiflush()
  706.         cbreak()
  707.         noraw()
  708.         noecho()
  709.         nonl()
  710.         noqiflush()
  711.         nocbreak()
  712. lib_setup.c     -- various tty-manipulation calls
  713.         use_env()
  714.         def_shell_mode()
  715.         def_prog_mode()
  716.         set_curterm()
  717.         del_curterm()
  718. lib_tstp.c      -- signal-manipulation calls
  719.         _nc_signal_handler()    -- enable/disable window-mode signal catching
  720. lib_twait.c     -- gettimeofday(), select().
  721.         usleep()                -- microsecond sleep
  722.         _nc_timed_wait()        -- timed wait for input
  723.  
  724.    The package kernel could be made smaller.
  725.    
  726.    
  727.      _________________________________________________________________
  728.    
  729.     Eric S. Raymond <esr@snark.thyrsus.com>
  730.