📄 ncurses-intro.html
字号:
at the top of the program source. The screen package uses the Standard I/Olibrary, so <CODE><curses.h></CODE> includes<CODE><stdio.h></CODE>. <CODE><curses.h></CODE> also includes<CODE><termios.h></CODE>, <CODE><termio.h></CODE>, or<CODE><sgtty.h></CODE> depending on your system. It is redundant (butharmless) for the programmer to do these includes, too. In linking with<CODE>curses</CODE> you need to have <CODE>-lncurses</CODE> in your LDFLAGS or on thecommand line. There is no need for any other libraries.<H3><A NAME="updating">Updating the Screen</A></H3>In order to update the screen optimally, it is necessary for the routines toknow what the screen currently looks like and what the programmer wants it tolook like next. For this purpose, a data type (structure) named WINDOW isdefined which describes a window image to the routines, including its startingposition on the screen (the (y, x) coordinates of the upper left hand corner)and its size. One of these (called <CODE>curscr</CODE>, for current screen) is ascreen image of what the terminal currently looks like. Another screen (called<CODE>stdscr</CODE>, for standard screen) is provided by default to make changeson. <P>A window is a purely internal representation. It is used to build and store apotential image of a portion of the terminal. It doesn't bear any necessaryrelation to what is really on the terminal screen; it's more like ascratchpad or write buffer. <P>To make the section of physical screen corresponding to a window reflect thecontents of the window structure, the routine <CODE>refresh()</CODE> (or<CODE>wrefresh()</CODE> if the window is not <CODE>stdscr</CODE>) is called. <P>A given physical screen section may be within the scope of any number ofoverlapping windows. Also, changes can be made to windows in any order,without regard to motion efficiency. Then, at will, the programmer caneffectively say ``make it look like this,'' and let the package implementationdetermine the most efficient way to repaint the screen.<H3><A NAME="stdscr">Standard Windows and Function Naming Conventions</A></H3>As hinted above, the routines can use several windows, but two areautomatically given: <CODE>curscr</CODE>, which knows what the terminal looks like,and <CODE>stdscr</CODE>, which is what the programmer wants the terminal to looklike next. The user should never actually access <CODE>curscr</CODE> directly.Changes should be made to through the API, and then the routine<CODE>refresh()</CODE> (or <CODE>wrefresh()</CODE>) called. <P>Many functions are defined to use <CODE>stdscr</CODE> as a default screen. Forexample, to add a character to <CODE>stdscr</CODE>, one calls <CODE>addch()</CODE> withthe desired character as argument. To write to a different window. use theroutine <CODE>waddch()</CODE> (for `w'indow-specific addch()) is provided. Thisconvention of prepending function names with a `w' when they are to beapplied to specific windows is consistent. The only routines which do notfollow it are those for which a window must always be specified. <P>In order to move the current (y, x) coordinates from one point to another, theroutines <CODE>move()</CODE> and <CODE>wmove()</CODE> are provided. However, it isoften desirable to first move and then perform some I/O operation. In order toavoid clumsiness, most I/O routines can be preceded by the prefix 'mv' andthe desired (y, x) coordinates prepended to the arguments to the function. Forexample, the calls<PRE> move(y, x); addch(ch);</PRE>can be replaced by<PRE> mvaddch(y, x, ch);</PRE>and<PRE> wmove(win, y, x); waddch(win, ch);</PRE>can be replaced by<PRE> mvwaddch(win, y, x, ch);</PRE>Note that the window description pointer (win) comes before the added (y, x)coordinates. If a function requires a window pointer, it is always the firstparameter passed.<H3><A NAME="variables">Variables</A></H3>The <CODE>curses</CODE> library sets some variables describing the terminalcapabilities.<PRE> type name description ------------------------------------------------------------------ int LINES number of lines on the terminal int COLS number of columns on the terminal</PRE>The <CODE>curses.h</CODE> also introduces some <CODE>#define</CODE> constants and typesof general usefulness:<DL><DT> <CODE>bool</CODE><DD> boolean type, actually a `char' (e.g., <CODE>bool doneit;</CODE>)<DT> <CODE>TRUE</CODE><DD> boolean `true' flag (1).<DT> <CODE>FALSE</CODE><DD> boolean `false' flag (0).<DT> <CODE>ERR</CODE><DD> error flag returned by routines on a failure (-1).<DT> <CODE>OK</CODE><DD> error flag returned by routines when things go right.</DL><H2><A NAME="using">Using the Library</A></H2>Now we describe how to actually use the screen package. In it, we assume allupdating, reading, etc. is applied to <CODE>stdscr</CODE>. These instructions willwork on any window, providing you change the function names and parameters asmentioned above. <P>Here is a sample program to motivate the discussion:<PRE>#include <curses.h>#include <signal.h>static void finish(int sig);intmain(int argc, char *argv[]){ int num = 0; /* initialize your non-curses data structures here */ (void) signal(SIGINT, finish); /* arrange interrupts to terminate */ (void) initscr(); /* initialize the curses library */ keypad(stdscr, TRUE); /* enable keyboard mapping */ (void) nonl(); /* tell curses not to do NL->CR/NL on output */ (void) cbreak(); /* take input chars one at a time, no wait for \n */ (void) echo(); /* echo input - in color */ if (has_colors()) { start_color(); /* * Simple color assignment, often all we need. Color pair 0 cannot * be redefined. This example uses the same value for the color * pair as for the foreground color, though of course that is not * necessary: */ init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); init_pair(3, COLOR_YELLOW, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); init_pair(5, COLOR_CYAN, COLOR_BLACK); init_pair(6, COLOR_MAGENTA, COLOR_BLACK); init_pair(7, COLOR_WHITE, COLOR_BLACK); } for (;;) { int c = getch(); /* refresh, accept single keystroke of input */ attrset(COLOR_PAIR(num % 8)); num++; /* process the command keystroke */ } finish(0); /* we're done */}static void finish(int sig){ endwin(); /* do your non-curses wrapup here */ exit(0);}</PRE><H3><A NAME="starting">Starting up</A></H3>In order to use the screen package, the routines must know about terminalcharacteristics, and the space for <CODE>curscr</CODE> and <CODE>stdscr</CODE> must beallocated. These function <CODE>initscr()</CODE> does both these things. Since itmust allocate space for the windows, it can overflow memory when attempting todo so. On the rare occasions this happens, <CODE>initscr()</CODE> will terminatethe program with an error message. <CODE>initscr()</CODE> must always be calledbefore any of the routines which affect windows are used. If it is not, theprogram will core dump as soon as either <CODE>curscr</CODE> or <CODE>stdscr</CODE> arereferenced. However, it is usually best to wait to call it until after you aresure you will need it, like after checking for startup errors. Terminal statuschanging routines like <CODE>nl()</CODE> and <CODE>cbreak()</CODE> should be calledafter <CODE>initscr()</CODE>. <P>Once the screen windows have been allocated, you can set them up foryour program. If you want to, say, allow a screen to scroll, use<CODE>scrollok()</CODE>. If you want the cursor to be left in place afterthe last change, use <CODE>leaveok()</CODE>. If this isn't done,<CODE>refresh()</CODE> will move the cursor to the window's current (y, x)coordinates after updating it. <P>You can create new windows of your own using the functions <CODE>newwin()</CODE>,<CODE>derwin()</CODE>, and <CODE>subwin()</CODE>. The routine <CODE>delwin()</CODE> willallow you to get rid of old windows. All the options described above can beapplied to any window.<H3><A NAME="output">Output</A></H3>Now that we have set things up, we will want to actually update the terminal.The basic functions used to change what will go on a window are<CODE>addch()</CODE> and <CODE>move()</CODE>. <CODE>addch()</CODE> adds a character at thecurrent (y, x) coordinates. <CODE>move()</CODE> changes the current (y, x)coordinates to whatever you want them to be. It returns <CODE>ERR</CODE> if youtry to move off the window. As mentioned above, you can combine the two into<CODE>mvaddch()</CODE> to do both things at once. <P>The other output functions, such as <CODE>addstr()</CODE> and <CODE>printw()</CODE>,all call <CODE>addch()</CODE> to add characters to the window. <P>After you have put on the window what you want there, when you want the portionof the terminal covered by the window to be made to look like it, you must call<CODE>refresh()</CODE>. In order to optimize finding changes, <CODE>refresh()</CODE>assumes that any part of the window not changed since the last<CODE>refresh()</CODE> of that window has not been changed on the terminal, i.e.,that you have not refreshed a portion of the terminal with an overlappingwindow. If this is not the case, the routine <CODE>touchwin()</CODE> is providedto make it look like the entire window has been changed, thus making<CODE>refresh()</CODE> check the whole subsection of the terminal for changes. <P>If you call <CODE>wrefresh()</CODE> with <CODE>curscr</CODE> as its argument, it willmake the screen look like <CODE>curscr</CODE> thinks it looks like. This is usefulfor implementing a command which would redraw the screen in case it get messedup.<H3><A NAME="input">Input</A></H3>The complementary function to <CODE>addch()</CODE> is <CODE>getch()</CODE> which, ifecho is set, will call <CODE>addch()</CODE> to echo the character. Since thescreen package needs to know what is on the terminal at all times, ifcharacters are to be echoed, the tty must be in raw or cbreak mode. Sinceinitially the terminal has echoing enabled and is in ordinary ``cooked'' mode,one or the other has to changed before calling <CODE>getch()</CODE>; otherwise,the program's output will be unpredictable. <P>When you need to accept line-oriented input in a window, the functions<CODE>wgetstr()</CODE> and friends are available. There is even a <CODE>wscanw()</CODE>function that can do <CODE>scanf()</CODE>(3)-style multi-field parsing on windowinput. These pseudo-line-oriented functions turn on echoing while theyexecute. <P>The example code above uses the call <CODE>keypad(stdscr, TRUE)</CODE> to enablesupport for function-key mapping. With this feature, the <CODE>getch()</CODE> codewatches the input stream for character sequences that correspond to arrow andfunction keys. These sequences are returned as pseudo-character values. The<CODE>#define</CODE> values returned are listed in the <CODE>curses.h</CODE> Themapping from sequences to <CODE>#define</CODE> values is determined by<CODE>key_</CODE> capabilities in the terminal's terminfo entry.<H3><A NAME="formschars">Using Forms Characters</A></H3>The <CODE>addch()</CODE> function (and some others, including <CODE>box()</CODE> and<CODE>border()</CODE>) can accept some pseudo-character arguments which are speciallydefined by <CODE>ncurses</CODE>. These are <CODE>#define</CODE> values set up inthe <CODE>curses.h</CODE> header; see there for a complete list (look forthe prefix <CODE>ACS_</CODE>). <P>The most useful of the ACS defines are the forms-drawing characters. You canuse these to draw boxes and simple graphs on the screen. If the terminaldoes not have such characters, <CODE>curses.h</CODE> will map them to arecognizable (though ugly) set of ASCII defaults.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -