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 — stable and reliable code, wide 13515589c42SPeter Wemm portability, good packaging, superior documentation.</li> 13615589c42SPeter Wemm 13715589c42SPeter Wemm <li>Featureful — 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 — 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 <name>@<host.domain> 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 — 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 — 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 — 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 — 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 “,” or “:” 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 — 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 — 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 “pure curses”; 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 “pure curses” 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 <[email protected]> 965 </address> 966 (Note: This is <em>not</em> the <a href="#bugtrack">bug 967 address</a>!) 968</body> 969</html> 970