1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
5 > NCURSES Programming HOWTO </TITLE
8 CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD
24 >NCURSES Programming HOWTO</A
41 HREF="mailto:ppadala@gmail.com"
49 >v1.9, 2005-06-20<BR></P
73 >Revised by: ppadala</TD
79 >The license has been changed to the MIT-style license used
80 by NCURSES. Note that the programs are also re-licensed under this.</TD
91 >Revised by: ppadala</TD
97 >Lots of updates. Added references and perl examples.
98 Changes to examples. Many grammatical and stylistic changes to the
99 content. Changes to NCURSES history.</TD
110 >Revised by: ppadala</TD
116 >Added a README file for building and instructions
117 for building from source.</TD
128 >Revised by: ppadala</TD
134 >Added "Other formats" section and made a lot of fancy
135 changes to the programs. Inlining of programs is gone.</TD
146 >Revised by: ppadala</TD
152 >Removed the old Changelog section, cleaned the makefiles</TD
163 >Revised by: ppadala</TD
169 >Corrected a lot of spelling mistakes, added ACS variables
181 >Revised by: ppadala</TD
187 >Changed structure to present proper TOC</TD
198 >Revised by: ppadala</TD
204 >Corrected maintainers paragraph, Corrected stable release number</TD
215 >Revised by: ppadala</TD
221 >Added copyright notices to main document (LDP license)
222 and programs (GPL), Corrected
234 >Revised by: ppadala</TD
240 >Incorporated ravi's changes. Mainly to introduction, menu,
241 form, justforfun sections</TD
252 >Revised by: ppadala</TD
258 >Added "a word about window" section, Added scanw_example.</TD
275 >This document is intended to be an "All in One" guide for programming with
276 ncurses and its sister libraries. We graduate from a simple "Hello World"
277 program to more complex form manipulation. No prior experience in ncurses is
278 assumed. Send comments to <A
279 HREF="mailto:ppadala@gmail.com"
297 >Table of Contents</B
314 >What we can do with NCURSES</A
324 >Purpose/Scope of the document</A
328 HREF="#ABOUTPROGRAMS"
329 >About the Programs</A
334 >Other Formats of the document</A
341 >Readily available formats from tldp.org</A
346 >Building from source</A
376 HREF="#COMPILECURSES"
377 >Compiling With the NCURSES Library</A
388 HREF="#ABOUT-INITSCR"
394 >The mysterious refresh()</A
420 >Initialization functions</A
425 >raw() and cbreak()</A
430 >echo() and noecho()</A
445 >Miscellaneous Initialization functions</A
457 >A Word about Windows</A
469 >addch() class of functions</A
474 >mvaddch(), waddch() and mvwaddch()</A
479 >printw() class of functions</A
485 HREF="#PRINTWMVPRINTW"
486 >printw() and mvprintw</A
490 HREF="#WPRINTWMVWPRINTW"
491 >wprintw() and mvwprintw</A
500 HREF="#SIMPLEPRINTWEX"
501 >A Simple printw example</A
508 >addstr() class of functions</A
513 >A word of caution</A
527 >getch() class of functions</A
532 >scanw() class of functions</A
539 >scanw() and mvscanw</A
543 HREF="#WSCANWMVWSCANW"
544 >wscanw() and mvwscanw()</A
556 >getstr() class of functions</A
574 HREF="#ATTRIBDETAILS"
579 HREF="#ATTRONVSATTRSET"
580 >attron() vs attrset()</A
600 >chgat() functions</A
619 >Let there be a Window !!!</A
629 >The other stuff in the example</A
633 HREF="#OTHERBORDERFUNCS"
634 >Other Border functions</A
652 HREF="#CHANGECOLORDEFS"
653 >Changing Color Definitions</A
665 >Interfacing with the key board</A
677 >A Simple Key Usage example</A
684 >Interfacing with the mouse</A
695 HREF="#GETTINGEVENTS"
696 >Getting the events</A
700 HREF="#MOUSETOGETHER"
701 >Putting it all Together</A
705 HREF="#MISCMOUSEFUNCS"
706 >Miscellaneous Functions</A
713 >Screen Manipulation</A
720 >getyx() functions</A
737 >Miscellaneous features</A
749 >Temporarily Leaving Curses mode</A
777 HREF="#COMPILEPANELS"
778 >Compiling With the Panels Library</A
782 HREF="#PANELBROWSING"
783 >Panel Window Browsing</A
788 >Using User Pointers</A
792 HREF="#PANELMOVERESIZE"
793 >Moving and Resizing Panels</A
797 HREF="#PANELSHOWHIDE"
798 >Hiding and Showing Panels</A
803 >panel_above() and panel_below() Functions</A
822 >Compiling With the Menu Library</A
827 >Menu Driver: The work horse of the menu system</A
842 >Multi Columnar Menus</A
846 HREF="#MULTIVALUEMENUS"
847 >Multi Valued Menus</A
857 >The useful User Pointer</A
876 >Compiling With the Forms Library</A
881 >Playing with Fields</A
888 >Fetching Size and Location of Field</A
898 >Field Justification</A
902 HREF="#FIELDDISPATTRIB"
903 >Field Display Attributes</A
907 HREF="#FIELDOPTIONBITS"
908 >Field Option Bits</A
918 >Field User Pointer</A
922 HREF="#VARIABLESIZEFIELDS"
923 >Variable-Sized Fields</A
934 HREF="#FILEDVALIDATE"
940 >Form Driver: The work horse of the forms system</A
947 >Page Navigation Requests</A
951 HREF="#INTERFIELDNAVREQ"
952 >Inter-Field Navigation Requests</A
956 HREF="#INTRAFIELDNAVREQ"
957 >Intra-Field Navigation Requests</A
962 >Scrolling Requests</A
976 HREF="#APPLICCOMMANDS"
977 >Application Commands</A
986 >Tools and Widget Libraries</A
993 >CDK (Curses Development Kit)</A
1005 >Some Attractive Features</A
1009 HREF="#CDKCONCLUSION"
1022 >Perl Curses Modules CURSES::FORM and CURSES::WIDGETS</A
1029 >Just For Fun !!!</A
1036 >The Game of Life</A
1081 >In the olden days of teletype terminals, terminals were away from computers and
1082 were connected to them through serial cables. The terminals could be configured
1083 by sending a series of bytes. All the capabilities (such as
1084 moving the cursor to a new location, erasing part of the screen, scrolling the
1085 screen, changing modes etc.) of terminals could be accessed through these
1086 series of bytes. These control seeuqnces are usually called escape sequences,
1088 with an escape(0x1B) character. Even today, with proper emulation, we can send
1089 escape sequences to the emulator and achieve the same effect on a terminal
1092 >Suppose you wanted to print a line in color. Try typing this on your console.</P
1094 CLASS="PROGRAMLISTING"
1095 >echo "^[[0;31;40mIn Color"</PRE
1097 >The first character is an escape character, which looks like two characters ^
1098 and [. To be able to print it, you have to press CTRL+V and then the ESC key.
1099 All the others are normal printable characters. You should be able to see the
1100 string "In Color" in red. It stays that way and to revert back to the original
1103 CLASS="PROGRAMLISTING"
1104 >echo "^[[0;37;40m"</PRE
1106 >Now, what do these magic characters mean? Difficult to comprehend? They might
1107 even be different for different terminals. So the designers of UNIX invented a
1111 >. It is a file that
1112 lists all the capabilities of a particular terminal, along with the escape
1113 sequences needed to achieve a particular effect. In the later years, this was
1117 >. Without delving too
1118 much into details, this mechanism allows application
1119 programs to query the terminfo database and obtain the control characters to be
1120 sent to a terminal or terminal emulator.</P
1127 >1.1. What is NCURSES?</A
1131 You might be wondering, what the import of all this technical gibberish is. In
1132 the above scenario, every application program is supposed to query the terminfo
1133 and perform the necessary stuff (sending control characters etc.). It soon became
1134 difficult to manage this complexity and this gave birth to 'CURSES'. Curses is
1135 a pun on the name "cursor optimization". The Curses library forms a wrapper
1136 over working with raw terminal codes, and provides highly flexible and
1137 efficient API (Application Programming Interface). It provides functions to
1138 move the cursor, create windows, produce colors, play with mouse etc. The
1139 application programs need not worry about the underlying terminal capabilities.</P
1141 >So what is NCURSES? NCURSES is a clone of the original System V Release 4.0
1142 (SVr4) curses. It is a freely distributable library, fully compatible with
1143 older version of curses. In short, it is a library of functions that manages
1144 an application's display on character-cell terminals. In the remainder of the
1145 document, the terms curses and ncurses are used interchangeably. </P
1147 >A detailed history of NCURSES can be found in the NEWS file from the source
1148 distribution. The current package is maintained by
1150 HREF="mailto:dickey@his.com"
1154 You can contact the maintainers at <A
1155 HREF="mailto:bug-ncurses@gnu.org"
1157 >bug-ncurses@gnu.org</A
1166 >1.2. What we can do with NCURSES</A
1169 >NCURSES not only creates a wrapper over terminal capabilities, but also gives a
1170 robust framework to create nice looking UI (User Interface)s in text mode. It
1171 provides functions to create windows etc. Its sister libraries panel, menu and
1172 form provide an extension to the basic curses library. These libraries usually
1173 come along with curses. One can create applications that contain multiple
1174 windows, menus, panels and forms. Windows can be managed independently, can
1175 provide 'scrollability' and even can be hidden.</P
1178 Menus provide the user with an easy command selection option. Forms allow the
1179 creation of easy-to-use data entry and display windows. Panels extend the
1180 capabilities of ncurses to deal with overlapping and stacked windows.</P
1182 >These are just some of the basic things we can do with ncurses. As we move
1183 along, We will see all the capabilities of these libraries. </P
1191 >1.3. Where to get it</A
1194 >All right, now that you know what you can do with ncurses, you must be rearing
1195 to get started. NCURSES is usually shipped with your installation. In case
1196 you don't have the library or want to compile it on your own, read on.</P
1202 >Compiling the package</I
1206 >NCURSES can be obtained from <A
1207 HREF="ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz"
1209 >ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</A
1211 sites mentioned in <A
1212 HREF="http://www.gnu.org/order/ftp.html"
1214 >http://www.gnu.org/order/ftp.html</A
1217 >Read the README and INSTALL files for details on to how to install it. It
1218 usually involves the following operations.</P
1220 CLASS="PROGRAMLISTING"
1221 > tar zxvf ncurses<version>.tar.gz # unzip and untar the archive
1222 cd ncurses<version> # cd to the directory
1223 ./configure # configure the build according to your
1226 su root # become root
1227 make install # install it</PRE
1237 >NCURSES RPM can be found and downloaded from <A
1238 HREF="http://rpmfind.net"
1240 >http://rpmfind.net </A
1241 >. The RPM can be installed with the following
1242 command after becoming root.</P
1244 CLASS="PROGRAMLISTING"
1245 > rpm -i <downloaded rpm></PRE
1253 >1.4. Purpose/Scope of the document</A
1256 >This document is intended to be a "All in One" guide for programming with
1257 ncurses and its sister libraries. We graduate from a simple "Hello World"
1258 program to more complex form manipulation. No prior experience in ncurses is
1259 assumed. The writing is informal, but a lot of detail is provided for
1260 each of the examples.</P
1267 NAME="ABOUTPROGRAMS"
1268 >1.5. About the Programs</A
1271 >All the programs in the document are available in zipped form
1273 HREF="http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz"
1276 >. Unzip and untar it. The directory structure looks like this.</P
1278 CLASS="PROGRAMLISTING"
1281 |----> JustForFun -- just for fun programs
1282 |----> basics -- basic programs
1283 |----> demo -- output files go into this directory after make
1285 | |----> exe -- exe files of all example programs
1286 |----> forms -- programs related to form library
1287 |----> menus -- programs related to menus library
1288 |----> panels -- programs related to panels library
1289 |----> perl -- perl equivalents of the examples (contributed
1290 | by Anuradha Ratnaweera)
1291 |----> Makefile -- the top level Makefile
1292 |----> README -- the top level README file. contains instructions
1293 |----> COPYING -- copyright notice</PRE
1295 >The individual directories contain the following files.</P
1297 CLASS="PROGRAMLISTING"
1298 >Description of files in each directory
1299 --------------------------------------
1302 |----> hanoi.c -- The Towers of Hanoi Solver
1303 |----> life.c -- The Game of Life demo
1304 |----> magic.c -- An Odd Order Magic Square builder
1305 |----> queens.c -- The famous N-Queens Solver
1306 |----> shuffle.c -- A fun game, if you have time to kill
1307 |----> tt.c -- A very trivial typing tutor
1311 |----> acs_vars.c -- ACS_ variables example
1312 |----> hello_world.c -- Simple "Hello World" Program
1313 |----> init_func_example.c -- Initialization functions example
1314 |----> key_code.c -- Shows the scan code of the key pressed
1315 |----> mouse_menu.c -- A menu accessible by mouse
1316 |----> other_border.c -- Shows usage of other border functions apa
1318 |----> printw_example.c -- A very simple printw() example
1319 |----> scanw_example.c -- A very simple getstr() example
1320 |----> simple_attr.c -- A program that can print a c file with
1321 | -- comments in attribute
1322 |----> simple_color.c -- A simple example demonstrating colors
1323 |----> simple_key.c -- A menu accessible with keyboard UP, DOWN
1325 |----> temp_leave.c -- Demonstrates temporarily leaving curses mode
1326 |----> win_border.c -- Shows Creation of windows and borders
1327 |----> with_chgat.c -- chgat() usage example
1331 |----> form_attrib.c -- Usage of field attributes
1332 |----> form_options.c -- Usage of field options
1333 |----> form_simple.c -- A simple form example
1334 |----> form_win.c -- Demo of windows associated with forms
1338 |----> menu_attrib.c -- Usage of menu attributes
1339 |----> menu_item_data.c -- Usage of item_name() etc.. functions
1340 |----> menu_multi_column.c -- Creates multi columnar menus
1341 |----> menu_scroll.c -- Demonstrates scrolling capability of menus
1342 |----> menu_simple.c -- A simple menu accessed by arrow keys
1343 |----> menu_toggle.c -- Creates multi valued menus and explains
1344 | -- REQ_TOGGLE_ITEM
1345 |----> menu_userptr.c -- Usage of user pointer
1346 |----> menu_win.c -- Demo of windows associated with menus
1350 |----> panel_browse.c -- Panel browsing through tab. Usage of user
1352 |----> panel_hide.c -- Hiding and Un hiding of panels
1353 |----> panel_resize.c -- Moving and resizing of panels
1354 |----> panel_simple.c -- A simple panel example
1357 |----> 01-10.pl -- Perl equivalents of first ten example programs</PRE
1359 >There is a top level Makefile included in the main directory. It builds all the
1360 files and puts the ready-to-use exes in demo/exe directory. You can also
1361 do selective make by going into the corresponding directory. Each directory
1362 contains a README file explaining the purpose of each c file in the directory.</P
1364 >For every example, I have included path name for the file relative to the
1365 examples directory. </P
1367 > If you prefer browsing individual programs, point your browser to
1369 HREF="http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/"
1371 >http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</A
1374 >All the programs are released under the same license that is used by ncurses
1375 (MIT-style). This gives you the ability to do pretty much anything other than
1376 claiming them as yours. Feel free to use them in your programs as appropriate.</P
1384 >1.6. Other Formats of the document</A
1387 >This howto is also availabe in various other formats on the tldp.org site.
1388 Here are the links to other formats of this document.</P
1395 >1.6.1. Readily available formats from tldp.org</A
1403 HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf"
1405 >Acrobat PDF Format</A
1411 HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz"
1413 >PostScript Format</A
1419 HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz"
1421 >In Multiple HTML pages</A
1427 HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html"
1429 >In One big HTML format</A
1440 >1.6.2. Building from source</A
1443 >If above links are broken or if you want to experiment with sgml read on.
1445 CLASS="PROGRAMLISTING"
1446 > Get both the source and the tar,gzipped programs, available at
1447 http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
1448 NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml
1449 http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
1450 NCURSES-HOWTO/ncurses_programs.tar.gz
1452 Unzip ncurses_programs.tar.gz with
1453 tar zxvf ncurses_programs.tar.gz
1455 Use jade to create various formats. For example if you just want to create
1456 the multiple html files, you would use
1457 jade -t sgml -i html -d <path to docbook html stylesheet>
1458 NCURSES-Programming-HOWTO.sgml
1459 to get pdf, first create a single html file of the HOWTO with
1460 jade -t sgml -i html -d <path to docbook html stylesheet> -V nochunks
1461 NCURSES-Programming-HOWTO.sgml > NCURSES-ONE-BIG-FILE.html
1462 then use htmldoc to get pdf file with
1463 htmldoc --size universal -t pdf --firstpage p1 -f <output file name.pdf>
1464 NCURSES-ONE-BIG-FILE.html
1465 for ps, you would use
1466 htmldoc --size universal -t ps --firstpage p1 -f <output file name.ps>
1467 NCURSES-ONE-BIG-FILE.html</PRE
1471 HREF="http://www.tldp.org/LDP/LDP-Author-Guide/"
1473 >LDP Author guide</A
1474 > for more details. If all else failes, mail me at
1476 HREF="ppadala@gmail.com"
1478 >ppadala@gmail.com</A
1492 HREF="mailto:sharath_1@usa.net"
1495 > and Emre Akbas for
1496 helping me with few sections. The introduction was initially written by sharath.
1497 I rewrote it with few excerpts taken from his initial work. Emre helped in
1498 writing printw and scanw sections.</P
1500 >Perl equivalents of the example programs are contributed by <A
1501 HREF="mailto:Aratnaweera@virtusa.com"
1503 >Anuradha Ratnaweera</A
1507 HREF="mailto:parimi@ece.arizona.edu"
1511 dearest friend, who has been on this project before even one line was written.
1512 He constantly bombarded me with suggestions and patiently reviewed the whole
1513 text. He also checked each program on Linux and Solaris. </P
1524 >This is the wish list, in the order of priority. If you have a wish or you want
1525 to work on completing the wish, mail <A
1526 HREF="mailto:ppadala@gmail.com"
1535 >Add examples to last parts of forms section.</P
1539 >Prepare a Demo showing all the programs and allow the user to browse through
1540 description of each program. Let the user compile and see the program in action.
1541 A dialog based interface is preferred.</P
1545 >Add debug info. _tracef, _tracemouse stuff.</P
1549 >Accessing termcap, terminfo using functions provided by ncurses
1554 >Working on two terminals simultaneously.</P
1558 >Add more stuff to miscellaneous section.</P
1571 >Copyright © 2001 by Pradeep Padala. </P
1573 >Permission is hereby granted, free of charge, to any person obtaining a copy
1574 of this software and associated documentation files (the "Software"), to deal
1575 in the Software without restriction, including without limitation the rights
1576 to use, copy, modify, merge, publish, distribute, distribute with
1577 modifications, sublicense, and/or sell copies of the Software, and to permit
1578 persons to whom the Software is furnished to do so, subject to the following
1581 >The above copyright notice and this permission notice shall be included in all
1582 copies or substantial portions of the Software.</P
1584 >THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1585 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1586 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1587 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1588 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1589 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</P
1591 >Except as contained in this notice, the name(s) of the above copyright holders
1592 shall not be used in advertising or otherwise to promote the sale, use or
1593 other dealings in this Software without prior written authorization. </P
1602 >2. Hello World !!!</A
1605 >Welcome to the world of curses. Before we plunge into the library and look into
1606 its various features, let's write a simple program and say
1607 hello to the world. </P
1613 NAME="COMPILECURSES"
1614 >2.1. Compiling With the NCURSES Library</A
1617 >To use ncurses library functions, you have to include ncurses.h in your
1618 programs. To link the
1619 program with ncurses the flag -lncurses should be added.</P
1621 CLASS="PROGRAMLISTING"
1622 > #include <ncurses.h>
1627 compile and link: gcc <program file> -lncurses</PRE
1635 >Example 1. The Hello World !!! Program </B
1638 CLASS="PROGRAMLISTING"
1640 CLASS="INLINEMEDIAOBJECT"
1641 >#include <ncurses.h>
1645 initscr(); /* Start curses mode */
1646 printw("Hello World !!!"); /* Print Hello World */
1647 refresh(); /* Print it on to the real screen */
1648 getch(); /* Wait for user input */
1649 endwin(); /* End curses mode */
1666 The above program prints "Hello World !!!" to the screen and exits. This
1667 program shows how to initialize curses and do screen manipulation and
1668 end curses mode. Let's dissect it line by line. </P
1674 NAME="ABOUT-INITSCR"
1675 >2.2.1. About initscr()</A
1678 >The function initscr() initializes the terminal in curses mode. In some
1679 implementations, it clears the screen and presents a blank screen. To do any
1680 screen manipulation using curses package this has to be called first. This
1681 function initializes the curses system and allocates memory for our present
1685 >) and some other data-structures. Under extreme
1686 cases this function might fail due to insufficient memory to allocate memory
1687 for curses library's data structures. </P
1690 After this is done, we can do a variety of initializations to customize
1691 our curses settings. These details will be explained <A
1702 >2.2.2. The mysterious refresh()</A
1705 >The next line printw prints the string "Hello World !!!" on to the screen. This
1706 function is analogous to normal printf in all respects except that it prints
1707 the data on a window called stdscr at the current (y,x) co-ordinates. Since our
1708 present co-ordinates are at 0,0 the string is printed at the left hand corner
1711 >This brings us to that mysterious refresh(). Well, when we called printw
1712 the data is actually written to an imaginary window, which is not updated
1713 on the screen yet. The job of printw is to update a few flags
1714 and data structures and write the data to a buffer corresponding to stdscr.
1715 In order to show it on the screen, we need to call refresh() and tell the
1716 curses system to dump the contents on the screen.</P
1718 >The philosophy behind all this is to allow the programmer to do multiple updates
1719 on the imaginary screen or windows and do a refresh once all his screen update
1720 is done. refresh() checks the window and updates only the portion which has been
1721 changed. This improves performance and offers greater flexibility too. But, it is
1722 sometimes frustrating to beginners. A common mistake committed by beginners is
1723 to forget to call refresh() after they did some update through printw() class of
1724 functions. I still forget to add it sometimes :-) </P
1732 >2.2.3. About endwin()</A
1735 >And finally don't forget to end the curses mode. Otherwise your terminal might
1736 behave strangely after the program quits. endwin() frees the memory taken by
1737 curses sub-system and its data structures and puts the terminal in normal
1738 mode. This function must be called after you are done with the curses mode. </P
1748 >3. The Gory Details</A
1751 >Now that we have seen how to write a simple curses program let's get into the
1752 details. There are many functions that help customize what you see on screen and
1753 many features which can be put to full use. </P
1763 >4. Initialization</A
1766 >We now know that to initialize curses system the function initscr() has to be
1767 called. There are functions which can be called after this initialization to
1768 customize our curses session. We may ask the curses system to set the terminal
1769 in raw mode or initialize color or initialize the mouse etc.. Let's discuss some
1770 of the functions that are normally called immediately after initscr();</P
1777 >4.1. Initialization functions</A
1788 >4.2. raw() and cbreak()</A
1791 >Normally the terminal driver buffers the characters a user types until a new
1792 line or carriage return is encountered. But most programs require that the
1793 characters be available as soon as the user types them. The above two functions
1794 are used to disable line buffering. The difference between these two functions
1795 is in the way control characters like suspend (CTRL-Z), interrupt and quit
1796 (CTRL-C) are passed to the program. In the raw() mode these characters are
1797 directly passed to the program without generating a signal. In the
1801 > mode these control characters are
1802 interpreted as any other character by the terminal driver. I personally prefer
1803 to use raw() as I can exercise greater control over what the user does.</P
1811 >4.3. echo() and noecho()</A
1815 These functions control the echoing of characters typed by the user to the
1819 > switches off echoing. The
1820 reason you might want to do this is to gain more control over echoing or to
1821 suppress unnecessary echoing while taking input from the user through the
1822 getch() etc. functions. Most of the interactive programs call
1826 > at initialization and do the echoing
1827 of characters in a controlled manner. It gives the programmer the flexibility
1828 of echoing characters at any place in the window without updating current (y,x)
1840 >This is my favorite initialization function. It enables the reading of function
1841 keys like F1, F2, arrow keys etc. Almost every interactive program enables this,
1842 as arrow keys are a major part of any User Interface. Do
1845 >keypad(stdscr, TRUE) </TT
1846 > to enable this feature
1847 for the regular screen (stdscr). You will learn more about key management in
1848 later sections of this document.</P
1856 >4.5. halfdelay()</A
1859 >This function, though not used very often, is a useful one at times.
1860 halfdelay()is called to enable the half-delay mode, which is similar to the
1861 cbreak() mode in that characters typed are immediately available to program.
1862 However, it waits for 'X' tenths of a second for input and then returns ERR, if
1863 no input is available. 'X' is the timeout value passed to the function
1864 halfdelay(). This function is useful when you want to ask the user for input,
1865 and if he doesn't respond with in certain time, we can do some thing else. One
1866 possible example is a timeout at the password prompt. </P
1874 >4.6. Miscellaneous Initialization functions</A
1877 >There are few more functions which are called at initialization to
1878 customize curses behavior. They are not used as extensively as those mentioned
1879 above. Some of them are explained where appropriate.</P
1890 >Let's write a program which will clarify the usage of these functions.</P
1898 >Example 2. Initialization Function Usage example </B
1901 CLASS="PROGRAMLISTING"
1903 CLASS="INLINEMEDIAOBJECT"
1904 >#include <ncurses.h>
1909 initscr(); /* Start curses mode */
1910 raw(); /* Line buffering disabled */
1911 keypad(stdscr, TRUE); /* We get F1, F2 etc.. */
1912 noecho(); /* Don't echo() while we do getch */
1914 printw("Type any character to see it in bold\n");
1915 ch = getch(); /* If raw() hadn't been called
1916 * we have to press enter before it
1917 * gets to the program */
1918 if(ch == KEY_F(1)) /* Without keypad enabled this will */
1919 printw("F1 Key pressed");/* not get to us either */
1920 /* Without noecho() some ugly escape
1921 * charachters might have been printed
1924 { printw("The pressed key is ");
1929 refresh(); /* Print it on to the real screen */
1930 getch(); /* Wait for user input */
1931 endwin(); /* End curses mode */
1938 >This program is self-explanatory. But I used functions which aren't explained
1939 yet. The function <TT
1943 character from user. It is equivalent to normal
1947 > except that we can disable the line
1948 buffering to avoid <enter> after input. Look for more about
1952 >and reading keys in the <A
1954 > key management section </A
1955 >. The functions attron and attroff
1956 are used to switch some attributes on and off respectively. In the example I
1957 used them to print the character in bold. These functions are explained in detail
1967 >5. A Word about Windows</A
1971 Before we plunge into the myriad ncurses functions, let me clear few things
1972 about windows. Windows are explained in detail in following <A
1977 >A Window is an imaginary screen defined by curses system. A window does not mean
1978 a bordered window which you usually see on Win9X platforms. When curses is
1979 initialized, it creates a default window named
1983 > which represents your 80x25 (or the size
1984 of window in which you are running) screen. If you are doing simple tasks like
1985 printing few strings, reading input etc., you can safely use this single window
1986 for all of your purposes. You can also create windows and call functions which
1987 explicitly work on the specified window.</P
1989 >For example, if you call</P
1991 CLASS="PROGRAMLISTING"
1992 > printw("Hi There !!!");
1995 >It prints the string on stdscr at the present cursor position. Similarly the
1996 call to refresh(), works on stdscr only. </P
1998 >Say you have created <A
2002 call a function with a 'w' added to the usual function.</P
2004 CLASS="PROGRAMLISTING"
2005 > wprintw(win, "Hi There !!!");
2008 >As you will see in the rest of the document, naming of functions follow the
2009 same convention. For each function there usually are three more functions.</P
2011 CLASS="PROGRAMLISTING"
2012 > printw(string); /* Print on stdscr at present cursor position */
2013 mvprintw(y, x, string);/* Move to (y, x) then print string */
2014 wprintw(win, string); /* Print on window win at present cursor position */
2016 mvwprintw(win, y, x, string); /* Move to (y, x) relative to window */
2017 /* co-ordinates and then print */</PRE
2019 >Usually the w-less functions are macros which expand to corresponding w-function
2020 with stdscr as the window parameter.</P
2028 >6. Output functions</A
2031 >I guess you can't wait any more to see some action. Back to our odyssey of
2032 curses functions. Now that curses is initialized, let's interact with
2035 >There are three classes of functions which you can use to do output on screen.
2042 >addch() class: Print single character with attributes </P
2046 >printw() class: Print formatted output similar to printf()</P
2050 >addstr() class: Print strings</P
2055 >These functions can be used interchangeably and it's a matter of style as to
2056 which class is used. Let's see each one in detail.</P
2063 >6.1. addch() class of functions</A
2066 >These functions put a single character into the current cursor location and
2067 advance the position of the cursor. You can give the character to be printed but
2068 they usually are used to print a character with some attributes. Attributes are
2069 explained in detail in later <A
2073 document. If a character is associated with an attribute(bold, reverse video
2074 etc.), when curses prints the character, it is printed in that attribute.</P
2076 >In order to combine a character with some attributes, you have two options:</P
2082 >By OR'ing a single character with the desired attribute macros. These attribute
2083 macros could be found in the header file
2087 >. For example, you want to print a
2088 character ch(of type char) bold and underlined, you would call addch() as below.
2090 CLASS="PROGRAMLISTING"
2091 > addch(ch | A_BOLD | A_UNDERLINE);</PRE
2096 >By using functions like <TT
2098 >attrset(),attron(),attroff()</TT
2099 >. These functions are explained in the <A
2102 > section. Briefly, they manipulate the current attributes of
2103 the given window. Once set, the character printed in the window are associated
2104 with the attributes until it is turned off.</P
2111 > provides some special
2112 characters for character-based graphics. You can draw tables, horizontal or
2113 vertical lines, etc. You can find all avaliable characters in the header file
2117 >. Try looking for macros beginning
2129 >6.2. mvaddch(), waddch() and mvwaddch()</A
2135 > is used to move the cursor to a
2136 given point, and then print. Thus, the calls:
2138 CLASS="PROGRAMLISTING"
2139 > move(row,col); /* moves the cursor to row<SPAN
2156 CLASS="PROGRAMLISTING"
2157 > mvaddch(row,col,ch);</PRE
2167 >, except that it adds a character into
2168 the given window. (Note that <TT
2172 character into the window <TT
2177 >In a similar fashion <TT
2181 used to add a character into the given window at the given coordinates.</P
2183 >Now, we are familiar with the basic output function
2187 >. But, if we want to print a string, it
2188 would be very annoying to print it character by character. Fortunately,
2219 >6.3. printw() class of functions</A
2222 >These functions are similar to <TT
2226 the added capability of printing at any position on the screen. </P
2232 NAME="PRINTWMVPRINTW"
2233 >6.3.1. printw() and mvprintw</A
2236 >These two functions work much like <TT
2243 > can be used to move the cursor to a
2244 position and then print. If you want to move the cursor first and then print
2252 > first and then use
2256 > though I see no point why one should
2261 flexibility to manipulate. </P
2268 NAME="WPRINTWMVWPRINTW"
2269 >6.3.2. wprintw() and mvwprintw</A
2272 >These two functions are similar to above two except that they print in the
2273 corresponding window given as argument. </P
2281 >6.3.3. vwprintw()</A
2284 >This function is similar to <TT
2288 be used when variable number of arguments are to be printed.</P
2295 NAME="SIMPLEPRINTWEX"
2296 >6.3.4. A Simple printw example</A
2305 >Example 3. A Simple printw example </B
2308 CLASS="PROGRAMLISTING"
2310 CLASS="INLINEMEDIAOBJECT"
2311 >#include <ncurses.h> /* ncurses.h includes stdio.h */
2312 #include <string.h>
2316 char mesg[]="Just a string"; /* message to be appeared on the screen */
2317 int row,col; /* to store the number of rows and *
2318 * the number of colums of the screen */
2319 initscr(); /* start the curses mode */
2320 getmaxyx(stdscr,row,col); /* get the number of rows and columns */
2321 mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
2322 /* print the message at the center of the screen */
2323 mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col);
2324 printw("Try resizing your window(if possible) and then run this program again");
2334 >Above program demonstrates how easy it is to use <TT
2337 >. You just feed the coordinates and the message to be appeared
2338 on the screen, then it does what you want.</P
2340 >The above program introduces us to a new function
2344 >, a macro defined in
2348 >. It gives the number of columns and
2349 the number of rows in a given window.
2353 > does this by updating the variables
2354 given to it. Since <TT
2358 we don't pass pointers to it, we just give two integer variables. </P
2367 >6.4. addstr() class of functions</A
2373 > is used to put a character string into
2374 a given window. This function is similar to calling
2378 > once for each character in a given
2379 string. This is true for all output functions. There are other functions from
2380 this family such as <TT
2382 >mvaddstr(),mvwaddstr()</TT
2387 >, which obey the naming convention of
2388 curses.(e.g. mvaddstr() is similar to the respective calls move() and then
2389 addstr().) Another function of this family is addnstr(), which takes an integer
2390 parameter(say n) additionally. This function puts at most n characters into the
2391 screen. If n is negative, then the entire string will be added. </P
2399 >6.5. A word of caution</A
2402 >All these functions take y co-ordinate first and then x in their arguments.
2403 A common mistake by beginners is to pass x,y in that order. If you are
2404 doing too many manipulations of (y,x) co-ordinates, think of dividing the
2405 screen into windows and manipulate each one separately. Windows are explained
2418 >7. Input functions</A
2421 >Well, printing without taking input, is boring. Let's see functions which
2422 allow us to get input from user. These functions also can be divided into
2423 three categories.</P
2430 >getch() class: Get a character</P
2434 >scanw() class: Get formatted input</P
2438 >getstr() class: Get strings</P
2447 >7.1. getch() class of functions</A
2450 >These functions read a single character from the terminal. But there are several
2451 subtle facts to consider. For example if you don't use the function cbreak(),
2452 curses will not read your input characters contiguously but will begin read them
2453 only after a new line or an EOF is encountered. In order to avoid this, the
2454 cbreak() function must used so that characters are immediately available to your
2455 program. Another widely used function is noecho(). As the name suggests, when
2456 this function is set (used), the characters that are keyed in by the user will
2457 not show up on the screen. The two functions cbreak() and noecho() are typical
2458 examples of key management. Functions of this genre are explained in the
2461 >key management section </A
2470 >7.2. scanw() class of functions</A
2473 >These functions are similar to <TT
2477 added capability of getting the input from any location on the screen.</P
2484 >7.2.1. scanw() and mvscanw</A
2487 >The usage of these functions is similar to that of
2491 >, where the line to be scanned is
2495 > function. That is, these
2496 functions call to <TT
2499 > function(explained
2500 below) and uses the resulting line for a scan. </P
2507 NAME="WSCANWMVWSCANW"
2508 >7.2.2. wscanw() and mvwscanw()</A
2511 >These are similar to above two functions except that they read from a window,
2512 which is supplied as one of the arguments to these functions. </P
2520 >7.2.3. vwscanw()</A
2523 >This function is similar to <TT
2527 be used when a variable number of arguments are to be scanned.</P
2536 >7.3. getstr() class of functions</A
2539 >These functions are used to get strings from the terminal. In essence, this
2540 function performs the same task as would be achieved by a series of calls to
2544 > until a newline, carriage return, or
2545 end-of-file is received. The resulting string of characters are pointed to by
2549 >, which is a character pointer provided by
2558 >7.4. Some examples</A
2567 >Example 4. A Simple scanw example </B
2570 CLASS="PROGRAMLISTING"
2572 CLASS="INLINEMEDIAOBJECT"
2573 >#include <ncurses.h> /* ncurses.h includes stdio.h */
2574 #include <string.h>
2578 char mesg[]="Enter a string: "; /* message to be appeared on the screen */
2580 int row,col; /* to store the number of rows and *
2581 * the number of colums of the screen */
2582 initscr(); /* start the curses mode */
2583 getmaxyx(stdscr,row,col); /* get the number of rows and columns */
2584 mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
2585 /* print the message at the center of the screen */
2587 mvprintw(LINES - 2, 0, "You Entered: %s", str);
2606 >We have seen an example of how attributes can be used to print characters with
2607 some special effects. Attributes, when set prudently, can present information in
2608 an easy, understandable manner. The following program takes a C file as input
2609 and prints the file with comments in bold. Scan through the code. </P
2617 >Example 5. A Simple Attributes example </B
2620 CLASS="PROGRAMLISTING"
2622 CLASS="INLINEMEDIAOBJECT"
2623 >/* pager functionality by Joseph Spainhour" <spainhou@bellsouth.net> */
2624 #include <ncurses.h>
2625 #include <stdlib.h>
2627 int main(int argc, char *argv[])
2629 int ch, prev, row, col;
2636 printf("Usage: %s <a c file name>\n", argv[0]);
2639 fp = fopen(argv[1], "r");
2642 perror("Cannot open input file");
2645 initscr(); /* Start curses mode */
2646 getmaxyx(stdscr, row, col); /* find the boundaries of the screeen */
2647 while((ch = fgetc(fp)) != EOF) /* read the file till we reach the end */
2649 getyx(stdscr, y, x); /* get the current curser position */
2650 if(y == (row - 1)) /* are we are at the end of the screen */
2652 printw("<-Press Any Key->"); /* tell the user to press a key */
2654 clear(); /* clear the screen */
2655 move(0, 0); /* start at the beginning of the screen */
2657 if(prev == '/' && ch == '*') /* If it is / and * then only
2660 attron(A_BOLD); /* cut bold on */
2661 getyx(stdscr, y, x); /* get the current curser position */
2662 move(y, x - 1); /* back up one space */
2663 printw("%c%c", '/', ch); /* The actual printing is done here */
2668 if(prev == '*' && ch == '/')
2669 attroff(A_BOLD); /* Switch it off once we got *
2673 endwin(); /* End curses mode */
2681 Don't worry about all those initialization and other crap. Concentrate on
2682 the while loop. It reads each character in the file and searches for the
2683 pattern /*. Once it spots the pattern, it switches the BOLD attribute on with
2687 > . When we get the pattern */ it is
2694 The above program also introduces us to two useful functions
2702 >. The first function gets the
2703 co-ordinates of the present cursor into the variables y, x. Since getyx() is a
2704 macro we don't have to pass pointers to variables. The function
2708 > moves the cursor to the co-ordinates
2712 The above program is really a simple one which doesn't do much. On these lines
2713 one could write a more useful program which reads a C file, parses it and prints
2714 it in different colors. One could even extend it to other languages as well.</P
2720 NAME="ATTRIBDETAILS"
2721 >8.1. The details</A
2724 >Let's get into more details of attributes. The functions <TT
2726 >attron(), attroff(), attrset() </TT
2727 >, and their sister functions
2731 > etc.. can be used to switch
2732 attributes on/off , get attributes and produce a colorful display.</P
2734 >The functions attron and attroff take a bit-mask of attributes and switch them
2735 on or off, respectively. The following video attributes, which are defined in
2736 <curses.h> can be passed to these functions. </P
2738 CLASS="PROGRAMLISTING"
2740 A_NORMAL Normal display (no highlight)
2741 A_STANDOUT Best highlighting mode of the terminal.
2742 A_UNDERLINE Underlining
2743 A_REVERSE Reverse video
2746 A_BOLD Extra bright or bold
2747 A_PROTECT Protected mode
2748 A_INVIS Invisible or blank mode
2749 A_ALTCHARSET Alternate character set
2750 A_CHARTEXT Bit-mask to extract a character
2751 COLOR_PAIR(n) Color-pair number n
2755 The last one is the most colorful one :-) Colors are explained in the
2762 >We can OR(|) any number of above attributes to get a combined effect. If you
2763 wanted reverse video with blinking characters you can use</P
2765 CLASS="PROGRAMLISTING"
2766 > attron(A_REVERSE | A_BLINK);</PRE
2773 NAME="ATTRONVSATTRSET"
2774 >8.2. attron() vs attrset()</A
2777 >Then what is the difference between attron() and attrset()? attrset sets the
2778 attributes of window whereas attron just switches on the attribute given to it.
2779 So attrset() fully overrides whatever attributes the window previously had and
2780 sets it to the new attribute(s). Similarly attroff() just switches off the
2781 attribute(s) given to it as an argument. This gives us the flexibility of
2782 managing attributes easily.But if you use them carelessly you may loose track of
2783 what attributes the window has and garble the display. This is especially true
2784 while managing menus with colors and highlighting. So decide on a consistent
2785 policy and stick to it. You can always use <TT
2788 > which is equivalent to <TT
2790 > attrset(A_NORMAL)</TT
2791 > which turns off all attributes and brings you to normal mode.</P
2802 > The function attr_get() gets the current attributes and color pair of the
2803 window. Though we might not use this as often as the above functions, this is
2804 useful in scanning areas of screen. Say we wanted to do some complex update on
2805 screen and we are not sure what attribute each character is associated with.
2806 Then this function can be used with either attrset or attron to produce the
2807 desired effect. </P
2815 >8.4. attr_ functions</A
2818 >There are series of functions like attr_set(), attr_on etc.. These are similar
2819 to above functions except that they take parameters of type
2831 >8.5. wattr functions</A
2834 >For each of the above functions we have a corresponding function with 'w' which
2835 operates on a particular window. The above functions operate on stdscr. </P
2843 >8.6. chgat() functions</A
2846 >The function chgat() is listed in the end of the man page curs_attr. It actually
2847 is a useful one. This function can be used to set attributes for a group of
2848 characters without moving. I mean it !!! without moving the cursor :-) It
2849 changes the attributes of a given number of characters starting at the current
2852 >We can give -1 as the character count to update till end of line. If you want to
2853 change attributes of characters from current position to end of line, just use
2856 CLASS="PROGRAMLISTING"
2857 > chgat(-1, A_REVERSE, 0, NULL);</PRE
2860 This function is useful when changing attributes for characters that are
2861 already on the screen. Move to the character from which you want to change and
2862 change the attribute. </P
2864 >Other functions wchgat(), mvchgat(), wchgat() behave similarly except that the w
2865 functions operate on the particular window. The mv functions first move the
2866 cursor then perform the work given to them. Actually chgat is a macro which is
2867 replaced by a wchgat() with stdscr as the window. Most of the "w-less" functions
2876 >Example 6. Chgat() Usage example </B
2879 CLASS="PROGRAMLISTING"
2881 CLASS="INLINEMEDIAOBJECT"
2882 >#include <ncurses.h>
2884 int main(int argc, char *argv[])
2885 { initscr(); /* Start curses mode */
2886 start_color(); /* Start color functionality */
2888 init_pair(1, COLOR_CYAN, COLOR_BLACK);
2889 printw("A Big string which i didn't care to type fully ");
2890 mvchgat(0, 0, -1, A_BLINK, 1, NULL);
2892 * First two parameters specify the position at which to start
2893 * Third parameter number of characters to update. -1 means till
2895 * Forth parameter is the normal attribute you wanted to give
2897 * Fifth is the color index. It is the index given during init_pair()
2898 * use 0 if you didn't want color
2899 * Sixth one is always NULL
2903 endwin(); /* End curses mode */
2909 >This example also introduces us to the color world of curses. Colors will be
2910 explained in detail later. Use 0 for no color.</P
2922 >Windows form the most important concept in curses. You have seen the standard
2923 window stdscr above where all the functions implicitly operated on this window.
2924 Now to make design even a simplest GUI, you need to resort to windows. The main
2925 reason you may want to use windows is to manipulate parts of the screen
2926 separately, for better efficiency, by updating only the windows that need to be
2927 changed and for a better design. I would say the last reason is the most
2928 important in going for windows. You should always strive for a better and
2929 easy-to-manage design in your programs. If you are writing big, complex GUIs
2930 this is of pivotal importance before you start doing anything.</P
2940 >A Window can be created by calling the function
2944 >. It doesn't create any thing on the
2945 screen actually. It allocates memory for a structure to manipulate the window
2946 and updates the structure with data regarding the window like it's size, beginy,
2947 beginx etc.. Hence in curses, a window is just an abstraction of an imaginary
2948 window, which can be manipulated independent of other parts of screen. The
2949 function newwin() returns a pointer to structure WINDOW, which can be passed to
2950 window related functions like wprintw() etc.. Finally the window can be
2951 destroyed with delwin(). It will deallocate the memory associated with the
2952 window structure.</P
2960 >9.2. Let there be a Window !!!</A
2963 >What fun is it, if a window is created and we can't see it. So the fun part
2964 begins by displaying the window. The function
2968 > can be used to draw a border around the
2969 window. Let's explore these functions in more detail in this example.</P
2977 >Example 7. Window Border example </B
2980 CLASS="PROGRAMLISTING"
2982 CLASS="INLINEMEDIAOBJECT"
2983 >#include <ncurses.h>
2986 WINDOW *create_newwin(int height, int width, int starty, int startx);
2987 void destroy_win(WINDOW *local_win);
2989 int main(int argc, char *argv[])
2991 int startx, starty, width, height;
2994 initscr(); /* Start curses mode */
2995 cbreak(); /* Line buffering disabled, Pass on
2996 * everty thing to me */
2997 keypad(stdscr, TRUE); /* I need that nifty F1 */
3001 starty = (LINES - height) / 2; /* Calculating for a center placement */
3002 startx = (COLS - width) / 2; /* of the window */
3003 printw("Press F1 to exit");
3005 my_win = create_newwin(height, width, starty, startx);
3007 while((ch = getch()) != KEY_F(1))
3010 destroy_win(my_win);
3011 my_win = create_newwin(height, width, starty,--startx);
3014 destroy_win(my_win);
3015 my_win = create_newwin(height, width, starty,++startx);
3018 destroy_win(my_win);
3019 my_win = create_newwin(height, width, --starty,startx);
3022 destroy_win(my_win);
3023 my_win = create_newwin(height, width, ++starty,startx);
3028 endwin(); /* End curses mode */
3032 WINDOW *create_newwin(int height, int width, int starty, int startx)
3033 { WINDOW *local_win;
3035 local_win = newwin(height, width, starty, startx);
3036 box(local_win, 0 , 0); /* 0, 0 gives default characters
3037 * for the vertical and horizontal
3039 wrefresh(local_win); /* Show that box */
3044 void destroy_win(WINDOW *local_win)
3046 /* box(local_win, ' ', ' '); : This won't produce the desired
3047 * result of erasing the window. It will leave it's four corners
3048 * and so an ugly remnant of window.
3050 wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
3051 /* The parameters taken are
3052 * 1. win: the window on which to operate
3053 * 2. ls: character to be used for the left side of the window
3054 * 3. rs: character to be used for the right side of the window
3055 * 4. ts: character to be used for the top side of the window
3056 * 5. bs: character to be used for the bottom side of the window
3057 * 6. tl: character to be used for the top left corner of the window
3058 * 7. tr: character to be used for the top right corner of the window
3059 * 8. bl: character to be used for the bottom left corner of the window
3060 * 9. br: character to be used for the bottom right corner of the window
3062 wrefresh(local_win);
3074 >9.3. Explanation</A
3077 >Don't scream. I know it's a big example. But I have to explain some important
3078 things here :-). This program creates a rectangular window that can be moved
3079 with left, right, up, down arrow keys. It repeatedly creates and destroys
3080 windows as user press a key. Don't go beyond the screen limits. Checking for
3081 those limits is left as an exercise for the reader. Let's dissect it by line by line.</P
3085 >create_newwin()</TT
3086 > function creates a window
3090 > and displays a border around it
3091 with box. The function <TT
3095 erases the window from screen by painting a border with ' ' character and then
3099 > to deallocate memory related
3100 to it. Depending on the key the user presses, starty or startx is changed and a
3101 new window is created.</P
3103 >In the destroy_win, as you can see, I used wborder instead of box. The reason is
3104 written in the comments (You missed it. I know. Read the code :-)). wborder
3105 draws a border around the window with the characters given to it as the 4 corner
3106 points and the 4 lines. To put it clearly, if you have called wborder as below:
3108 CLASS="PROGRAMLISTING"
3109 > wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');</PRE
3112 >it produces some thing like </P
3114 CLASS="PROGRAMLISTING"
3130 >9.4. The other stuff in the example</A
3133 >You can also see in the above examples, that I have used the variables COLS,
3134 LINES which are initialized to the screen sizes after initscr(). They can be
3135 useful in finding screen dimensions and finding the center co-ordinate of the
3136 screen as above. The function <TT
3140 gets the key from keyboard and according to the key it does the corresponding
3141 work. This type of switch- case is very common in any GUI based programs.</P
3148 NAME="OTHERBORDERFUNCS"
3149 >9.5. Other Border functions</A
3152 >Above program is grossly inefficient in that with each press of a key, a window
3153 is destroyed and another is created. So let's write a more efficient program
3154 which uses other border related functions.</P
3156 >The following program uses <TT
3163 > to achieve similar effect. These two
3164 functions are simple. They create a horizontal or vertical line of the specified
3165 length at the specified position.</P
3173 >Example 8. More border functions</B
3176 CLASS="PROGRAMLISTING"
3178 CLASS="INLINEMEDIAOBJECT"
3179 >#include <ncurses.h>
3181 typedef struct _win_border_struct {
3182 chtype ls, rs, ts, bs,
3186 typedef struct _WIN_struct {
3193 void init_win_params(WIN *p_win);
3194 void print_win_params(WIN *p_win);
3195 void create_box(WIN *win, bool flag);
3197 int main(int argc, char *argv[])
3201 initscr(); /* Start curses mode */
3202 start_color(); /* Start the color functionality */
3203 cbreak(); /* Line buffering disabled, Pass on
3204 * everty thing to me */
3205 keypad(stdscr, TRUE); /* I need that nifty F1 */
3207 init_pair(1, COLOR_CYAN, COLOR_BLACK);
3209 /* Initialize the window parameters */
3210 init_win_params(&win);
3211 print_win_params(&win);
3213 attron(COLOR_PAIR(1));
3214 printw("Press F1 to exit");
3216 attroff(COLOR_PAIR(1));
3218 create_box(&win, TRUE);
3219 while((ch = getch()) != KEY_F(1))
3222 create_box(&win, FALSE);
3224 create_box(&win, TRUE);
3227 create_box(&win, FALSE);
3229 create_box(&win, TRUE);
3232 create_box(&win, FALSE);
3234 create_box(&win, TRUE);
3237 create_box(&win, FALSE);
3239 create_box(&win, TRUE);
3243 endwin(); /* End curses mode */
3246 void init_win_params(WIN *p_win)
3248 p_win->height = 3;
3249 p_win->width = 10;
3250 p_win->starty = (LINES - p_win->height)/2;
3251 p_win->startx = (COLS - p_win->width)/2;
3253 p_win->border.ls = '|';
3254 p_win->border.rs = '|';
3255 p_win->border.ts = '-';
3256 p_win->border.bs = '-';
3257 p_win->border.tl = '+';
3258 p_win->border.tr = '+';
3259 p_win->border.bl = '+';
3260 p_win->border.br = '+';
3263 void print_win_params(WIN *p_win)
3266 mvprintw(25, 0, "%d %d %d %d", p_win->startx, p_win->starty,
3267 p_win->width, p_win->height);
3271 void create_box(WIN *p_win, bool flag)
3275 x = p_win->startx;
3276 y = p_win->starty;
3277 w = p_win->width;
3278 h = p_win->height;
3281 { mvaddch(y, x, p_win->border.tl);
3282 mvaddch(y, x + w, p_win->border.tr);
3283 mvaddch(y + h, x, p_win->border.bl);
3284 mvaddch(y + h, x + w, p_win->border.br);
3285 mvhline(y, x + 1, p_win->border.ts, w - 1);
3286 mvhline(y + h, x + 1, p_win->border.bs, w - 1);
3287 mvvline(y + 1, x, p_win->border.ls, h - 1);
3288 mvvline(y + 1, x + w, p_win->border.rs, h - 1);
3292 for(j = y; j <= y + h; ++j)
3293 for(i = x; i <= x + w; ++i)
3317 >10.1. The basics</A
3320 >Life seems dull with no colors. Curses has a nice mechanism to handle colors.
3321 Let's get into the thick of the things with a small program.</P
3329 >Example 9. A Simple Color example </B
3332 CLASS="PROGRAMLISTING"
3334 CLASS="INLINEMEDIAOBJECT"
3335 >#include <ncurses.h>
3337 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
3338 int main(int argc, char *argv[])
3339 { initscr(); /* Start curses mode */
3340 if(has_colors() == FALSE)
3342 printf("Your terminal does not support color\n");
3345 start_color(); /* Start color */
3346 init_pair(1, COLOR_RED, COLOR_BLACK);
3348 attron(COLOR_PAIR(1));
3349 print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ...");
3350 attroff(COLOR_PAIR(1));
3354 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string)
3368 length = strlen(string);
3369 temp = (width - length)/ 2;
3370 x = startx + (int)temp;
3371 mvwprintw(win, y, x, "%s", string);
3378 >As you can see, to start using color, you should first call the function
3382 >. After that, you can use color
3383 capabilities of your terminals using various functions. To find out whether a
3384 terminal has color capabilities or not, you can use
3388 > function, which returns FALSE if
3389 the terminal does not support color. </P
3391 >Curses initializes all the colors supported by terminal when start_color() is
3392 called. These can be accessed by the define constants like
3396 > etc. Now to actually start using
3397 colors, you have to define pairs. Colors are always used in pairs. That means
3398 you have to use the function <TT
3402 define the foreground and background for the pair number you give. After that
3403 that pair number can be used as a normal attribute with <TT
3406 >function. This may seem to be cumbersome at first.
3407 But this elegant solution allows us to manage color pairs very easily. To
3408 appreciate it, you have to look into the the source code of "dialog", a utility
3409 for displaying dialog boxes from shell scripts. The developers have defined
3410 foreground and background combinations for all the colors they might need and
3411 initialized at the beginning. This makes it very easy to set attributes just by
3412 accessing a pair which we already have defined as a constant.</P
3414 >The following colors are defined in <TT
3418 You can use these as parameters for various color functions.
3420 CLASS="PROGRAMLISTING"
3436 NAME="CHANGECOLORDEFS"
3437 >10.2. Changing Color Definitions</A
3443 >can be used to change
3444 the rgb values for the colors defined by curses initially. Say you wanted to
3445 lighten the intensity of red color by a minuscule. Then you can use this
3448 CLASS="PROGRAMLISTING"
3449 > init_color(COLOR_RED, 700, 0, 0);
3450 /* param 1 : color name
3451 * param 2, 3, 4 : rgb content min = 0, max = 1000 */</PRE
3453 >If your terminal cannot change the color definitions, the function returns ERR.
3456 >can_change_color()</TT
3458 find out whether the terminal has the capability of changing color content or
3459 not. The rgb content is scaled from 0 to 1000. Initially RED color is defined
3460 with content 1000(r), 0(g), 0(b). </P
3468 >10.3. Color Content</A
3473 >color_content()</TT
3478 > can be used to find the color
3479 content and foreground, background combination for the pair. </P
3488 >11. Interfacing with the key board</A
3496 >11.1. The Basics</A
3499 >No GUI is complete without a strong user interface and to interact with the
3500 user, a curses program should be sensitive to key presses or the mouse actions
3501 done by the user. Let's deal with the keys first.</P
3503 >As you have seen in almost all of the above examples, it's very easy to get key
3504 input from the user. A simple way of getting key presses is to use
3508 > function. The cbreak mode should be
3509 enabled to read keys when you are interested in reading individual key hits
3510 rather than complete lines of text (which usually end with a carriage return).
3511 keypad should be enabled to get the Functions keys, arrow keys etc. See the
3512 initialization section for details.</P
3517 > returns an integer corresponding to the
3518 key pressed. If it is a normal character, the integer value will be equivalent
3519 to the character. Otherwise it returns a number which can be matched with the
3520 constants defined in <TT
3524 the user presses F1, the integer returned is 265. This can be checked using the
3525 macro KEY_F() defined in curses.h. This makes reading keys portable and easy to
3528 >For example, if you call getch() like this</P
3530 CLASS="PROGRAMLISTING"
3535 >getch() will wait for the user to press a key, (unless you specified a timeout)
3536 and when user presses a key, the corresponding integer is returned. Then you can
3537 check the value returned with the constants defined in curses.h to match against
3538 the keys you want.</P
3540 >The following code piece will do that job.</P
3542 CLASS="PROGRAMLISTING"
3543 > if(ch == KEY_LEFT)
3544 printw("Left arrow is pressed\n");</PRE
3546 >Let's write a small program which creates a menu which can be navigated by up
3555 >11.2. A Simple Key Usage example</A
3564 >Example 10. A Simple Key Usage example </B
3567 CLASS="PROGRAMLISTING"
3569 CLASS="INLINEMEDIAOBJECT"
3570 >#include <stdio.h>
3571 #include <ncurses.h>
3586 int n_choices = sizeof(choices) / sizeof(char *);
3587 void print_menu(WINDOW *menu_win, int highlight);
3598 cbreak(); /* Line buffering disabled. pass on everything */
3599 startx = (80 - WIDTH) / 2;
3600 starty = (24 - HEIGHT) / 2;
3602 menu_win = newwin(HEIGHT, WIDTH, starty, startx);
3603 keypad(menu_win, TRUE);
3604 mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
3606 print_menu(menu_win, highlight);
3608 { c = wgetch(menu_win);
3612 highlight = n_choices;
3617 if(highlight == n_choices)
3626 mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
3630 print_menu(menu_win, highlight);
3631 if(choice != 0) /* User did a choice come out of the infinite loop */
3634 mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]);
3642 void print_menu(WINDOW *menu_win, int highlight)
3648 box(menu_win, 0, 0);
3649 for(i = 0; i < n_choices; ++i)
3650 { if(highlight == i + 1) /* High light the present choice */
3651 { wattron(menu_win, A_REVERSE);
3652 mvwprintw(menu_win, y, x, "%s", choices[i]);
3653 wattroff(menu_win, A_REVERSE);
3656 mvwprintw(menu_win, y, x, "%s", choices[i]);
3672 >12. Interfacing with the mouse</A
3675 >Now that you have seen how to get keys, lets do the same thing from mouse.
3676 Usually each UI allows the user to interact with both keyboard and mouse. </P
3683 >12.1. The Basics</A
3686 >Before you do any thing else, the events you want to receive have to be enabled
3692 CLASS="PROGRAMLISTING"
3693 > mousemask( mmask_t newmask, /* The events you want to listen to */
3694 mmask_t *oldmask) /* The old events mask */</PRE
3696 >The first parameter to above function is a bit mask of events you would like to
3697 listen. By default, all the events are turned off. The bit mask <TT
3699 > ALL_MOUSE_EVENTS</TT
3700 > can be used to get all the events.</P
3702 >The following are all the event masks:</P
3704 CLASS="PROGRAMLISTING"
3706 ---------------------------------------------------------------------
3707 BUTTON1_PRESSED mouse button 1 down
3708 BUTTON1_RELEASED mouse button 1 up
3709 BUTTON1_CLICKED mouse button 1 clicked
3710 BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
3711 BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
3712 BUTTON2_PRESSED mouse button 2 down
3713 BUTTON2_RELEASED mouse button 2 up
3714 BUTTON2_CLICKED mouse button 2 clicked
3715 BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
3716 BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
3717 BUTTON3_PRESSED mouse button 3 down
3718 BUTTON3_RELEASED mouse button 3 up
3719 BUTTON3_CLICKED mouse button 3 clicked
3720 BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
3721 BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
3722 BUTTON4_PRESSED mouse button 4 down
3723 BUTTON4_RELEASED mouse button 4 up
3724 BUTTON4_CLICKED mouse button 4 clicked
3725 BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
3726 BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
3727 BUTTON_SHIFT shift was down during button state change
3728 BUTTON_CTRL control was down during button state change
3729 BUTTON_ALT alt was down during button state change
3730 ALL_MOUSE_EVENTS report all button state changes
3731 REPORT_MOUSE_POSITION report mouse movement</PRE
3738 NAME="GETTINGEVENTS"
3739 >12.2. Getting the events</A
3742 >Once a class of mouse events have been enabled, getch() class of functions
3743 return KEY_MOUSE every time some mouse event happens. Then the mouse event can
3744 be retrieved with <TT
3749 >The code approximately looks like this:</P
3751 CLASS="PROGRAMLISTING"
3756 if(getmouse(&event) == OK)
3757 . /* Do some thing with the event */