📄 hackguide.doc
字号:
There's one other interactive tester, tctest, that exercises translation between termcap and terminfo formats. If you have a serious need to run this, you probably belong on our development team! A Tour of the Ncurses LibraryLibrary Overview Most of the library is superstructure -- fairly trivial convenience interfaces to a small set of basic functions and data structures used to manipulate the virtual screen (in particular, none of this code does any I/O except through calls to more fundamental modules described below). The files lib_addch.c lib_bkgd.c lib_box.c lib_chgat.c lib_clear.c lib_clearok.c lib_clrbot.c lib_clreol.c lib_colorset.c lib_data.c lib_delch.c lib_delwin.c lib_echo.c lib_erase.c lib_gen.c lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c lib_insch.c lib_insdel.c lib_insstr.c lib_instr.c lib_isendwin.c lib_keyname.c lib_leaveok.c lib_move.c lib_mvwin.c lib_overlay.c lib_pad.c lib_printw.c lib_redrawln.c lib_scanw.c lib_screen.c lib_scroll.c lib_scrollok.c lib_scrreg.c lib_set_term.c lib_slk.c lib_slkatr_set.c lib_slkatrof.c lib_slkatron.c lib_slkatrset.c lib_slkattr.c lib_slkclear.c lib_slkcolor.c lib_slkinit.c lib_slklab.c lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c lib_unctrl.c lib_vline.c lib_wattroff.c lib_wattron.c lib_window.c are all in this category. They are very unlikely to need change, barring bugs or some fundamental reorganization in the underlying data structures. These files are used only for debugging support: lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c lib_tracedmp.c lib_tracemse.c trace_buf.c It is rather unlikely you will ever need to change these, unless you want to introduce a new debug trace level for some reasoon. There is another group of files that do direct I/O via tputs(), computations on the terminal capabilities, or queries to the OS environment, but nevertheless have only fairly low complexity. These include: lib_acs.c lib_beep.c lib_color.c lib_endwin.c lib_initscr.c lib_longname.c lib_newterm.c lib_options.c lib_termcap.c lib_ti.c lib_tparm.c lib_tputs.c lib_vidattr.c read_entry.c. They are likely to need revision only if ncurses is being ported to an environment without an underlying terminfo capability representation. These files have serious hooks into the tty driver and signal facilities: lib_kernel.c lib_baudrate.c lib_raw.c lib_tstp.c lib_twait.c If you run into porting snafus moving the package to another UNIX, the problem is likely to be in one of these files. The file lib_print.c uses sleep(2) and also falls in this category. Almost all of the real work is done in the files hardscroll.c hashmap.c lib_addch.c lib_doupdate.c lib_getch.c lib_mouse.c lib_mvcur.c lib_refresh.c lib_setup.c lib_vidattr.c Most of the algorithmic complexity in the library lives in these files. If there is a real bug in ncurses itself, it's probably here. We'll tour some of these files in detail below (see The Engine Room). Finally, there is a group of files that is actually most of the terminfo compiler. The reason this code lives in the ncurses library is to support fallback to /etc/termcap. These files include alloc_entry.c captoinfo.c comp_captab.c comp_error.c comp_hash.c comp_parse.c comp_scan.c parse_entry.c read_termcap.c write_entry.c We'll discuss these in the compiler tour.The Engine Room Keyboard Input All ncurses input funnels through the function wgetch(), defined in lib_getch.c. This function is tricky; it has to poll for keyboard and mouse events and do a running match of incoming input against the set of defined special keys. The central data structure in this module is a FIFO queue, used to match multiple-character input sequences against special-key capabilities; also to implement pushback via ungetch(). The wgetch() code distinguishes between function key sequences and the same sequences typed manually by doing a timed wait after each input character that could lead a function key sequence. If the entire sequence takes less than 1 second, it is assumed to have been generated by a function key press. Hackers bruised by previous encounters with variant select(2) calls may find the code in lib_twait.c interesting. It deals with the problem that some BSD selects don't return a reliable time-left value. The function timed_wait() effectively simulates a System V select. Mouse Events If the mouse interface is active, wgetch() polls for mouse events each call, before it goes to the keyboard for input. It is up to lib_mouse.c how the polling is accomplished; it may vary for different devices. Under xterm, however, mouse event notifications come in via the keyboard input stream. They are recognized by having the kmous capability as a prefix. This is kind of klugey, but trying to wire in recognition of a mouse key prefix without going through the function-key machinery would be just too painful, and this turns out to imply having the prefix somewhere in the function-key capabilities at terminal-type initialization. This kluge only works because kmous isn't actually used by any historic terminal type or curses implementation we know of. Best guess is it's a relic of some forgotten experiment in-house at Bell Labs that didn't leave any traces in the publicly-distributed System V terminfo files. If System V or XPG4 ever gets serious about using it again, this kluge may have to change. Here are some more details about mouse event handling: The lib_mouse()code is logically split into a lower level that accepts event reports in a device-dependent format and an upper level that parses mouse gestures and filters events. The mediating data structure is a circular queue of event structures. Functionally, the lower level's job is to pick up primitive events and put them on the circular queue. This can happen in one of two ways: either (a) _nc_mouse_event() detects a series of incoming mouse reports and queues them, or (b) code in lib_getch.c detects the kmous prefix in the keyboard input stream and calls _nc_mouse_inline to queue up a series of adjacent mouse reports. In either case, _nc_mouse_parse() should be called after the series is accepted to parse the digested mouse reports (low-level events) into a gesture (a high-level or composite event). Output and Screen Updating With the single exception of character echoes during a wgetnstr() call (which simulates cooked-mode line editing in an ncurses window), the library normally does all its output at refresh time. The main job is to go from the current state of the screen (as represented in the curscr window structure) to the desired new state (as represented in the newscr window structure), while doing as little I/O as possible. The brains of this operation are the modules hashmap.c, hardscroll.c and lib_doupdate.c; the latter two use lib_mvcur.c. Essentially, what happens looks like this: The hashmap.c module tries to detect vertical motion changes between the real and virtual screens. This information is represented by the oldindex members in the newscr structure. These are modified by vertical-motion and clear operations, and both are re-initialized 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. The hardscroll.c module computes an optimum set of scroll, insertion, and deletion operations to make the indices match. It calls _nc_mvcur_scrolln() in lib_mvcur.c to do those motions. Then lib_doupdate.c goes to work. Its job is to do line-by-line transformations of curscr lines to newscr lines. Its main tool is the routine mvcur() in lib_mvcur.c. This routine does cursor-movement optimization, attempting to get from given screen location A to given location B in the fewest output characters posible. If you want to work on screen optimizations, you should use the fact that (in the trace-enabled version of the library) enabling the TRACE_TIMES trace level causes a report to be emitted after each screen update giving the elapsed time and a count of characters emitted during the update. You can use this to tell when an update optimization improves efficiency. In the trace-enabled version of the library, it is also possible to disable and re-enable various optimizations at runtime by tweaking the variable _nc_optimize_enable. See the file include/curses.h.in for mask values, near the end. The Forms and Menu Libraries The forms and menu libraries should work reliably in any environment you can port ncurses to. The only portability issue anywhere in them is what flavor of regular expressions the built-in form field type TYPE_REGEXP will recognize. The configuration code prefers the POSIX regex facility, modeled on System V's, but will settle for BSD regexps if the former isn't available. Historical note: the panels code was written primarily to assist in porting u386mon 2.0 (comp.sources.misc v14i001-4) to systems lacking panels support; u386mon 2.10 and beyond use it. This version has been slightly cleaned up for ncurses. A Tour of the Terminfo Compiler The ncurses implementation of tic is rather complex internally; it has to do a trying combination of missions. This starts with the fact that, in addition to its normal duty of compiling terminfo sources into loadable terminfo binaries, it has to be able to handle termcap syntax and compile that too into terminfo entries. The implementation therefore starts with a table-driven, dual-mode lexical analyzer (in comp_scan.c). The lexer chooses its mode (termcap or terminfo) based on the first `,' or `:' it finds in each entry. The lexer does all the work of recognizing capability names and values; the grammar above it is trivial, just "parse entries till you run out of file".Translation of Non-use Capabilities Translation of most things besides use capabilities is pretty straightforward. The lexical analyzer's tokenizer hands each capability name to a hash function, which drives a table lookup. The table entry yields an index which is used to look up the token type in another table, and controls interpretation of the value. One possibly interesting aspect of the implementation is the way the compiler tables are initialized. All the tables are generated by various awk/sed/sh scripts from a master table include/Caps; these
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -