<!--
- $Id: hackguide.html,v 1.30 2017/05/05 11:50:09 tom Exp $
+ $Id: hackguide.html,v 1.36 2022/11/26 19:31:56 tom Exp $
****************************************************************************
- * Copyright (c) 1998-2012,2017 Free Software Foundation, Inc. *
+ * Copyright 2019-2020,2022 Thomas E. Dickey *
+ * Copyright 2000-2013,2017 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
****************************************************************************
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-
<html>
<head>
<meta name="generator" content=
- "HTML Tidy for Linux (vers 25 March 2009), see www.w3.org">
-
+ "HTML Tidy for HTML5 for Linux version 5.6.0">
<title>A Hacker's Guide to Ncurses Internals</title>
- <link rev="made" href="mailto:bugs-ncurses@gnu.org">
+ <link rel="author" href="mailto:bugs-ncurses@gnu.org">
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii"><!--
This document is self-contained, *except* that there is one relative link to
this one.
-->
</head>
-
<body>
- <h1>A Hacker's Guide to NCURSES</h1>
-
- <h1>Contents</h1>
+ <h1 class="no-header">A Hacker's Guide to NCURSES</h1>
- <ul>
- <li><a href="#abstract">Abstract</a></li>
-
- <li>
- <a href="#objective">Objective of the Package</a>
+ <h2>A Hacker's Guide to NCURSES</h2>
- <ul>
- <li><a href="#whysvr4">Why System V Curses?</a></li>
+ <div class="nav">
+ <h2>Contents</h2>
- <li><a href="#extensions">How to Design Extensions</a></li>
- </ul>
- </li>
+ <ul>
+ <li><a href="#abstract">Abstract</a></li>
- <li><a href="#portability">Portability and
- Configuration</a></li>
+ <li>
+ <a href="#objective">Objective of the Package</a>
+ <ul>
+ <li><a href="#whysvr4">Why System V Curses?</a></li>
- <li><a href="#documentation">Documentation Conventions</a></li>
+ <li><a href="#extensions">How to Design Extensions</a></li>
+ </ul>
+ </li>
- <li><a href="#bugtrack">How to Report Bugs</a></li>
+ <li><a href="#portability">Portability and Configuration</a></li>
- <li>
- <a href="#ncurslib">A Tour of the Ncurses Library</a>
+ <li><a href="#documentation">Documentation Conventions</a></li>
- <ul>
- <li><a href="#loverview">Library Overview</a></li>
+ <li><a href="#bugtrack">How to Report Bugs</a></li>
- <li><a href="#engine">The Engine Room</a></li>
+ <li>
+ <a href="#ncurslib">A Tour of the Ncurses Library</a>
+ <ul>
+ <li><a href="#loverview">Library Overview</a></li>
- <li><a href="#input">Keyboard Input</a></li>
+ <li><a href="#engine">The Engine Room</a></li>
- <li><a href="#mouse">Mouse Events</a></li>
+ <li><a href="#input">Keyboard Input</a></li>
- <li><a href="#output">Output and Screen Updating</a></li>
- </ul>
- </li>
+ <li><a href="#mouse">Mouse Events</a></li>
- <li><a href="#fmnote">The Forms and Menu Libraries</a></li>
+ <li><a href="#output">Output and Screen Updating</a></li>
+ </ul>
+ </li>
- <li>
- <a href="#tic">A Tour of the Terminfo Compiler</a>
+ <li><a href="#fmnote">The Forms and Menu Libraries</a></li>
- <ul>
- <li><a href="#nonuse">Translation of
- Non-<strong>use</strong> Capabilities</a></li>
+ <li>
+ <a href="#tic">A Tour of the Terminfo Compiler</a>
+ <ul>
+ <li><a href="#nonuse">Translation of
+ Non-<strong>use</strong> Capabilities</a></li>
- <li><a href="#uses">Use Capability Resolution</a></li>
+ <li><a href="#uses">Use Capability Resolution</a></li>
- <li><a href="#translation">Source-Form Translation</a></li>
- </ul>
- </li>
+ <li><a href="#translation">Source-Form Translation</a></li>
+ </ul>
+ </li>
- <li><a href="#utils">Other Utilities</a></li>
+ <li><a href="#utils">Other Utilities</a></li>
- <li><a href="#style">Style Tips for Developers</a></li>
+ <li><a href="#style">Style Tips for Developers</a></li>
- <li><a href="#port">Porting Hints</a></li>
- </ul>
+ <li><a href="#port">Porting Hints</a></li>
+ </ul>
+ </div>
- <h1><a name="abstract" id="abstract">Abstract</a></h1>
+ <h2><a name="abstract" id="abstract">Abstract</a></h2>
<p>This document is a hacker's tour of the
<strong>ncurses</strong> library and utilities. It discusses
anyone who is interested in porting, extending or improving the
package.</p>
- <h1><a name="objective" id="objective">Objective of the
- Package</a></h1>
+ <h2><a name="objective" id="objective">Objective of the
+ Package</a></h2>
<p>The objective of the <strong>ncurses</strong> package is to
provide a free software API for character-cell terminals and
— we cannot add features if it means breaking the portion
of the API corresponding to historical curses versions.</p>
- <h2><a name="whysvr4" id="whysvr4">Why System V Curses?</a></h2>
+ <h3><a name="whysvr4" id="whysvr4">Why System V Curses?</a></h3>
<p>We used System V curses as a model, reverse-engineering their
API, in order to fulfill the first two objectives.</p>
So conformance with System V took us most of the way to
base-level XSI conformance.</p>
- <h2><a name="extensions" id="extensions">How to Design
- Extensions</a></h2>
+ <h3><a name="extensions" id="extensions">How to Design
+ Extensions</a></h3>
<p>The third objective (standards conformance) requires that it
be easy to condition source code using <strong>ncurses</strong>
library header. You can use this to condition the calls to the
mouse API calls.</p>
- <h1><a name="portability" id="portability">Portability and
- Configuration</a></h1>
+ <h2><a name="portability" id="portability">Portability and
+ Configuration</a></h2>
<p>Code written for <strong>ncurses</strong> may assume an
ANSI-standard C compiler and POSIX-compatible OS interface. It
(configure.in and aclocal.m4) to set up a new feature macro,
which you then use to condition your code.</p>
- <h1><a name="documentation" id="documentation">Documentation
- Conventions</a></h1>
+ <h2><a name="documentation" id="documentation">Documentation
+ Conventions</a></h2>
<p>There are three kinds of documentation associated with this
package. Each has a different preferred format:</p>
<ol>
<li><strong>Maintain package-internal files in plain
- text.</strong> The expected viewer for them <em>more(1)</em> or
+ text.</strong> The expected viewer for them is <em>more(1)</em> or
an editor window; there is no point in elaborate mark-up.</li>
<li><strong>Mark up manual pages in the man macros.</strong>
These have to be viewable through traditional <em>man(1)</em>
programs.</li>
- <li><strong>Write everything else in HTML.</strong></li>
+ <li><strong>Write everything else in HTML.</strong>
+ </li>
</ol>
<p>When in doubt, HTMLize a master and use <em>lynx(1)</em> to
course, it make exporting things like the announcement document
to WWW pretty trivial.</p>
- <h1><a name="bugtrack" id="bugtrack">How to Report Bugs</a></h1>
+ <h2><a name="bugtrack" id="bugtrack">How to Report Bugs</a></h2>
<p>The <a name="bugreport" id="bugreport">reporting address for
bugs</a> is <a href=
majordomo list; to join, write to
<code>bug-ncurses-request@gnu.org</code> with a message
containing the line:</p>
- <pre>
+
+ <pre class="code-block">
subscribe <name>@<host.domain>
</pre>
-
<p>The <code>ncurses</code> code is maintained by a small group
of volunteers. While we try our best to fix bugs promptly, we
simply do not have a lot of hours to spend on elementary
tail end and have to wait a while.</p>
<ol>
- <li>Develop a recipe to reproduce the bug.
-
+ <li><p>Develop a recipe to reproduce the bug.
<p>Bugs we can reproduce are likely to be fixed very quickly,
often within days. The most effective single thing you can do
to get a quick fix is develop a way we can duplicate the bad
with the distribution.)</p>
</li>
- <li>Try to reproduce the bug on a different terminal type.
-
+ <li><p>Try to reproduce the bug on a different terminal type.
<p>In our experience, most of the behaviors people report as
library bugs are actually due to subtle problems in terminal
descriptions. This is especially likely to be true if you are
triggered or masked by these.</p>
</li>
- <li>Generate and examine a trace file for the broken behavior.
-
+ <li><p>Generate and examine a trace file for the broken behavior.
<p>Recompile your program with the debugging versions of the
libraries. Insert a <code>trace()</code> call with the
argument set to <code>TRACE_UPDATE</code>. (See <a href=
screen-update logic quite exactly.</p>
</li>
- <li>Report details and symptoms, not just interpretations.
-
+ <li><p>Report details and symptoms, not just interpretations.
<p>If you do the preceding two steps, it is very likely that
you will discover the nature of the problem yourself and be
able to send us a fix. This will create happy feelings all
<p>Tell us about every terminal on which you have reproduced
the bug — and every terminal on which you cannot.
- Ideally, sent us terminfo sources for all of these (yours
+ Ideally, send us terminfo sources for all of these (yours
might differ from ours).</p>
<p>Include your ncurses version and your OS/machine type, of
out. You can also test the hardware-scrolling optimization
separately with <code>hardscroll</code>.</p>
- <h1><a name="ncurslib" id="ncurslib">A Tour of the Ncurses
- Library</a></h1>
+ <h2><a name="ncurslib" id="ncurslib">A Tour of the Ncurses
+ Library</a></h2>
- <h2><a name="loverview" id="loverview">Library Overview</a></h2>
+ <h3><a name="loverview" id="loverview">Library Overview</a></h3>
<p>Most of the library is superstructure — fairly trivial
convenience interfaces to a small set of basic functions and data
<p>We will discuss these in the compiler tour.</p>
- <h2><a name="engine" id="engine">The Engine Room</a></h2>
+ <h3><a name="engine" id="engine">The Engine Room</a></h3>
- <h3><a name="input" id="input">Keyboard Input</a></h3>
+ <h4><a name="input" id="input">Keyboard Input</a></h4>
<p>All <code>ncurses</code> input funnels through the function
<code>wgetch()</code>, defined in <code>lib_getch.c</code>. This
The function <code>timed_wait()</code> effectively simulates a
System V select.</p>
- <h3><a name="mouse" id="mouse">Mouse Events</a></h3>
+ <h4><a name="mouse" id="mouse">Mouse Events</a></h4>
<p>If the mouse interface is active, <code>wgetch()</code> polls
for mouse events each call, before it goes to the keyboard for
<p>Here are some more details about mouse event handling:</p>
- <p>The <code>lib_mouse()</code>code is logically split into a
+ <p>The <code>lib_mouse()</code> code is logically split into a
lower level that accepts event reports in a device-dependent
format and an upper level that parses mouse gestures and filters
events. The mediating data structure is a circular queue of event
reports (low-level events) into a gesture (a high-level or
composite event).</p>
- <h3><a name="output" id="output">Output and Screen
- Updating</a></h3>
+ <h4><a name="output" id="output">Output and Screen Updating</a></h4>
<p>With the single exception of character echoes during a
<code>wgetnstr()</code> call (which simulates cooked-mode line
<code>lib_mvcur.c</code>. Essentially, what happens looks like
this:</p>
- <p>The <code>hashmap.c</code> module tries to detect vertical
- motion changes between the real and virtual screens. This
- information is represented by the oldindex members in the newscr
- structure. These are modified by vertical-motion and clear
- operations, and both are re-initialized after each update. To
- this change-journalling information, the hashmap code adds
- deductions made using a modified Heckel algorithm on hash values
- generated from the line contents.</p>
-
- <p>The <code>hardscroll.c</code> module computes an optimum set
- of scroll, insertion, and deletion operations to make the indices
- match. It calls <code>_nc_mvcur_scrolln()</code> in
- <code>lib_mvcur.c</code> to do those motions.</p>
-
- <p>Then <code>lib_doupdate.c</code> goes to work. Its job is to
- do line-by-line transformations of <code>curscr</code> lines to
- <code>newscr</code> lines. Its main tool is the routine
- <code>mvcur()</code> in <code>lib_mvcur.c</code>. This routine
- does cursor-movement optimization, attempting to get from given
- screen location A to given location B in the fewest output
- characters possible.</p>
+ <ul>
+ <li>
+ <p>The <code>hashmap.c</code> module tries to detect vertical
+ motion changes between the real and virtual screens. This
+ information is represented by the oldindex members in the
+ newscr structure. These are modified by vertical-motion and
+ clear operations, and both are re-initialized after each
+ update. To this change-journalling information, the hashmap
+ code adds deductions made using a modified Heckel algorithm
+ on hash values generated from the line contents.</p>
+ </li>
+
+ <li>
+ <p>The <code>hardscroll.c</code> module computes an optimum
+ set of scroll, insertion, and deletion operations to make the
+ indices match. It calls <code>_nc_mvcur_scrolln()</code> in
+ <code>lib_mvcur.c</code> to do those motions.</p>
+ </li>
+
+ <li>
+ <p>Then <code>lib_doupdate.c</code> goes to work. Its job is
+ to do line-by-line transformations of <code>curscr</code>
+ lines to <code>newscr</code> lines. Its main tool is the
+ routine <code>mvcur()</code> in <code>lib_mvcur.c</code>.
+ This routine does cursor-movement optimization, attempting to
+ get from given screen location A to given location B in the
+ fewest output characters possible.</p>
+ </li>
+ </ul>
<p>If you want to work on screen optimizations, you should use
the fact that (in the trace-enabled version of the library)
<code>include/curses.h.in</code> for mask values, near the
end.</p>
- <h1><a name="fmnote" id="fmnote">The Forms and Menu
- Libraries</a></h1>
+ <h2><a name="fmnote" id="fmnote">The Forms and Menu Libraries</a></h2>
<p>The forms and menu libraries should work reliably in any
environment you can port ncurses to. The only portability issue
This version has been slightly cleaned up for
<code>ncurses</code>.</p>
- <h1><a name="tic" id="tic">A Tour of the Terminfo
- Compiler</a></h1>
+ <h2><a name="tic" id="tic">A Tour of the Terminfo Compiler</a></h2>
<p>The <strong>ncurses</strong> implementation of
<strong>tic</strong> is rather complex internally; it has to do a
values; the grammar above it is trivial, just "parse entries till
you run out of file".</p>
- <h2><a name="nonuse" id="nonuse">Translation of
- Non-<strong>use</strong> Capabilities</a></h2>
+ <h3><a name="nonuse" id="nonuse">Translation of
+ Non-<strong>use</strong> Capabilities</a></h3>
<p>Translation of most things besides <strong>use</strong>
capabilities is pretty straightforward. The lexical analyzer's
file. We will have more to say about this in the section on
<a href="#translation">Source-Form Translation</a>.</p>
- <h2><a name="uses" id="uses">Use Capability Resolution</a></h2>
+ <h3><a name="uses" id="uses">Use Capability Resolution</a></h3>
<p>The background problem that makes <strong>tic</strong> tricky
is not the capability translation itself, it is the resolution of
overwriting entries newly made during the <strong>tic</strong>
run, but not about overwriting ones that predate it.</p>
- <h2><a name="translation" id="translation">Source-Form
- Translation</a></h2>
+ <h3><a name="translation" id="translation">Source-Form
+ Translation</a></h3>
<p>Another use of <strong>tic</strong> is to do source
translation between various termcap and terminfo formats. There
where the AIX <strong>box1</strong> capability get translated to
an <strong>acsc</strong> string.</p>
- <h1><a name="utils" id="utils">Other Utilities</a></h1>
+ <h2><a name="utils" id="utils">Other Utilities</a></h2>
<p>The <strong>infocmp</strong> utility is just a wrapper around
the same entry-dumping code used by <strong>tic</strong> for
just do an entry load followed by a <code>tputs()</code> of a
selected capability.</p>
- <h1><a name="style" id="style">Style Tips for Developers</a></h1>
+ <h2><a name="style" id="style">Style Tips for Developers</a></h2>
<p>See the TO-DO file in the top-level directory of the source
distribution for additions that would be particularly useful.</p>
<p>Have fun!</p>
- <h1><a name="port" id="port">Porting Hints</a></h1>
+ <h2><a name="port" id="port">Porting Hints</a></h2>
<p>The following notes are intended to be a first step towards
DOS and Macintosh ports of the ncurses libraries.</p>
<dd>gettimeofday(), select().</dd>
</dl>
+
<hr>
<address>
Eric S. Raymond <esr@snark.thyrsus.com>
- </address>(Note: This is <em>not</em> the <a href="#bugtrack">bug
+ </address>
+ (Note: This is <em>not</em> the <a href="#bugtrack">bug
address</a>!)
</body>
</html>