📄 ncurses-intro.doc
字号:
The initscr() function actually calls a function named newterm() to do most of its work. If you are writing a program that opens multiple terminals, use newterm() directly. For each call, you will have to specify a terminal type and a pair of file pointers; each call will return a screen reference, and stdscr will be set to the last one allocated. You will switch between screens with the set_term call. Note that you will also have to call def_shell_mode and def_prog_mode on each tty yourself. Testing for Terminal Capabilities Sometimes you may want to write programs that test for the presence of various capabilities before deciding whether to go into ncurses mode. An easy way to do this is to call setupterm(), then use the functions tigetflag(), tigetnum(), and tigetstr() to do your testing. A particularly useful case of this often comes up when you want to test whether a given terminal type should be treated as `smart' (cursor-addressable) or `stupid'. The right way to test this is to see if the return value of tigetstr("cup") is non-NULL. Alternatively, you can include the term.h file and test the value of the macro cursor_address. Tuning for Speed Use the addchstr() family of functions for fast screen-painting of text when you know the text doesn't contain any control characters. Try to make attribute changes infrequent on your screens. Don't use the immedok() option! Special Features of NCURSES The wresize() function allows you to resize a window in place. The associated resizeterm() function simplifies the construction of SIGWINCH handlers, for resizing all windows. The define_key() function allows you to define at runtime function-key control sequences which are not in the terminal description. The keyok() function allows you to temporarily enable or disable interpretation of any function-key control sequence. The use_default_colors() function allows you to construct applications which can use the terminal's default foreground and background colors as an additional "default" color. Several terminal emulators support this feature, which is based on ISO 6429. Ncurses supports up 16 colors, unlike SVr4 curses which defines only 8. While most terminals which provide color allow only 8 colors, about a quarter (including XFree86 xterm) support 16 colors.Compatibility with Older Versions Despite our best efforts, there are some differences between ncurses and the (undocumented!) behavior of older curses implementations. These arise from ambiguities or omissions in the documentation of the API. Refresh of Overlapping Windows If you define two windows A and B that overlap, and then alternately scribble on and refresh them, the changes made to the overlapping region under historic curses versions were often not documented precisely. To understand why this is a problem, remember that screen updates are calculated between two representations of the entire display. The documentation says that when you refresh a window, it is first copied to to the virtual screen, and then changes are calculated to update the physical screen (and applied to the terminal). But "copied to" is not very specific, and subtle differences in how copying works can produce different behaviors in the case where two overlapping windows are each being refreshed at unpredictable intervals. What happens to the overlapping region depends on what wnoutrefresh() does with its argument -- what portions of the argument window it copies to the virtual screen. Some implementations do "change copy", copying down only locations in the window that have changed (or been marked changed with wtouchln() and friends). Some implementations do "entire copy", copying all window locations to the virtual screen whether or not they have changed. The ncurses library itself has not always been consistent on this score. Due to a bug, versions 1.8.7 to 1.9.8a did entire copy. Versions 1.8.6 and older, and versions 1.9.9 and newer, do change copy. For most commercial curses implementations, it is not documented and not known for sure (at least not to the ncurses maintainers) whether they do change copy or entire copy. We know that System V release 3 curses has logic in it that looks like an attempt to do change copy, but the surrounding logic and data representations are sufficiently complex, and our knowledge sufficiently indirect, that it's hard to know whether this is reliable. It is not clear what the SVr4 documentation and XSI standard intend. The XSI Curses standard barely mentions wnoutrefresh(); the SVr4 documents seem to be describing entire-copy, but it is possible with some effort and straining to read them the other way. It might therefore be unwise to rely on either behavior in programs that might have to be linked with other curses implementations. Instead, you can do an explicit touchwin() before the wnoutrefresh() call to guarantee an entire-contents copy anywhere. The really clean way to handle this is to use the panels library. If, when you want a screen update, you do update_panels(), it will do all the necessary wnoutrfresh() calls for whatever panel stacking order you have defined. Then you can do one doupdate() and there will be a single burst of physical I/O that will do all your updates. Background Erase If you have been using a very old versions of ncurses (1.8.7 or older) you may be surprised by the behavior of the erase functions. In older versions, erased areas of a window were filled with a blank modified by the window's current attribute (as set by wattrset(), wattron(), wattroff() and friends). In newer versions, this is not so. Instead, the attribute of erased blanks is normal unless and until it is modified by the functions bkgdset() or wbkgdset(). This change in behavior conforms ncurses to System V Release 4 and the XSI Curses standard.XSI Curses Conformance The ncurses library is intended to be base-level conformant with the XSI Curses standard from X/Open. Many extended-level features (in fact, almost all features not directly concerned with wide characters and internationalization) are also supported. One effect of XSI conformance is the change in behavior described under "Background Erase -- Compatibility with Old Versions". Also, ncurses meets the XSI requirement that every macro entry point have a corresponding function which may be linked (and will be prototype-checked) if the macro definition is disabled with #undef. The Panels Library The ncurses library by itself provides good support for screen displays in which the windows are tiled (non-overlapping). In the more general case that windows may overlap, you have to use a series of wnoutrefresh() calls followed by a doupdate(), and be careful about the order you do the window refreshes in. It has to be bottom-upwards, otherwise parts of windows that should be obscured will show through. When your interface design is such that windows may dive deeper into the visibility stack or pop to the top at runtime, the resulting book-keeping can be tedious and difficult to get right. Hence the panels library. The panel library first appeared in AT&T System V. The version documented here is the panel code distributed with ncurses.Compiling With the Panels Library Your panels-using modules must import the panels library declarations with #include <panel.h> and must be linked explicitly with the panels library using an -lpanel argument. Note that they must also link the ncurses library with -lncurses. Many linkers are two-pass and will accept either order, but it is still good practice to put -lpanel first and -lncurses second.Overview of Panels A panel object is a window that is implicitly treated as part of a deck including all other panel objects. The deck has an implicit bottom-to-top visibility order. The panels library includes an update function (analogous to refresh()) that displays all panels in the deck in the proper order to resolve overlaps. The standard window, stdscr, is considered below all panels. Details on the panels functions are available in the man pages. We'll just hit the highlights here. You create a panel from a window by calling new_panel() on a window pointer. It then becomes the top of the deck. The panel's window is available as the value of panel_window() called with the panel pointer as argument. You can delete a panel (removing it from the deck) with del_panel. This will not deallocate the associated window; you have to do that yourself. You can replace a panel's window with a different window by calling replace_window. The new window may be of different size; the panel code will re-compute all overlaps. This operation doesn't change the panel's position in the deck. To move a panel's window, use move_panel(). The mvwin() function on the panel's window isn't sufficient because it doesn't update the panels library's representation of where the windows are. This operation leaves the panel's depth, contents, and size unchanged. Two functions (top_panel(), bottom_panel()) are provided for rearranging the deck. The first pops its argument window to the top of the deck; the second sends it to the bottom. Either operation leaves the panel's screen location, contents, and size unchanged. The function update_panels() does all the wnoutrefresh() calls needed to prepare for doupdate() (which you must call yourself, afterwards). Typically, you will want to call update_panels() and doupdate() just before accepting command input, once in each cycle of interaction with the user. If you call update_panels() after each and every panel write, you'll generate a lot of unnecessary refresh activity and screen flicker.Panels, Input, and the Standard Screen You shouldn't mix wnoutrefresh() or wrefresh() operations with panels code; this will work only if the argument window is either in the top panel or unobscured by any other panels. The stsdcr window is a special case. It is considered below all panels. Because changes to panels may obscure parts of stdscr, though, you should call update_panels() before doupdate() even when you only change stdscr. Note that wgetch automatically calls wrefresh. Therefore, before requesting input from a panel window, you need to be sure that the panel is totally unobscured. There is presently no way to display changes to one obscured panel without repainting all panels.Hiding Panels It's possible to remove a panel from the deck temporarily; use hide_panel for this. Use show_panel() to render it visible again. The predicate function panel_hidden tests whether or not a panel is hidden. The panel_update code ignores hidden panels. You cannot do top_panel() or bottom_panel on a hidden panel(). Other panels operations are applicable.Miscellaneous Other Facilities It's possible to navigate the deck using the functions panel_above() and panel_below. Handed a panel pointer, they return the panel above or below that panel. Handed NULL, they return the bottom-most or top-most panel. Every panel has an associated user pointer, not used by the panel code, to which you can attach application data. See the man page documentation of set_panel_userptr() and panel_userptr for details. The Menu Library A menu is a screen display that assists the user to choose some subset of a given set of items. The menu library is a curses extension that supports easy programming of menu hierarchies with a uniform but flexible interface. The menu library first appeared in AT&T System V. The version documented here is the menu code distributed with ncurses.Compiling With the menu Library Your menu-using modules must import the menu library declarations with #include <menu.h> and must be linked explicitly with the menus library using an -lmenu argument. Note that they must also link the ncurses library with -lncurses. Many linkers are two-pass and will accept either order, but it is still good practice to put -lmenu first and -lncurses second.Overview of Menus The menus created by this library consist of collections of items including a name string part and a description string part. To make menus, you create groups of these items and connect them with menu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -