115589c42SPeter Wemm<!--
215589c42SPeter Wemm  $Id: hackguide.html,v 1.33 2020/02/02 23:34:34 tom Exp $
3*4a1a9510SRong-En Fan  ****************************************************************************
4*4a1a9510SRong-En Fan  * Copyright 2019,2020 Thomas E. Dickey                                     *
5*4a1a9510SRong-En Fan  * Copyright 2000-2013,2017 Free Software Foundation, Inc.                  *
6*4a1a9510SRong-En Fan  *                                                                          *
7*4a1a9510SRong-En Fan  * Permission is hereby granted, free of charge, to any person obtaining a  *
8*4a1a9510SRong-En Fan  * copy of this software and associated documentation files (the            *
9*4a1a9510SRong-En Fan  * "Software"), to deal in the Software without restriction, including      *
10*4a1a9510SRong-En Fan  * without limitation the rights to use, copy, modify, merge, publish,      *
11*4a1a9510SRong-En Fan  * distribute, distribute with modifications, sublicense, and/or sell       *
12*4a1a9510SRong-En Fan  * copies of the Software, and to permit persons to whom the Software is    *
13*4a1a9510SRong-En Fan  * furnished to do so, subject to the following conditions:                 *
14*4a1a9510SRong-En Fan  *                                                                          *
15*4a1a9510SRong-En Fan  * The above copyright notice and this permission notice shall be included  *
16*4a1a9510SRong-En Fan  * in all copies or substantial portions of the Software.                   *
17*4a1a9510SRong-En Fan  *                                                                          *
18*4a1a9510SRong-En Fan  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
19*4a1a9510SRong-En Fan  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
20*4a1a9510SRong-En Fan  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
21*4a1a9510SRong-En Fan  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
22*4a1a9510SRong-En Fan  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
23*4a1a9510SRong-En Fan  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
24*4a1a9510SRong-En Fan  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
25*4a1a9510SRong-En Fan  *                                                                          *
26*4a1a9510SRong-En Fan  * Except as contained in this notice, the name(s) of the above copyright   *
27*4a1a9510SRong-En Fan  * holders shall not be used in advertising or otherwise to promote the     *
28*4a1a9510SRong-En Fan  * sale, use or other dealings in this Software without prior written       *
29*4a1a9510SRong-En Fan  * authorization.                                                           *
30*4a1a9510SRong-En Fan  ****************************************************************************
3115589c42SPeter Wemm-->
3215589c42SPeter Wemm<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
3315589c42SPeter Wemm
3415589c42SPeter Wemm<html>
3515589c42SPeter Wemm<head>
36*4a1a9510SRong-En Fan  <meta name="generator" content=
3715589c42SPeter Wemm  "HTML Tidy for HTML5 for Linux version 5.2.0">
3815589c42SPeter Wemm
3915589c42SPeter Wemm  <title>A Hacker's Guide to Ncurses Internals</title>
4015589c42SPeter Wemm  <link rel="author" href="mailto:[email protected]">
4115589c42SPeter Wemm  <meta http-equiv="Content-Type" content=
4215589c42SPeter Wemm  "text/html; charset=us-ascii"><!--
4315589c42SPeter WemmThis document is self-contained, *except* that there is one relative link to
4415589c42SPeter Wemmthe ncurses-intro.html document, expected to be in the same directory with
4515589c42SPeter Wemmthis one.
4615589c42SPeter Wemm-->
4715589c42SPeter Wemm</head>
4815589c42SPeter Wemm
4915589c42SPeter Wemm<body>
5015589c42SPeter Wemm  <h1>A Hacker's Guide to NCURSES</h1>
5115589c42SPeter Wemm
5215589c42SPeter Wemm  <h1>Contents</h1>
5315589c42SPeter Wemm
5415589c42SPeter Wemm  <ul>
5515589c42SPeter Wemm    <li><a href="#abstract">Abstract</a></li>
5615589c42SPeter Wemm
5715589c42SPeter Wemm    <li>
5815589c42SPeter Wemm      <a href="#objective">Objective of the Package</a>
5915589c42SPeter Wemm
6015589c42SPeter Wemm      <ul>
6115589c42SPeter Wemm        <li><a href="#whysvr4">Why System V Curses?</a></li>
6215589c42SPeter Wemm
6315589c42SPeter Wemm        <li><a href="#extensions">How to Design Extensions</a></li>
6415589c42SPeter Wemm      </ul>
6515589c42SPeter Wemm    </li>
6615589c42SPeter Wemm
6715589c42SPeter Wemm    <li><a href="#portability">Portability and Configuration</a></li>
6815589c42SPeter Wemm
6915589c42SPeter Wemm    <li><a href="#documentation">Documentation Conventions</a></li>
7015589c42SPeter Wemm
7115589c42SPeter Wemm    <li><a href="#bugtrack">How to Report Bugs</a></li>
7215589c42SPeter Wemm
7315589c42SPeter Wemm    <li>
7415589c42SPeter Wemm      <a href="#ncurslib">A Tour of the Ncurses Library</a>
7515589c42SPeter Wemm
7615589c42SPeter Wemm      <ul>
7715589c42SPeter Wemm        <li><a href="#loverview">Library Overview</a></li>
7815589c42SPeter Wemm
7915589c42SPeter Wemm        <li><a href="#engine">The Engine Room</a></li>
8015589c42SPeter Wemm
8115589c42SPeter Wemm        <li><a href="#input">Keyboard Input</a></li>
8215589c42SPeter Wemm
8315589c42SPeter Wemm        <li><a href="#mouse">Mouse Events</a></li>
8415589c42SPeter Wemm
8515589c42SPeter Wemm        <li><a href="#output">Output and Screen Updating</a></li>
8615589c42SPeter Wemm      </ul>
8715589c42SPeter Wemm    </li>
8815589c42SPeter Wemm
8915589c42SPeter Wemm    <li><a href="#fmnote">The Forms and Menu Libraries</a></li>
9015589c42SPeter Wemm
9115589c42SPeter Wemm    <li>
9215589c42SPeter Wemm      <a href="#tic">A Tour of the Terminfo Compiler</a>
9315589c42SPeter Wemm
9415589c42SPeter Wemm      <ul>
9515589c42SPeter Wemm        <li><a href="#nonuse">Translation of
9615589c42SPeter Wemm        Non-<strong>use</strong> Capabilities</a></li>
9715589c42SPeter Wemm
9815589c42SPeter Wemm        <li><a href="#uses">Use Capability Resolution</a></li>
9915589c42SPeter Wemm
10015589c42SPeter Wemm        <li><a href="#translation">Source-Form Translation</a></li>
10115589c42SPeter Wemm      </ul>
10215589c42SPeter Wemm    </li>
10315589c42SPeter Wemm
10415589c42SPeter Wemm    <li><a href="#utils">Other Utilities</a></li>
10515589c42SPeter Wemm
10615589c42SPeter Wemm    <li><a href="#style">Style Tips for Developers</a></li>
10715589c42SPeter Wemm
10815589c42SPeter Wemm    <li><a href="#port">Porting Hints</a></li>
10915589c42SPeter Wemm  </ul>
11015589c42SPeter Wemm
11115589c42SPeter Wemm  <h1><a name="abstract" id="abstract">Abstract</a></h1>
11215589c42SPeter Wemm
11315589c42SPeter Wemm  <p>This document is a hacker's tour of the
11415589c42SPeter Wemm  <strong>ncurses</strong> library and utilities. It discusses
11515589c42SPeter Wemm  design philosophy, implementation methods, and the conventions
11615589c42SPeter Wemm  used for coding and documentation. It is recommended reading for
11715589c42SPeter Wemm  anyone who is interested in porting, extending or improving the
11815589c42SPeter Wemm  package.</p>
11915589c42SPeter Wemm
12015589c42SPeter Wemm  <h1><a name="objective" id="objective">Objective of the
12115589c42SPeter Wemm  Package</a></h1>
12215589c42SPeter Wemm
12315589c42SPeter Wemm  <p>The objective of the <strong>ncurses</strong> package is to
12415589c42SPeter Wemm  provide a free software API for character-cell terminals and
12515589c42SPeter Wemm  terminal emulators with the following characteristics:</p>
12615589c42SPeter Wemm
12715589c42SPeter Wemm  <ul>
12815589c42SPeter Wemm    <li>Source-compatible with historical curses implementations
12915589c42SPeter Wemm    (including the original BSD curses and System V curses.</li>
13015589c42SPeter Wemm
13115589c42SPeter Wemm    <li>Conformant with the XSI Curses standard issued as part of
13215589c42SPeter Wemm    XPG4 by X/Open.</li>
13315589c42SPeter Wemm
13415589c42SPeter Wemm    <li>High-quality &mdash; stable and reliable code, wide
13515589c42SPeter Wemm    portability, good packaging, superior documentation.</li>
13615589c42SPeter Wemm
13715589c42SPeter Wemm    <li>Featureful &mdash; should eliminate as much of the drudgery
13815589c42SPeter Wemm    of C interface programming as possible, freeing programmers to
13915589c42SPeter Wemm    think at a higher level of design.</li>
14015589c42SPeter Wemm  </ul>
14115589c42SPeter Wemm
14215589c42SPeter Wemm  <p>These objectives are in priority order. So, for example,
14315589c42SPeter Wemm  source compatibility with older version must trump featurefulness
14415589c42SPeter Wemm  &mdash; we cannot add features if it means breaking the portion
14515589c42SPeter Wemm  of the API corresponding to historical curses versions.</p>
14615589c42SPeter Wemm
14715589c42SPeter Wemm  <h2><a name="whysvr4" id="whysvr4">Why System V Curses?</a></h2>
14815589c42SPeter Wemm
14915589c42SPeter Wemm  <p>We used System V curses as a model, reverse-engineering their
15015589c42SPeter Wemm  API, in order to fulfill the first two objectives.</p>
15115589c42SPeter Wemm
15215589c42SPeter Wemm  <p>System V curses implementations can support BSD curses
15315589c42SPeter Wemm  programs with just a recompilation, so by capturing the System V
15415589c42SPeter Wemm  API we also capture BSD's.</p>
15515589c42SPeter Wemm
15615589c42SPeter Wemm  <p>More importantly for the future, the XSI Curses standard
15715589c42SPeter Wemm  issued by X/Open is explicitly and closely modeled on System V.
15815589c42SPeter Wemm  So conformance with System V took us most of the way to
15915589c42SPeter Wemm  base-level XSI conformance.</p>
16015589c42SPeter Wemm
16115589c42SPeter Wemm  <h2><a name="extensions" id="extensions">How to Design
16215589c42SPeter Wemm  Extensions</a></h2>
16315589c42SPeter Wemm
16415589c42SPeter Wemm  <p>The third objective (standards conformance) requires that it
16515589c42SPeter Wemm  be easy to condition source code using <strong>ncurses</strong>
16615589c42SPeter Wemm  so that the absence of nonstandard extensions does not break the
16715589c42SPeter Wemm  code.</p>
16815589c42SPeter Wemm
16915589c42SPeter Wemm  <p>Accordingly, we have a policy of associating with each
17015589c42SPeter Wemm  nonstandard extension a feature macro, so that ncurses client
17115589c42SPeter Wemm  code can use this macro to condition in or out the code that
17215589c42SPeter Wemm  requires the <strong>ncurses</strong> extension.</p>
17315589c42SPeter Wemm
17415589c42SPeter Wemm  <p>For example, there is a macro
17515589c42SPeter Wemm  <code>NCURSES_MOUSE_VERSION</code> which XSI Curses does not
17615589c42SPeter Wemm  define, but which is defined in the <strong>ncurses</strong>
17715589c42SPeter Wemm  library header. You can use this to condition the calls to the
17815589c42SPeter Wemm  mouse API calls.</p>
17915589c42SPeter Wemm
18015589c42SPeter Wemm  <h1><a name="portability" id="portability">Portability and
18115589c42SPeter Wemm  Configuration</a></h1>
18215589c42SPeter Wemm
18315589c42SPeter Wemm  <p>Code written for <strong>ncurses</strong> may assume an
18415589c42SPeter Wemm  ANSI-standard C compiler and POSIX-compatible OS interface. It
18515589c42SPeter Wemm  may also assume the presence of a System-V-compatible
18615589c42SPeter Wemm  <em>select(2)</em> call.</p>
18715589c42SPeter Wemm
18815589c42SPeter Wemm  <p>We encourage (but do not require) developers to make the code
18915589c42SPeter Wemm  friendly to less-capable UNIX environments wherever possible.</p>
19015589c42SPeter Wemm
19115589c42SPeter Wemm  <p>We encourage developers to support OS-specific optimizations
19215589c42SPeter Wemm  and methods not available under POSIX/ANSI, provided only
19315589c42SPeter Wemm  that:</p>
19415589c42SPeter Wemm
19515589c42SPeter Wemm  <ul>
19615589c42SPeter Wemm    <li>All such code is properly conditioned so the build process
19715589c42SPeter Wemm    does not attempt to compile it under a plain ANSI/POSIX
19815589c42SPeter Wemm    environment.</li>
19915589c42SPeter Wemm
20015589c42SPeter Wemm    <li>Adding such implementation methods does not introduce
20115589c42SPeter Wemm    incompatibilities in the <strong>ncurses</strong> API between
20215589c42SPeter Wemm    platforms.</li>
20315589c42SPeter Wemm  </ul>
20415589c42SPeter Wemm
20515589c42SPeter Wemm  <p>We use GNU <code>autoconf(1)</code> as a tool to deal with
20615589c42SPeter Wemm  portability issues. The right way to leverage an OS-specific
20715589c42SPeter Wemm  feature is to modify the autoconf specification files
20815589c42SPeter Wemm  (configure.in and aclocal.m4) to set up a new feature macro,
20915589c42SPeter Wemm  which you then use to condition your code.</p>
21015589c42SPeter Wemm
21115589c42SPeter Wemm  <h1><a name="documentation" id="documentation">Documentation
21215589c42SPeter Wemm  Conventions</a></h1>
21315589c42SPeter Wemm
21415589c42SPeter Wemm  <p>There are three kinds of documentation associated with this
21515589c42SPeter Wemm  package. Each has a different preferred format:</p>
21615589c42SPeter Wemm
21715589c42SPeter Wemm  <ul>
21815589c42SPeter Wemm    <li>Package-internal files (README, INSTALL, TO-DO etc.)</li>
21915589c42SPeter Wemm
22015589c42SPeter Wemm    <li>Manual pages.</li>
22115589c42SPeter Wemm
22215589c42SPeter Wemm    <li>Everything else (i.e., narrative documentation).</li>
22315589c42SPeter Wemm  </ul>
22415589c42SPeter Wemm
22515589c42SPeter Wemm  <p>Our conventions are simple:</p>
22615589c42SPeter Wemm
22715589c42SPeter Wemm  <ol>
22815589c42SPeter Wemm    <li><strong>Maintain package-internal files in plain
22915589c42SPeter Wemm    text.</strong> The expected viewer for them <em>more(1)</em> or
23015589c42SPeter Wemm    an editor window; there is no point in elaborate mark-up.</li>
23115589c42SPeter Wemm
23215589c42SPeter Wemm    <li><strong>Mark up manual pages in the man macros.</strong>
23315589c42SPeter Wemm    These have to be viewable through traditional <em>man(1)</em>
23415589c42SPeter Wemm    programs.</li>
23515589c42SPeter Wemm
23615589c42SPeter Wemm    <li><strong>Write everything else in HTML.</strong>
23715589c42SPeter Wemm    </li>
23815589c42SPeter Wemm  </ol>
23915589c42SPeter Wemm
24015589c42SPeter Wemm  <p>When in doubt, HTMLize a master and use <em>lynx(1)</em> to
24115589c42SPeter Wemm  generate plain ASCII (as we do for the announcement
24215589c42SPeter Wemm  document).</p>
24315589c42SPeter Wemm
24415589c42SPeter Wemm  <p>The reason for choosing HTML is that it is (a) well-adapted
24515589c42SPeter Wemm  for on-line browsing through viewers that are everywhere; (b)
24615589c42SPeter Wemm  more easily readable as plain text than most other mark-ups, if
24715589c42SPeter Wemm  you do not have a viewer; and (c) carries enough information that
24815589c42SPeter Wemm  you can generate a nice-looking printed version from it. Also, of
24915589c42SPeter Wemm  course, it make exporting things like the announcement document
25015589c42SPeter Wemm  to WWW pretty trivial.</p>
25115589c42SPeter Wemm
25215589c42SPeter Wemm  <h1><a name="bugtrack" id="bugtrack">How to Report Bugs</a></h1>
25315589c42SPeter Wemm
25415589c42SPeter Wemm  <p>The <a name="bugreport" id="bugreport">reporting address for
25515589c42SPeter Wemm  bugs</a> is <a href=
25615589c42SPeter Wemm  "mailto:[email protected]">[email protected]</a>. This is a
25715589c42SPeter Wemm  majordomo list; to join, write to
25815589c42SPeter Wemm  <code>[email protected]</code> with a message
25915589c42SPeter Wemm  containing the line:</p>
26015589c42SPeter Wemm
26115589c42SPeter Wemm  <pre>
26215589c42SPeter Wemm             subscribe &lt;name&gt;@&lt;host.domain&gt;
26315589c42SPeter Wemm</pre>
26415589c42SPeter Wemm
26515589c42SPeter Wemm  <p>The <code>ncurses</code> code is maintained by a small group
26615589c42SPeter Wemm  of volunteers. While we try our best to fix bugs promptly, we
26715589c42SPeter Wemm  simply do not have a lot of hours to spend on elementary
26815589c42SPeter Wemm  hand-holding. We rely on intelligent cooperation from our users.
26915589c42SPeter Wemm  If you think you have found a bug in <code>ncurses</code>, there
27015589c42SPeter Wemm  are some steps you can take before contacting us that will help
27115589c42SPeter Wemm  get the bug fixed quickly.</p>
27215589c42SPeter Wemm
27315589c42SPeter Wemm  <p>In order to use our bug-fixing time efficiently, we put people
27415589c42SPeter Wemm  who show us they have taken these steps at the head of our queue.
27515589c42SPeter Wemm  This means that if you do not, you will probably end up at the
27615589c42SPeter Wemm  tail end and have to wait a while.</p>
27715589c42SPeter Wemm
27815589c42SPeter Wemm  <ol>
27915589c42SPeter Wemm    <li>Develop a recipe to reproduce the bug.
28015589c42SPeter Wemm
28115589c42SPeter Wemm      <p>Bugs we can reproduce are likely to be fixed very quickly,
28215589c42SPeter Wemm      often within days. The most effective single thing you can do
28315589c42SPeter Wemm      to get a quick fix is develop a way we can duplicate the bad
28415589c42SPeter Wemm      behavior &mdash; ideally, by giving us source for a small,
28515589c42SPeter Wemm      portable test program that breaks the library. (Even better
28615589c42SPeter Wemm      is a keystroke recipe using one of the test programs provided
28715589c42SPeter Wemm      with the distribution.)</p>
28815589c42SPeter Wemm    </li>
28915589c42SPeter Wemm
29015589c42SPeter Wemm    <li>Try to reproduce the bug on a different terminal type.
29115589c42SPeter Wemm
29215589c42SPeter Wemm      <p>In our experience, most of the behaviors people report as
29315589c42SPeter Wemm      library bugs are actually due to subtle problems in terminal
29415589c42SPeter Wemm      descriptions. This is especially likely to be true if you are
29515589c42SPeter Wemm      using a traditional asynchronous terminal or PC-based
29615589c42SPeter Wemm      terminal emulator, rather than xterm or a UNIX console
29715589c42SPeter Wemm      entry.</p>
29815589c42SPeter Wemm
29915589c42SPeter Wemm      <p>It is therefore extremely helpful if you can tell us
30015589c42SPeter Wemm      whether or not your problem reproduces on other terminal
30115589c42SPeter Wemm      types. Usually you will have both a console type and xterm
30215589c42SPeter Wemm      available; please tell us whether or not your bug reproduces
30315589c42SPeter Wemm      on both.</p>
30415589c42SPeter Wemm
30515589c42SPeter Wemm      <p>If you have xterm available, it is also good to collect
30615589c42SPeter Wemm      xterm reports for different window sizes. This is especially
30715589c42SPeter Wemm      true if you normally use an unusual xterm window size &mdash;
30815589c42SPeter Wemm      a surprising number of the bugs we have seen are either
30915589c42SPeter Wemm      triggered or masked by these.</p>
31015589c42SPeter Wemm    </li>
31115589c42SPeter Wemm
31215589c42SPeter Wemm    <li>Generate and examine a trace file for the broken behavior.
31315589c42SPeter Wemm
31415589c42SPeter Wemm      <p>Recompile your program with the debugging versions of the
31515589c42SPeter Wemm      libraries. Insert a <code>trace()</code> call with the
31615589c42SPeter Wemm      argument set to <code>TRACE_UPDATE</code>. (See <a href=
31715589c42SPeter Wemm      "ncurses-intro.html#debugging">"Writing Programs with
31815589c42SPeter Wemm      NCURSES"</a> for details on trace levels.) Reproduce your
31915589c42SPeter Wemm      bug, then look at the trace file to see what the library was
32015589c42SPeter Wemm      actually doing.</p>
32115589c42SPeter Wemm
32215589c42SPeter Wemm      <p>Another frequent cause of apparent bugs is application
32315589c42SPeter Wemm      coding errors that cause the wrong things to be put on the
32415589c42SPeter Wemm      virtual screen. Looking at the virtual-screen dumps in the
32515589c42SPeter Wemm      trace file will tell you immediately if this is happening,
32615589c42SPeter Wemm      and save you from the possible embarrassment of being told
32715589c42SPeter Wemm      that the bug is in your code and is your problem rather than
32815589c42SPeter Wemm      ours.</p>
32915589c42SPeter Wemm
33015589c42SPeter Wemm      <p>If the virtual-screen dumps look correct but the bug
33115589c42SPeter Wemm      persists, it is possible to crank up the trace level to give
33215589c42SPeter Wemm      more and more information about the library's update actions
33315589c42SPeter Wemm      and the control sequences it issues to perform them. The test
33415589c42SPeter Wemm      directory of the distribution contains a tool for digesting
33515589c42SPeter Wemm      these logs to make them less tedious to wade through.</p>
33615589c42SPeter Wemm
33715589c42SPeter Wemm      <p>Often you will find terminfo problems at this stage by
33815589c42SPeter Wemm      noticing that the escape sequences put out for various
33915589c42SPeter Wemm      capabilities are wrong. If not, you are likely to learn
34015589c42SPeter Wemm      enough to be able to characterize any bug in the
34115589c42SPeter Wemm      screen-update logic quite exactly.</p>
34215589c42SPeter Wemm    </li>
34315589c42SPeter Wemm
34415589c42SPeter Wemm    <li>Report details and symptoms, not just interpretations.
34515589c42SPeter Wemm
34615589c42SPeter Wemm      <p>If you do the preceding two steps, it is very likely that
34715589c42SPeter Wemm      you will discover the nature of the problem yourself and be
34815589c42SPeter Wemm      able to send us a fix. This will create happy feelings all
34915589c42SPeter Wemm      around and earn you good karma for the first time you run
35015589c42SPeter Wemm      into a bug you really cannot characterize and fix
35115589c42SPeter Wemm      yourself.</p>
35215589c42SPeter Wemm
35315589c42SPeter Wemm      <p>If you are still stuck, at least you will know what to
35415589c42SPeter Wemm      tell us. Remember, we need details. If you guess about what
35515589c42SPeter Wemm      is safe to leave out, you are too likely to be wrong.</p>
35615589c42SPeter Wemm
35715589c42SPeter Wemm      <p>If your bug produces a bad update, include a trace file.
35815589c42SPeter Wemm      Try to make the trace at the <em>least</em> voluminous level
35915589c42SPeter Wemm      that pins down the bug. Logs that have been through
36015589c42SPeter Wemm      tracemunch are OK, it does not throw away any information
36115589c42SPeter Wemm      (actually they are better than un-munched ones because they
36215589c42SPeter Wemm      are easier to read).</p>
36315589c42SPeter Wemm
36415589c42SPeter Wemm      <p>If your bug produces a core-dump, please include a
36515589c42SPeter Wemm      symbolic stack trace generated by gdb(1) or your local
36615589c42SPeter Wemm      equivalent.</p>
36715589c42SPeter Wemm
36815589c42SPeter Wemm      <p>Tell us about every terminal on which you have reproduced
36915589c42SPeter Wemm      the bug &mdash; and every terminal on which you cannot.
37015589c42SPeter Wemm      Ideally, send us terminfo sources for all of these (yours
37115589c42SPeter Wemm      might differ from ours).</p>
37215589c42SPeter Wemm
37315589c42SPeter Wemm      <p>Include your ncurses version and your OS/machine type, of
37415589c42SPeter Wemm      course! You can find your ncurses version in the
37515589c42SPeter Wemm      <code>curses.h</code> file.</p>
37615589c42SPeter Wemm    </li>
37715589c42SPeter Wemm  </ol>
37815589c42SPeter Wemm
37915589c42SPeter Wemm  <p>If your problem smells like a logic error or in cursor
38015589c42SPeter Wemm  movement or scrolling or a bad capability, there are a couple of
38115589c42SPeter Wemm  tiny test frames for the library algorithms in the progs
38215589c42SPeter Wemm  directory that may help you isolate it. These are not part of the
38315589c42SPeter Wemm  normal build, but do have their own make productions.</p>
38415589c42SPeter Wemm
38515589c42SPeter Wemm  <p>The most important of these is <code>mvcur</code>, a test
38615589c42SPeter Wemm  frame for the cursor-movement optimization code. With this
38715589c42SPeter Wemm  program, you can see directly what control sequences will be
38815589c42SPeter Wemm  emitted for any given cursor movement or scroll/insert/delete
38915589c42SPeter Wemm  operations. If you think you have got a bad capability
39015589c42SPeter Wemm  identified, you can disable it and test again. The program is
39115589c42SPeter Wemm  command-driven and has on-line help.</p>
39215589c42SPeter Wemm
39315589c42SPeter Wemm  <p>If you think the vertical-scroll optimization is broken, or
39415589c42SPeter Wemm  just want to understand how it works better, build
39515589c42SPeter Wemm  <code>hashmap</code> and read the header comments of
39615589c42SPeter Wemm  <code>hardscroll.c</code> and <code>hashmap.c</code>; then try it
39715589c42SPeter Wemm  out. You can also test the hardware-scrolling optimization
39815589c42SPeter Wemm  separately with <code>hardscroll</code>.</p>
39915589c42SPeter Wemm
40015589c42SPeter Wemm  <h1><a name="ncurslib" id="ncurslib">A Tour of the Ncurses
40115589c42SPeter Wemm  Library</a></h1>
40215589c42SPeter Wemm
40315589c42SPeter Wemm  <h2><a name="loverview" id="loverview">Library Overview</a></h2>
404*4a1a9510SRong-En Fan
40515589c42SPeter Wemm  <p>Most of the library is superstructure &mdash; fairly trivial
40615589c42SPeter Wemm  convenience interfaces to a small set of basic functions and data
40715589c42SPeter Wemm  structures used to manipulate the virtual screen (in particular,
40815589c42SPeter Wemm  none of this code does any I/O except through calls to more
40915589c42SPeter Wemm  fundamental modules described below). The files</p>
41015589c42SPeter Wemm
41115589c42SPeter Wemm  <blockquote>
41215589c42SPeter Wemm    <code>lib_addch.c lib_bkgd.c lib_box.c lib_chgat.c lib_clear.c
41315589c42SPeter Wemm    lib_clearok.c lib_clrbot.c lib_clreol.c lib_colorset.c
41415589c42SPeter Wemm    lib_data.c lib_delch.c lib_delwin.c lib_echo.c lib_erase.c
41515589c42SPeter Wemm    lib_gen.c lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c
41615589c42SPeter Wemm    lib_insch.c lib_insdel.c lib_insstr.c lib_instr.c
41715589c42SPeter Wemm    lib_isendwin.c lib_keyname.c lib_leaveok.c lib_move.c
41815589c42SPeter Wemm    lib_mvwin.c lib_overlay.c lib_pad.c lib_printw.c lib_redrawln.c
41915589c42SPeter Wemm    lib_scanw.c lib_screen.c lib_scroll.c lib_scrollok.c
42015589c42SPeter Wemm    lib_scrreg.c lib_set_term.c lib_slk.c lib_slkatr_set.c
42115589c42SPeter Wemm    lib_slkatrof.c lib_slkatron.c lib_slkatrset.c lib_slkattr.c
42215589c42SPeter Wemm    lib_slkclear.c lib_slkcolor.c lib_slkinit.c lib_slklab.c
42315589c42SPeter Wemm    lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c
42415589c42SPeter Wemm    lib_unctrl.c lib_vline.c lib_wattroff.c lib_wattron.c
42515589c42SPeter Wemm    lib_window.c</code>
42615589c42SPeter Wemm  </blockquote>
42715589c42SPeter Wemm
42815589c42SPeter Wemm  <p>are all in this category. They are very unlikely to need
42915589c42SPeter Wemm  change, barring bugs or some fundamental reorganization in the
43015589c42SPeter Wemm  underlying data structures.</p>
43115589c42SPeter Wemm
43215589c42SPeter Wemm  <p>These files are used only for debugging support:</p>
43315589c42SPeter Wemm
43415589c42SPeter Wemm  <blockquote>
43515589c42SPeter Wemm    <code>lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c
43615589c42SPeter Wemm    lib_tracedmp.c lib_tracemse.c trace_buf.c</code>
43715589c42SPeter Wemm  </blockquote>
43815589c42SPeter Wemm
43915589c42SPeter Wemm  <p>It is rather unlikely you will ever need to change these,
44015589c42SPeter Wemm  unless you want to introduce a new debug trace level for some
44115589c42SPeter Wemm  reason.</p>
44215589c42SPeter Wemm
44315589c42SPeter Wemm  <p>There is another group of files that do direct I/O via
44415589c42SPeter Wemm  <em>tputs()</em>, computations on the terminal capabilities, or
44515589c42SPeter Wemm  queries to the OS environment, but nevertheless have only fairly
44615589c42SPeter Wemm  low complexity. These include:</p>
44715589c42SPeter Wemm
44815589c42SPeter Wemm  <blockquote>
44915589c42SPeter Wemm    <code>lib_acs.c lib_beep.c lib_color.c lib_endwin.c
45015589c42SPeter Wemm    lib_initscr.c lib_longname.c lib_newterm.c lib_options.c
45115589c42SPeter Wemm    lib_termcap.c lib_ti.c lib_tparm.c lib_tputs.c lib_vidattr.c
45215589c42SPeter Wemm    read_entry.c.</code>
45315589c42SPeter Wemm  </blockquote>
45415589c42SPeter Wemm
45515589c42SPeter Wemm  <p>They are likely to need revision only if ncurses is being
45615589c42SPeter Wemm  ported to an environment without an underlying terminfo
45715589c42SPeter Wemm  capability representation.</p>
45815589c42SPeter Wemm
45915589c42SPeter Wemm  <p>These files have serious hooks into the tty driver and signal
46015589c42SPeter Wemm  facilities:</p>
46115589c42SPeter Wemm
46215589c42SPeter Wemm  <blockquote>
46315589c42SPeter Wemm    <code>lib_kernel.c lib_baudrate.c lib_raw.c lib_tstp.c
46415589c42SPeter Wemm    lib_twait.c</code>
46515589c42SPeter Wemm  </blockquote>
46615589c42SPeter Wemm
46715589c42SPeter Wemm  <p>If you run into porting snafus moving the package to another
46815589c42SPeter Wemm  UNIX, the problem is likely to be in one of these files. The file
46915589c42SPeter Wemm  <code>lib_print.c</code> uses sleep(2) and also falls in this
47015589c42SPeter Wemm  category.</p>
47115589c42SPeter Wemm
47215589c42SPeter Wemm  <p>Almost all of the real work is done in the files</p>
47315589c42SPeter Wemm
47415589c42SPeter Wemm  <blockquote>
47515589c42SPeter Wemm    <code>hardscroll.c hashmap.c lib_addch.c lib_doupdate.c
47615589c42SPeter Wemm    lib_getch.c lib_mouse.c lib_mvcur.c lib_refresh.c lib_setup.c
47715589c42SPeter Wemm    lib_vidattr.c</code>
47815589c42SPeter Wemm  </blockquote>
47915589c42SPeter Wemm
48015589c42SPeter Wemm  <p>Most of the algorithmic complexity in the library lives in
48115589c42SPeter Wemm  these files. If there is a real bug in <strong>ncurses</strong>
48215589c42SPeter Wemm  itself, it is probably here. We will tour some of these files in
48315589c42SPeter Wemm  detail below (see <a href="#engine">The Engine Room</a>).</p>
48415589c42SPeter Wemm
48515589c42SPeter Wemm  <p>Finally, there is a group of files that is actually most of
48615589c42SPeter Wemm  the terminfo compiler. The reason this code lives in the
48715589c42SPeter Wemm  <strong>ncurses</strong> library is to support fallback to
48815589c42SPeter Wemm  /etc/termcap. These files include</p>
48915589c42SPeter Wemm
49015589c42SPeter Wemm  <blockquote>
49115589c42SPeter Wemm    <code>alloc_entry.c captoinfo.c comp_captab.c comp_error.c
49215589c42SPeter Wemm    comp_hash.c comp_parse.c comp_scan.c parse_entry.c
49315589c42SPeter Wemm    read_termcap.c write_entry.c</code>
49415589c42SPeter Wemm  </blockquote>
49515589c42SPeter Wemm
49615589c42SPeter Wemm  <p>We will discuss these in the compiler tour.</p>
49715589c42SPeter Wemm
49815589c42SPeter Wemm  <h2><a name="engine" id="engine">The Engine Room</a></h2>
49915589c42SPeter Wemm
50015589c42SPeter Wemm  <h3><a name="input" id="input">Keyboard Input</a></h3>
50115589c42SPeter Wemm
50215589c42SPeter Wemm  <p>All <code>ncurses</code> input funnels through the function
50315589c42SPeter Wemm  <code>wgetch()</code>, defined in <code>lib_getch.c</code>. This
50415589c42SPeter Wemm  function is tricky; it has to poll for keyboard and mouse events
50515589c42SPeter Wemm  and do a running match of incoming input against the set of
50615589c42SPeter Wemm  defined special keys.</p>
50715589c42SPeter Wemm
50815589c42SPeter Wemm  <p>The central data structure in this module is a FIFO queue,
50915589c42SPeter Wemm  used to match multiple-character input sequences against
51015589c42SPeter Wemm  special-key capabilities; also to implement pushback via
51115589c42SPeter Wemm  <code>ungetch()</code>.</p>
51215589c42SPeter Wemm
51315589c42SPeter Wemm  <p>The <code>wgetch()</code> code distinguishes between function
51415589c42SPeter Wemm  key sequences and the same sequences typed manually by doing a
51515589c42SPeter Wemm  timed wait after each input character that could lead a function
51615589c42SPeter Wemm  key sequence. If the entire sequence takes less than 1 second, it
51715589c42SPeter Wemm  is assumed to have been generated by a function key press.</p>
51815589c42SPeter Wemm
51915589c42SPeter Wemm  <p>Hackers bruised by previous encounters with variant
52015589c42SPeter Wemm  <code>select(2)</code> calls may find the code in
52115589c42SPeter Wemm  <code>lib_twait.c</code> interesting. It deals with the problem
52215589c42SPeter Wemm  that some BSD selects do not return a reliable time-left value.
52315589c42SPeter Wemm  The function <code>timed_wait()</code> effectively simulates a
52415589c42SPeter Wemm  System V select.</p>
52515589c42SPeter Wemm
52615589c42SPeter Wemm  <h3><a name="mouse" id="mouse">Mouse Events</a></h3>
52715589c42SPeter Wemm
52815589c42SPeter Wemm  <p>If the mouse interface is active, <code>wgetch()</code> polls
52915589c42SPeter Wemm  for mouse events each call, before it goes to the keyboard for
53015589c42SPeter Wemm  input. It is up to <code>lib_mouse.c</code> how the polling is
53115589c42SPeter Wemm  accomplished; it may vary for different devices.</p>
53215589c42SPeter Wemm
53315589c42SPeter Wemm  <p>Under xterm, however, mouse event notifications come in via
53415589c42SPeter Wemm  the keyboard input stream. They are recognized by having the
53515589c42SPeter Wemm  <strong>kmous</strong> capability as a prefix. This is kind of
53615589c42SPeter Wemm  klugey, but trying to wire in recognition of a mouse key prefix
53715589c42SPeter Wemm  without going through the function-key machinery would be just
53815589c42SPeter Wemm  too painful, and this turns out to imply having the prefix
53915589c42SPeter Wemm  somewhere in the function-key capabilities at terminal-type
54015589c42SPeter Wemm  initialization.</p>
54115589c42SPeter Wemm
54215589c42SPeter Wemm  <p>This kluge only works because <strong>kmous</strong> is not
54315589c42SPeter Wemm  actually used by any historic terminal type or curses
54415589c42SPeter Wemm  implementation we know of. Best guess is it is a relic of some
54515589c42SPeter Wemm  forgotten experiment in-house at Bell Labs that did not leave any
54615589c42SPeter Wemm  traces in the publicly-distributed System V terminfo files. If
54715589c42SPeter Wemm  System V or XPG4 ever gets serious about using it again, this
54815589c42SPeter Wemm  kluge may have to change.</p>
54915589c42SPeter Wemm
55015589c42SPeter Wemm  <p>Here are some more details about mouse event handling:</p>
55115589c42SPeter Wemm
55215589c42SPeter Wemm  <p>The <code>lib_mouse()</code> code is logically split into a
55315589c42SPeter Wemm  lower level that accepts event reports in a device-dependent
55415589c42SPeter Wemm  format and an upper level that parses mouse gestures and filters
55515589c42SPeter Wemm  events. The mediating data structure is a circular queue of event
55615589c42SPeter Wemm  structures.</p>
55715589c42SPeter Wemm
55815589c42SPeter Wemm  <p>Functionally, the lower level's job is to pick up primitive
55915589c42SPeter Wemm  events and put them on the circular queue. This can happen in one
56015589c42SPeter Wemm  of two ways: either (a) <code>_nc_mouse_event()</code> detects a
56115589c42SPeter Wemm  series of incoming mouse reports and queues them, or (b) code in
56215589c42SPeter Wemm  <code>lib_getch.c</code> detects the <strong>kmous</strong>
56315589c42SPeter Wemm  prefix in the keyboard input stream and calls _nc_mouse_inline to
56415589c42SPeter Wemm  queue up a series of adjacent mouse reports.</p>
56515589c42SPeter Wemm
56615589c42SPeter Wemm  <p>In either case, <code>_nc_mouse_parse()</code> should be
56715589c42SPeter Wemm  called after the series is accepted to parse the digested mouse
56815589c42SPeter Wemm  reports (low-level events) into a gesture (a high-level or
56915589c42SPeter Wemm  composite event).</p>
57015589c42SPeter Wemm
57115589c42SPeter Wemm  <h3><a name="output" id="output">Output and Screen Updating</a></h3>
57215589c42SPeter Wemm
57315589c42SPeter Wemm  <p>With the single exception of character echoes during a
57415589c42SPeter Wemm  <code>wgetnstr()</code> call (which simulates cooked-mode line
57515589c42SPeter Wemm  editing in an ncurses window), the library normally does all its
57615589c42SPeter Wemm  output at refresh time.</p>
57715589c42SPeter Wemm
57815589c42SPeter Wemm  <p>The main job is to go from the current state of the screen (as
57915589c42SPeter Wemm  represented in the <code>curscr</code> window structure) to the
58015589c42SPeter Wemm  desired new state (as represented in the <code>newscr</code>
58115589c42SPeter Wemm  window structure), while doing as little I/O as possible.</p>
58215589c42SPeter Wemm
58315589c42SPeter Wemm  <p>The brains of this operation are the modules
58415589c42SPeter Wemm  <code>hashmap.c</code>, <code>hardscroll.c</code> and
585*4a1a9510SRong-En Fan  <code>lib_doupdate.c</code>; the latter two use
58615589c42SPeter Wemm  <code>lib_mvcur.c</code>. Essentially, what happens looks like
58715589c42SPeter Wemm  this:</p>
58815589c42SPeter Wemm
58915589c42SPeter Wemm  <ul>
59015589c42SPeter Wemm    <li>
59115589c42SPeter Wemm      <p>The <code>hashmap.c</code> module tries to detect vertical
59215589c42SPeter Wemm      motion changes between the real and virtual screens. This
59315589c42SPeter Wemm      information is represented by the oldindex members in the
59415589c42SPeter Wemm      newscr structure. These are modified by vertical-motion and
59515589c42SPeter Wemm      clear operations, and both are re-initialized after each
59615589c42SPeter Wemm      update. To this change-journalling information, the hashmap
59715589c42SPeter Wemm      code adds deductions made using a modified Heckel algorithm
59815589c42SPeter Wemm      on hash values generated from the line contents.</p>
59915589c42SPeter Wemm    </li>
60015589c42SPeter Wemm
60115589c42SPeter Wemm    <li>
60215589c42SPeter Wemm      <p>The <code>hardscroll.c</code> module computes an optimum
60315589c42SPeter Wemm      set of scroll, insertion, and deletion operations to make the
60415589c42SPeter Wemm      indices match. It calls <code>_nc_mvcur_scrolln()</code> in
60515589c42SPeter Wemm      <code>lib_mvcur.c</code> to do those motions.</p>
60615589c42SPeter Wemm    </li>
60715589c42SPeter Wemm
60815589c42SPeter Wemm    <li>
60915589c42SPeter Wemm      <p>Then <code>lib_doupdate.c</code> goes to work. Its job is
61015589c42SPeter Wemm      to do line-by-line transformations of <code>curscr</code>
61115589c42SPeter Wemm      lines to <code>newscr</code> lines. Its main tool is the
61215589c42SPeter Wemm      routine <code>mvcur()</code> in <code>lib_mvcur.c</code>.
61315589c42SPeter Wemm      This routine does cursor-movement optimization, attempting to
61415589c42SPeter Wemm      get from given screen location A to given location B in the
61515589c42SPeter Wemm      fewest output characters possible.</p>
61615589c42SPeter Wemm    </li>
61715589c42SPeter Wemm  </ul>
61815589c42SPeter Wemm
61915589c42SPeter Wemm  <p>If you want to work on screen optimizations, you should use
62015589c42SPeter Wemm  the fact that (in the trace-enabled version of the library)
62115589c42SPeter Wemm  enabling the <code>TRACE_TIMES</code> trace level causes a report
62215589c42SPeter Wemm  to be emitted after each screen update giving the elapsed time
62315589c42SPeter Wemm  and a count of characters emitted during the update. You can use
62415589c42SPeter Wemm  this to tell when an update optimization improves efficiency.</p>
62515589c42SPeter Wemm
62615589c42SPeter Wemm  <p>In the trace-enabled version of the library, it is also
62715589c42SPeter Wemm  possible to disable and re-enable various optimizations at
62815589c42SPeter Wemm  runtime by tweaking the variable
62915589c42SPeter Wemm  <code>_nc_optimize_enable</code>. See the file
63015589c42SPeter Wemm  <code>include/curses.h.in</code> for mask values, near the
63115589c42SPeter Wemm  end.</p>
63215589c42SPeter Wemm
63315589c42SPeter Wemm  <h1><a name="fmnote" id="fmnote">The Forms and Menu Libraries</a></h1>
63415589c42SPeter Wemm
63515589c42SPeter Wemm  <p>The forms and menu libraries should work reliably in any
63615589c42SPeter Wemm  environment you can port ncurses to. The only portability issue
63715589c42SPeter Wemm  anywhere in them is what flavor of regular expressions the
63815589c42SPeter Wemm  built-in form field type TYPE_REGEXP will recognize.</p>
63915589c42SPeter Wemm
64015589c42SPeter Wemm  <p>The configuration code prefers the POSIX regex facility,
64115589c42SPeter Wemm  modeled on System V's, but will settle for BSD regexps if the
64215589c42SPeter Wemm  former is not available.</p>
64315589c42SPeter Wemm
64415589c42SPeter Wemm  <p>Historical note: the panels code was written primarily to
64515589c42SPeter Wemm  assist in porting u386mon 2.0 (comp.sources.misc v14i001-4) to
64615589c42SPeter Wemm  systems lacking panels support; u386mon 2.10 and beyond use it.
64715589c42SPeter Wemm  This version has been slightly cleaned up for
64815589c42SPeter Wemm  <code>ncurses</code>.</p>
64915589c42SPeter Wemm
65015589c42SPeter Wemm  <h1><a name="tic" id="tic">A Tour of the Terminfo Compiler</a></h1>
65115589c42SPeter Wemm
65215589c42SPeter Wemm  <p>The <strong>ncurses</strong> implementation of
65315589c42SPeter Wemm  <strong>tic</strong> is rather complex internally; it has to do a
65415589c42SPeter Wemm  trying combination of missions. This starts with the fact that,
65515589c42SPeter Wemm  in addition to its normal duty of compiling terminfo sources into
65615589c42SPeter Wemm  loadable terminfo binaries, it has to be able to handle termcap
65715589c42SPeter Wemm  syntax and compile that too into terminfo entries.</p>
65815589c42SPeter Wemm
65915589c42SPeter Wemm  <p>The implementation therefore starts with a table-driven,
66015589c42SPeter Wemm  dual-mode lexical analyzer (in <code>comp_scan.c</code>). The
66115589c42SPeter Wemm  lexer chooses its mode (termcap or terminfo) based on the first
66215589c42SPeter Wemm  &ldquo;,&rdquo; or &ldquo;:&rdquo; it finds in each entry. The
66315589c42SPeter Wemm  lexer does all the work of recognizing capability names and
66415589c42SPeter Wemm  values; the grammar above it is trivial, just "parse entries till
66515589c42SPeter Wemm  you run out of file".</p>
66615589c42SPeter Wemm
66715589c42SPeter Wemm  <h2><a name="nonuse" id="nonuse">Translation of
66815589c42SPeter Wemm  Non-<strong>use</strong> Capabilities</a></h2>
66915589c42SPeter Wemm
67015589c42SPeter Wemm  <p>Translation of most things besides <strong>use</strong>
67115589c42SPeter Wemm  capabilities is pretty straightforward. The lexical analyzer's
67215589c42SPeter Wemm  tokenizer hands each capability name to a hash function, which
67315589c42SPeter Wemm  drives a table lookup. The table entry yields an index which is
67415589c42SPeter Wemm  used to look up the token type in another table, and controls
67515589c42SPeter Wemm  interpretation of the value.</p>
67615589c42SPeter Wemm
67715589c42SPeter Wemm  <p>One possibly interesting aspect of the implementation is the
67815589c42SPeter Wemm  way the compiler tables are initialized. All the tables are
67915589c42SPeter Wemm  generated by various awk/sed/sh scripts from a master table
68015589c42SPeter Wemm  <code>include/Caps</code>; these scripts actually write C
68115589c42SPeter Wemm  initializers which are linked to the compiler. Furthermore, the
68215589c42SPeter Wemm  hash table is generated in the same way, so it doesn't have to be
68315589c42SPeter Wemm  generated at compiler startup time (another benefit of this
68415589c42SPeter Wemm  organization is that the hash table can be in shareable text
68515589c42SPeter Wemm  space).</p>
68615589c42SPeter Wemm
68715589c42SPeter Wemm  <p>Thus, adding a new capability is usually pretty trivial, just
68815589c42SPeter Wemm  a matter of adding one line to the <code>include/Caps</code>
68915589c42SPeter Wemm  file. We will have more to say about this in the section on
69015589c42SPeter Wemm  <a href="#translation">Source-Form Translation</a>.</p>
69115589c42SPeter Wemm
69215589c42SPeter Wemm  <h2><a name="uses" id="uses">Use Capability Resolution</a></h2>
69315589c42SPeter Wemm
69415589c42SPeter Wemm  <p>The background problem that makes <strong>tic</strong> tricky
69515589c42SPeter Wemm  is not the capability translation itself, it is the resolution of
69615589c42SPeter Wemm  <strong>use</strong> capabilities. Older versions would not
69715589c42SPeter Wemm  handle forward <strong>use</strong> references for this reason
69815589c42SPeter Wemm  (that is, a using terminal always had to follow its use target in
69915589c42SPeter Wemm  the source file). By doing this, they got away with a simple
70015589c42SPeter Wemm  implementation tactic; compile everything as it blows by, then
70115589c42SPeter Wemm  resolve uses from compiled entries.</p>
70215589c42SPeter Wemm
70315589c42SPeter Wemm  <p>This will not do for <strong>ncurses</strong>. The problem is
70415589c42SPeter Wemm  that that the whole compilation process has to be embeddable in
70515589c42SPeter Wemm  the <strong>ncurses</strong> library so that it can be called by
70615589c42SPeter Wemm  the startup code to translate termcap entries on the fly. The
70715589c42SPeter Wemm  embedded version cannot go promiscuously writing everything it
70815589c42SPeter Wemm  translates out to disk &mdash; for one thing, it will typically
70915589c42SPeter Wemm  be running with non-root permissions.</p>
71015589c42SPeter Wemm
71115589c42SPeter Wemm  <p>So our <strong>tic</strong> is designed to parse an entire
71215589c42SPeter Wemm  terminfo file into a doubly-linked circular list of entry
71315589c42SPeter Wemm  structures in-core, and then do <strong>use</strong> resolution
71415589c42SPeter Wemm  in-memory before writing everything out. This design has other
71515589c42SPeter Wemm  advantages: it makes forward and back use-references equally easy
71615589c42SPeter Wemm  (so we get the latter for free), and it makes checking for name
71715589c42SPeter Wemm  collisions before they are written out easy to do.</p>
71815589c42SPeter Wemm
71915589c42SPeter Wemm  <p>And this is exactly how the embedded version works. But the
72015589c42SPeter Wemm  stand-alone user-accessible version of <strong>tic</strong>
72115589c42SPeter Wemm  partly reverts to the historical strategy; it writes to disk (not
72215589c42SPeter Wemm  keeping in core) any entry with no <strong>use</strong>
72315589c42SPeter Wemm  references.</p>
72415589c42SPeter Wemm
72515589c42SPeter Wemm  <p>This is strictly a core-economy kluge, implemented because the
72615589c42SPeter Wemm  terminfo master file is large enough that some core-poor systems
72715589c42SPeter Wemm  swap like crazy when you compile it all in memory...there have
72815589c42SPeter Wemm  been reports of this process taking <strong>three hours</strong>,
72915589c42SPeter Wemm  rather than the twenty seconds or less typical on the author's
73015589c42SPeter Wemm  development box.</p>
73115589c42SPeter Wemm
73215589c42SPeter Wemm  <p>So. The executable <strong>tic</strong> passes the
73315589c42SPeter Wemm  entry-parser a hook that <em>immediately</em> writes out the
73415589c42SPeter Wemm  referenced entry if it has no use capabilities. The compiler main
73515589c42SPeter Wemm  loop refrains from adding the entry to the in-core list when this
73615589c42SPeter Wemm  hook fires. If some other entry later needs to reference an entry
73715589c42SPeter Wemm  that got written immediately, that is OK; the resolution code
73815589c42SPeter Wemm  will fetch it off disk when it cannot find it in core.</p>
73915589c42SPeter Wemm
74015589c42SPeter Wemm  <p>Name collisions will still be detected, just not as cleanly.
74115589c42SPeter Wemm  The <code>write_entry()</code> code complains before overwriting
74215589c42SPeter Wemm  an entry that postdates the time of <strong>tic</strong>'s first
74315589c42SPeter Wemm  call to <code>write_entry()</code>, Thus it will complain about
74415589c42SPeter Wemm  overwriting entries newly made during the <strong>tic</strong>
74515589c42SPeter Wemm  run, but not about overwriting ones that predate it.</p>
74615589c42SPeter Wemm
74715589c42SPeter Wemm  <h2><a name="translation" id="translation">Source-Form
74815589c42SPeter Wemm  Translation</a></h2>
74915589c42SPeter Wemm
75015589c42SPeter Wemm  <p>Another use of <strong>tic</strong> is to do source
75115589c42SPeter Wemm  translation between various termcap and terminfo formats. There
75215589c42SPeter Wemm  are more variants out there than you might think; the ones we
75315589c42SPeter Wemm  know about are described in the <strong>captoinfo(1)</strong>
75415589c42SPeter Wemm  manual page.</p>
75515589c42SPeter Wemm
75615589c42SPeter Wemm  <p>The translation output code (<code>dump_entry()</code> in
75715589c42SPeter Wemm  <code>ncurses/dump_entry.c</code>) is shared with the
75815589c42SPeter Wemm  <strong>infocmp(1)</strong> utility. It takes the same internal
75915589c42SPeter Wemm  representation used to generate the binary form and dumps it to
76015589c42SPeter Wemm  standard output in a specified format.</p>
76115589c42SPeter Wemm
76215589c42SPeter Wemm  <p>The <code>include/Caps</code> file has a header comment
76315589c42SPeter Wemm  describing ways you can specify source translations for
76415589c42SPeter Wemm  nonstandard capabilities just by altering the master table. It is
76515589c42SPeter Wemm  possible to set up capability aliasing or tell the compiler to
76615589c42SPeter Wemm  plain ignore a given capability without writing any C code at
76715589c42SPeter Wemm  all.</p>
76815589c42SPeter Wemm
76915589c42SPeter Wemm  <p>For circumstances where you need to do algorithmic
77015589c42SPeter Wemm  translation, there are functions in <code>parse_entry.c</code>
77115589c42SPeter Wemm  called after the parse of each entry that are specifically
77215589c42SPeter Wemm  intended to encapsulate such translations. This, for example, is
77315589c42SPeter Wemm  where the AIX <strong>box1</strong> capability get translated to
77415589c42SPeter Wemm  an <strong>acsc</strong> string.</p>
77515589c42SPeter Wemm
77615589c42SPeter Wemm  <h1><a name="utils" id="utils">Other Utilities</a></h1>
77715589c42SPeter Wemm
77815589c42SPeter Wemm  <p>The <strong>infocmp</strong> utility is just a wrapper around
77915589c42SPeter Wemm  the same entry-dumping code used by <strong>tic</strong> for
78015589c42SPeter Wemm  source translation. Perhaps the one interesting aspect of the
78115589c42SPeter Wemm  code is the use of a predicate function passed in to
78215589c42SPeter Wemm  <code>dump_entry()</code> to control which capabilities are
78315589c42SPeter Wemm  dumped. This is necessary in order to handle both the ordinary
78415589c42SPeter Wemm  De-compilation case and entry difference reporting.</p>
78515589c42SPeter Wemm
78615589c42SPeter Wemm  <p>The <strong>tput</strong> and <strong>clear</strong> utilities
78715589c42SPeter Wemm  just do an entry load followed by a <code>tputs()</code> of a
78815589c42SPeter Wemm  selected capability.</p>
78915589c42SPeter Wemm
79015589c42SPeter Wemm  <h1><a name="style" id="style">Style Tips for Developers</a></h1>
79115589c42SPeter Wemm
79215589c42SPeter Wemm  <p>See the TO-DO file in the top-level directory of the source
79315589c42SPeter Wemm  distribution for additions that would be particularly useful.</p>
79415589c42SPeter Wemm
79515589c42SPeter Wemm  <p>The prefix <code>_nc_</code> should be used on library public
79615589c42SPeter Wemm  functions that are not part of the curses API in order to prevent
79715589c42SPeter Wemm  pollution of the application namespace. If you have to add to or
79815589c42SPeter Wemm  modify the function prototypes in curses.h.in, read
79915589c42SPeter Wemm  ncurses/MKlib_gen.sh first so you can avoid breaking XSI
80015589c42SPeter Wemm  conformance. Please join the ncurses mailing list. See the
80115589c42SPeter Wemm  INSTALL file in the top level of the distribution for details on
80215589c42SPeter Wemm  the list.</p>
80315589c42SPeter Wemm
80415589c42SPeter Wemm  <p>Look for the string <code>FIXME</code> in source files to tag
80515589c42SPeter Wemm  minor bugs and potential problems that could use fixing.</p>
80615589c42SPeter Wemm
80715589c42SPeter Wemm  <p>Do not try to auto-detect OS features in the main body of the
80815589c42SPeter Wemm  C code. That is the job of the configuration system.</p>
80915589c42SPeter Wemm
81015589c42SPeter Wemm  <p>To hold down complexity, do make your code data-driven.
81115589c42SPeter Wemm  Especially, if you can drive logic from a table filtered out of
81215589c42SPeter Wemm  <code>include/Caps</code>, do it. If you find you need to augment
81315589c42SPeter Wemm  the data in that file in order to generate the proper table, that
81415589c42SPeter Wemm  is still preferable to ad-hoc code &mdash; that is why the fifth
81515589c42SPeter Wemm  field (flags) is there.</p>
81615589c42SPeter Wemm
81715589c42SPeter Wemm  <p>Have fun!</p>
81815589c42SPeter Wemm
81915589c42SPeter Wemm  <h1><a name="port" id="port">Porting Hints</a></h1>
82015589c42SPeter Wemm
82115589c42SPeter Wemm  <p>The following notes are intended to be a first step towards
82215589c42SPeter Wemm  DOS and Macintosh ports of the ncurses libraries.</p>
82315589c42SPeter Wemm
82415589c42SPeter Wemm  <p>The following library modules are &ldquo;pure curses&rdquo;;
82515589c42SPeter Wemm  they operate only on the curses internal structures, do all
82615589c42SPeter Wemm  output through other curses calls (not including
82715589c42SPeter Wemm  <code>tputs()</code> and <code>putp()</code>) and do not call any
82815589c42SPeter Wemm  other UNIX routines such as signal(2) or the stdio library. Thus,
82915589c42SPeter Wemm  they should not need to be modified for single-terminal
83015589c42SPeter Wemm  ports.</p>
83115589c42SPeter Wemm
83215589c42SPeter Wemm  <blockquote>
83315589c42SPeter Wemm    <code>lib_addch.c lib_addstr.c lib_bkgd.c lib_box.c lib_clear.c
83415589c42SPeter Wemm    lib_clrbot.c lib_clreol.c lib_delch.c lib_delwin.c lib_erase.c
83515589c42SPeter Wemm    lib_inchstr.c lib_insch.c lib_insdel.c lib_insstr.c
83615589c42SPeter Wemm    lib_keyname.c lib_move.c lib_mvwin.c lib_newwin.c lib_overlay.c
83715589c42SPeter Wemm    lib_pad.c lib_printw.c lib_refresh.c lib_scanw.c lib_scroll.c
83815589c42SPeter Wemm    lib_scrreg.c lib_set_term.c lib_touch.c lib_tparm.c lib_tputs.c
83915589c42SPeter Wemm    lib_unctrl.c lib_window.c panel.c</code>
84015589c42SPeter Wemm  </blockquote>
84115589c42SPeter Wemm
84215589c42SPeter Wemm  <p>This module is pure curses, but calls outstr():</p>
84315589c42SPeter Wemm
84415589c42SPeter Wemm  <blockquote>
84515589c42SPeter Wemm    <code>lib_getstr.c</code>
84615589c42SPeter Wemm  </blockquote>
84715589c42SPeter Wemm
84815589c42SPeter Wemm  <p>These modules are pure curses, except that they use
84915589c42SPeter Wemm  <code>tputs()</code> and <code>putp()</code>:</p>
85015589c42SPeter Wemm
85115589c42SPeter Wemm  <blockquote>
85215589c42SPeter Wemm    <code>lib_beep.c lib_color.c lib_endwin.c lib_options.c
85315589c42SPeter Wemm    lib_slk.c lib_vidattr.c</code>
85415589c42SPeter Wemm  </blockquote>
85515589c42SPeter Wemm
85615589c42SPeter Wemm  <p>This modules assist in POSIX emulation on non-POSIX
85715589c42SPeter Wemm  systems:</p>
85815589c42SPeter Wemm
85915589c42SPeter Wemm  <dl>
86015589c42SPeter Wemm    <dt>sigaction.c</dt>
86115589c42SPeter Wemm
86215589c42SPeter Wemm    <dd>signal calls</dd>
86315589c42SPeter Wemm  </dl>
86415589c42SPeter Wemm
86515589c42SPeter Wemm  <p>The following source files will not be needed for a
86615589c42SPeter Wemm  single-terminal-type port.</p>
86715589c42SPeter Wemm
86815589c42SPeter Wemm  <blockquote>
86915589c42SPeter Wemm    <code>alloc_entry.c captoinfo.c clear.c comp_captab.c
87015589c42SPeter Wemm    comp_error.c comp_hash.c comp_main.c comp_parse.c comp_scan.c
87115589c42SPeter Wemm    dump_entry.c infocmp.c parse_entry.c read_entry.c tput.c
87215589c42SPeter Wemm    write_entry.c</code>
87315589c42SPeter Wemm  </blockquote>
87415589c42SPeter Wemm
87515589c42SPeter Wemm  <p>The following modules will use
87615589c42SPeter Wemm  open()/read()/write()/close()/lseek() on files, but no other OS
87715589c42SPeter Wemm  calls.</p>
87815589c42SPeter Wemm
87915589c42SPeter Wemm  <dl>
88015589c42SPeter Wemm    <dt>lib_screen.c</dt>
88115589c42SPeter Wemm
88215589c42SPeter Wemm    <dd>used to read/write screen dumps</dd>
88315589c42SPeter Wemm
88415589c42SPeter Wemm    <dt>lib_trace.c</dt>
88515589c42SPeter Wemm
88615589c42SPeter Wemm    <dd>used to write trace data to the logfile</dd>
88715589c42SPeter Wemm  </dl>
88815589c42SPeter Wemm
88915589c42SPeter Wemm  <p>Modules that would have to be modified for a port start
89015589c42SPeter Wemm  here:</p>
89115589c42SPeter Wemm
89215589c42SPeter Wemm  <p>The following modules are &ldquo;pure curses&rdquo; but
89315589c42SPeter Wemm  contain assumptions inappropriate for a memory-mapped port.</p>
89415589c42SPeter Wemm
89515589c42SPeter Wemm  <dl>
89615589c42SPeter Wemm    <dt>lib_longname.c</dt>
89715589c42SPeter Wemm
89815589c42SPeter Wemm    <dd>assumes there may be multiple terminals</dd>
89915589c42SPeter Wemm
90015589c42SPeter Wemm    <dt>lib_acs.c</dt>
90115589c42SPeter Wemm
90215589c42SPeter Wemm    <dd>assumes acs_map as a double indirection</dd>
90315589c42SPeter Wemm
90415589c42SPeter Wemm    <dt>lib_mvcur.c</dt>
90515589c42SPeter Wemm
90615589c42SPeter Wemm    <dd>assumes cursor moves have variable cost</dd>
90715589c42SPeter Wemm
90815589c42SPeter Wemm    <dt>lib_termcap.c</dt>
90915589c42SPeter Wemm
91015589c42SPeter Wemm    <dd>assumes there may be multiple terminals</dd>
91115589c42SPeter Wemm
91215589c42SPeter Wemm    <dt>lib_ti.c</dt>
91315589c42SPeter Wemm
91415589c42SPeter Wemm    <dd>assumes there may be multiple terminals</dd>
915  </dl>
916
917  <p>The following modules use UNIX-specific calls:</p>
918
919  <dl>
920    <dt>lib_doupdate.c</dt>
921
922    <dd>input checking</dd>
923
924    <dt>lib_getch.c</dt>
925
926    <dd>read()</dd>
927
928    <dt>lib_initscr.c</dt>
929
930    <dd>getenv()</dd>
931
932    <dt>lib_newterm.c</dt>
933
934    <dt>lib_baudrate.c</dt>
935
936    <dt>lib_kernel.c</dt>
937
938    <dd>various tty-manipulation and system calls</dd>
939
940    <dt>lib_raw.c</dt>
941
942    <dd>various tty-manipulation calls</dd>
943
944    <dt>lib_setup.c</dt>
945
946    <dd>various tty-manipulation calls</dd>
947
948    <dt>lib_restart.c</dt>
949
950    <dd>various tty-manipulation calls</dd>
951
952    <dt>lib_tstp.c</dt>
953
954    <dd>signal-manipulation calls</dd>
955
956    <dt>lib_twait.c</dt>
957
958    <dd>gettimeofday(), select().</dd>
959  </dl>
960
961  <hr>
962
963  <address>
964    Eric S. Raymond &lt;[email protected]&gt;
965  </address>
966  (Note: This is <em>not</em> the <a href="#bugtrack">bug
967  address</a>!)
968</body>
969</html>
970