| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> |
| <HTML |
| ><HEAD |
| ><TITLE |
| > NCURSES Programming HOWTO </TITLE |
| ><META |
| NAME="GENERATOR" |
| CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD |
| ><BODY |
| CLASS="ARTICLE" |
| BGCOLOR="#FFFFFF" |
| TEXT="#000000" |
| LINK="#0000FF" |
| VLINK="#840084" |
| ALINK="#0000FF" |
| ><DIV |
| CLASS="ARTICLE" |
| ><DIV |
| CLASS="TITLEPAGE" |
| ><H1 |
| CLASS="TITLE" |
| ><A |
| NAME="AEN2" |
| >NCURSES Programming HOWTO</A |
| ></H1 |
| ><H3 |
| CLASS="AUTHOR" |
| ><A |
| NAME="AEN4" |
| > Pradeep Padala </A |
| ></H3 |
| ><DIV |
| CLASS="AFFILIATION" |
| ><DIV |
| CLASS="ADDRESS" |
| ><P |
| CLASS="ADDRESS" |
| ><CODE |
| CLASS="EMAIL" |
| ><<A |
| HREF="mailto:ppadala@gmail.com" |
| >ppadala@gmail.com</A |
| >></CODE |
| ></P |
| ></DIV |
| ></DIV |
| ><P |
| CLASS="PUBDATE" |
| >v1.9, 2005-06-20<BR></P |
| ><DIV |
| CLASS="REVHISTORY" |
| ><TABLE |
| WIDTH="100%" |
| BORDER="0" |
| ><TR |
| ><TH |
| ALIGN="LEFT" |
| VALIGN="TOP" |
| COLSPAN="3" |
| ><B |
| >Revision History</B |
| ></TH |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.9</TD |
| ><TD |
| ALIGN="LEFT" |
| >2005-06-20</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >The license has been changed to the MIT-style license used |
| by NCURSES. Note that the programs are also re-licensed under this.</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.8</TD |
| ><TD |
| ALIGN="LEFT" |
| >2005-06-17</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Lots of updates. Added references and perl examples. |
| Changes to examples. Many grammatical and stylistic changes to the |
| content. Changes to NCURSES history.</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.7.1</TD |
| ><TD |
| ALIGN="LEFT" |
| >2002-06-25</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Added a README file for building and instructions |
| for building from source.</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.7</TD |
| ><TD |
| ALIGN="LEFT" |
| >2002-06-25</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Added "Other formats" section and made a lot of fancy |
| changes to the programs. Inlining of programs is gone.</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.6.1</TD |
| ><TD |
| ALIGN="LEFT" |
| >2002-02-24</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Removed the old Changelog section, cleaned the makefiles</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.6</TD |
| ><TD |
| ALIGN="LEFT" |
| >2002-02-16</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Corrected a lot of spelling mistakes, added ACS variables |
| section</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.5</TD |
| ><TD |
| ALIGN="LEFT" |
| >2002-01-05</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Changed structure to present proper TOC</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.3.1</TD |
| ><TD |
| ALIGN="LEFT" |
| >2001-07-26</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Corrected maintainers paragraph, Corrected stable release number</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.3</TD |
| ><TD |
| ALIGN="LEFT" |
| >2001-07-24</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Added copyright notices to main document (LDP license) |
| and programs (GPL), Corrected |
| printw_example.</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.2</TD |
| ><TD |
| ALIGN="LEFT" |
| >2001-06-05</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Incorporated ravi's changes. Mainly to introduction, menu, |
| form, justforfun sections</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| >Revision 1.1</TD |
| ><TD |
| ALIGN="LEFT" |
| >2001-05-22</TD |
| ><TD |
| ALIGN="LEFT" |
| >Revised by: ppadala</TD |
| ></TR |
| ><TR |
| ><TD |
| ALIGN="LEFT" |
| COLSPAN="3" |
| >Added "a word about window" section, Added scanw_example.</TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ><DIV |
| ><DIV |
| CLASS="ABSTRACT" |
| ><P |
| ></P |
| ><A |
| NAME="AEN67" |
| ></A |
| ><P |
| > <SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >This document is intended to be an "All in One" guide for programming with |
| ncurses and its sister libraries. We graduate from a simple "Hello World" |
| program to more complex form manipulation. No prior experience in ncurses is |
| assumed. Send comments to <A |
| HREF="mailto:ppadala@gmail.com" |
| TARGET="_top" |
| >this address</A |
| > |
| </I |
| ></SPAN |
| > |
| </P |
| ><P |
| ></P |
| ></DIV |
| ></DIV |
| ><HR></DIV |
| ><DIV |
| CLASS="TOC" |
| ><DL |
| ><DT |
| ><B |
| >Table of Contents</B |
| ></DT |
| ><DT |
| >1. <A |
| HREF="#INTRO" |
| >Introduction</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >1.1. <A |
| HREF="#WHATIS" |
| >What is NCURSES?</A |
| ></DT |
| ><DT |
| >1.2. <A |
| HREF="#WHATCANWEDO" |
| >What we can do with NCURSES</A |
| ></DT |
| ><DT |
| >1.3. <A |
| HREF="#WHERETOGETIT" |
| >Where to get it</A |
| ></DT |
| ><DT |
| >1.4. <A |
| HREF="#PURPOSE" |
| >Purpose/Scope of the document</A |
| ></DT |
| ><DT |
| >1.5. <A |
| HREF="#ABOUTPROGRAMS" |
| >About the Programs</A |
| ></DT |
| ><DT |
| >1.6. <A |
| HREF="#OTHERFORMATS" |
| >Other Formats of the document</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >1.6.1. <A |
| HREF="#LISTFORMATS" |
| >Readily available formats from tldp.org</A |
| ></DT |
| ><DT |
| >1.6.2. <A |
| HREF="#BUILDSOURCE" |
| >Building from source</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >1.7. <A |
| HREF="#CREDITS" |
| >Credits</A |
| ></DT |
| ><DT |
| >1.8. <A |
| HREF="#WISHLIST" |
| >Wish List</A |
| ></DT |
| ><DT |
| >1.9. <A |
| HREF="#COPYRIGHT" |
| >Copyright</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >2. <A |
| HREF="#HELLOWORLD" |
| >Hello World !!!</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >2.1. <A |
| HREF="#COMPILECURSES" |
| >Compiling With the NCURSES Library</A |
| ></DT |
| ><DT |
| >2.2. <A |
| HREF="#DISSECTION" |
| >Dissection</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >2.2.1. <A |
| HREF="#ABOUT-INITSCR" |
| >About initscr()</A |
| ></DT |
| ><DT |
| >2.2.2. <A |
| HREF="#MYST-REFRESH" |
| >The mysterious refresh()</A |
| ></DT |
| ><DT |
| >2.2.3. <A |
| HREF="#ABOUT-ENDWIN" |
| >About endwin()</A |
| ></DT |
| ></DL |
| ></DD |
| ></DL |
| ></DD |
| ><DT |
| >3. <A |
| HREF="#GORY" |
| >The Gory Details</A |
| ></DT |
| ><DT |
| >4. <A |
| HREF="#INIT" |
| >Initialization</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >4.1. <A |
| HREF="#ABOUTINIT" |
| >Initialization functions</A |
| ></DT |
| ><DT |
| >4.2. <A |
| HREF="#RAWCBREAK" |
| >raw() and cbreak()</A |
| ></DT |
| ><DT |
| >4.3. <A |
| HREF="#ECHONOECHO" |
| >echo() and noecho()</A |
| ></DT |
| ><DT |
| >4.4. <A |
| HREF="#KEYPAD" |
| >keypad()</A |
| ></DT |
| ><DT |
| >4.5. <A |
| HREF="#HALFDELAY" |
| >halfdelay()</A |
| ></DT |
| ><DT |
| >4.6. <A |
| HREF="#MISCINIT" |
| >Miscellaneous Initialization functions</A |
| ></DT |
| ><DT |
| >4.7. <A |
| HREF="#INITEX" |
| >An Example</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >5. <A |
| HREF="#AWORDWINDOWS" |
| >A Word about Windows</A |
| ></DT |
| ><DT |
| >6. <A |
| HREF="#PRINTW" |
| >Output functions</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >6.1. <A |
| HREF="#ADDCHCLASS" |
| >addch() class of functions</A |
| ></DT |
| ><DT |
| >6.2. <A |
| HREF="#AEN298" |
| >mvaddch(), waddch() and mvwaddch()</A |
| ></DT |
| ><DT |
| >6.3. <A |
| HREF="#PRINTWCLASS" |
| >printw() class of functions</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >6.3.1. <A |
| HREF="#PRINTWMVPRINTW" |
| >printw() and mvprintw</A |
| ></DT |
| ><DT |
| >6.3.2. <A |
| HREF="#WPRINTWMVWPRINTW" |
| >wprintw() and mvwprintw</A |
| ></DT |
| ><DT |
| >6.3.3. <A |
| HREF="#VWPRINTW" |
| >vwprintw()</A |
| ></DT |
| ><DT |
| >6.3.4. <A |
| HREF="#SIMPLEPRINTWEX" |
| >A Simple printw example</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >6.4. <A |
| HREF="#ADDSTRCLASS" |
| >addstr() class of functions</A |
| ></DT |
| ><DT |
| >6.5. <A |
| HREF="#ACAUTION" |
| >A word of caution</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >7. <A |
| HREF="#SCANW" |
| >Input functions</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >7.1. <A |
| HREF="#GETCHCLASS" |
| >getch() class of functions</A |
| ></DT |
| ><DT |
| >7.2. <A |
| HREF="#SCANWCLASS" |
| >scanw() class of functions</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >7.2.1. <A |
| HREF="#SCANWMVSCANW" |
| >scanw() and mvscanw</A |
| ></DT |
| ><DT |
| >7.2.2. <A |
| HREF="#WSCANWMVWSCANW" |
| >wscanw() and mvwscanw()</A |
| ></DT |
| ><DT |
| >7.2.3. <A |
| HREF="#VWSCANW" |
| >vwscanw()</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >7.3. <A |
| HREF="#GETSTRCLASS" |
| >getstr() class of functions</A |
| ></DT |
| ><DT |
| >7.4. <A |
| HREF="#GETSTREX" |
| >Some examples</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >8. <A |
| HREF="#ATTRIB" |
| >Attributes</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >8.1. <A |
| HREF="#ATTRIBDETAILS" |
| >The details</A |
| ></DT |
| ><DT |
| >8.2. <A |
| HREF="#ATTRONVSATTRSET" |
| >attron() vs attrset()</A |
| ></DT |
| ><DT |
| >8.3. <A |
| HREF="#ATTR_GET" |
| >attr_get()</A |
| ></DT |
| ><DT |
| >8.4. <A |
| HREF="#ATTR_FUNCS" |
| >attr_ functions</A |
| ></DT |
| ><DT |
| >8.5. <A |
| HREF="#WATTRFUNCS" |
| >wattr functions</A |
| ></DT |
| ><DT |
| >8.6. <A |
| HREF="#CHGAT" |
| >chgat() functions</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >9. <A |
| HREF="#WINDOWS" |
| >Windows</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >9.1. <A |
| HREF="#WINDOWBASICS" |
| >The basics</A |
| ></DT |
| ><DT |
| >9.2. <A |
| HREF="#LETBEWINDOW" |
| >Let there be a Window !!!</A |
| ></DT |
| ><DT |
| >9.3. <A |
| HREF="#BORDEREXEXPL" |
| >Explanation</A |
| ></DT |
| ><DT |
| >9.4. <A |
| HREF="#OTHERSTUFF" |
| >The other stuff in the example</A |
| ></DT |
| ><DT |
| >9.5. <A |
| HREF="#OTHERBORDERFUNCS" |
| >Other Border functions</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >10. <A |
| HREF="#COLOR" |
| >Colors</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >10.1. <A |
| HREF="#COLORBASICS" |
| >The basics</A |
| ></DT |
| ><DT |
| >10.2. <A |
| HREF="#CHANGECOLORDEFS" |
| >Changing Color Definitions</A |
| ></DT |
| ><DT |
| >10.3. <A |
| HREF="#COLORCONTENT" |
| >Color Content</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >11. <A |
| HREF="#KEYS" |
| >Interfacing with the key board</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >11.1. <A |
| HREF="#KEYSBASICS" |
| >The Basics</A |
| ></DT |
| ><DT |
| >11.2. <A |
| HREF="#SIMPLEKEYEX" |
| >A Simple Key Usage example</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >12. <A |
| HREF="#MOUSE" |
| >Interfacing with the mouse</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >12.1. <A |
| HREF="#MOUSEBASICS" |
| >The Basics</A |
| ></DT |
| ><DT |
| >12.2. <A |
| HREF="#GETTINGEVENTS" |
| >Getting the events</A |
| ></DT |
| ><DT |
| >12.3. <A |
| HREF="#MOUSETOGETHER" |
| >Putting it all Together</A |
| ></DT |
| ><DT |
| >12.4. <A |
| HREF="#MISCMOUSEFUNCS" |
| >Miscellaneous Functions</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >13. <A |
| HREF="#SCREEN" |
| >Screen Manipulation</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >13.1. <A |
| HREF="#GETYX" |
| >getyx() functions</A |
| ></DT |
| ><DT |
| >13.2. <A |
| HREF="#SCREENDUMP" |
| >Screen Dumping</A |
| ></DT |
| ><DT |
| >13.3. <A |
| HREF="#WINDOWDUMP" |
| >Window Dumping</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >14. <A |
| HREF="#MISC" |
| >Miscellaneous features</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >14.1. <A |
| HREF="#CURSSET" |
| >curs_set()</A |
| ></DT |
| ><DT |
| >14.2. <A |
| HREF="#TEMPLEAVE" |
| >Temporarily Leaving Curses mode</A |
| ></DT |
| ><DT |
| >14.3. <A |
| HREF="#ACSVARS" |
| >ACS_ variables</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >15. <A |
| HREF="#OTHERLIB" |
| >Other libraries</A |
| ></DT |
| ><DT |
| >16. <A |
| HREF="#PANELS" |
| >Panel Library</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >16.1. <A |
| HREF="#PANELBASICS" |
| >The Basics</A |
| ></DT |
| ><DT |
| >16.2. <A |
| HREF="#COMPILEPANELS" |
| >Compiling With the Panels Library</A |
| ></DT |
| ><DT |
| >16.3. <A |
| HREF="#PANELBROWSING" |
| >Panel Window Browsing</A |
| ></DT |
| ><DT |
| >16.4. <A |
| HREF="#USERPTRUSING" |
| >Using User Pointers</A |
| ></DT |
| ><DT |
| >16.5. <A |
| HREF="#PANELMOVERESIZE" |
| >Moving and Resizing Panels</A |
| ></DT |
| ><DT |
| >16.6. <A |
| HREF="#PANELSHOWHIDE" |
| >Hiding and Showing Panels</A |
| ></DT |
| ><DT |
| >16.7. <A |
| HREF="#PANELABOVE" |
| >panel_above() and panel_below() Functions</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >17. <A |
| HREF="#MENUS" |
| >Menus Library</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >17.1. <A |
| HREF="#MENUBASICS" |
| >The Basics</A |
| ></DT |
| ><DT |
| >17.2. <A |
| HREF="#COMPILEMENUS" |
| >Compiling With the Menu Library</A |
| ></DT |
| ><DT |
| >17.3. <A |
| HREF="#MENUDRIVER" |
| >Menu Driver: The work horse of the menu system</A |
| ></DT |
| ><DT |
| >17.4. <A |
| HREF="#MENUWINDOWS" |
| >Menu Windows</A |
| ></DT |
| ><DT |
| >17.5. <A |
| HREF="#SCROLLMENUS" |
| >Scrolling Menus</A |
| ></DT |
| ><DT |
| >17.6. <A |
| HREF="#MULTICOLUMN" |
| >Multi Columnar Menus</A |
| ></DT |
| ><DT |
| >17.7. <A |
| HREF="#MULTIVALUEMENUS" |
| >Multi Valued Menus</A |
| ></DT |
| ><DT |
| >17.8. <A |
| HREF="#MENUOPT" |
| >Menu Options</A |
| ></DT |
| ><DT |
| >17.9. <A |
| HREF="#MENUUSERPTR" |
| >The useful User Pointer</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >18. <A |
| HREF="#FORMS" |
| >Forms Library</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >18.1. <A |
| HREF="#FORMBASICS" |
| >The Basics</A |
| ></DT |
| ><DT |
| >18.2. <A |
| HREF="#COMPILEFORMS" |
| >Compiling With the Forms Library</A |
| ></DT |
| ><DT |
| >18.3. <A |
| HREF="#PLAYFIELDS" |
| >Playing with Fields</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >18.3.1. <A |
| HREF="#FETCHINFO" |
| >Fetching Size and Location of Field</A |
| ></DT |
| ><DT |
| >18.3.2. <A |
| HREF="#MOVEFIELD" |
| >Moving the field</A |
| ></DT |
| ><DT |
| >18.3.3. <A |
| HREF="#JUSTIFYFIELD" |
| >Field Justification</A |
| ></DT |
| ><DT |
| >18.3.4. <A |
| HREF="#FIELDDISPATTRIB" |
| >Field Display Attributes</A |
| ></DT |
| ><DT |
| >18.3.5. <A |
| HREF="#FIELDOPTIONBITS" |
| >Field Option Bits</A |
| ></DT |
| ><DT |
| >18.3.6. <A |
| HREF="#FIELDSTATUS" |
| >Field Status</A |
| ></DT |
| ><DT |
| >18.3.7. <A |
| HREF="#FIELDUSERPTR" |
| >Field User Pointer</A |
| ></DT |
| ><DT |
| >18.3.8. <A |
| HREF="#VARIABLESIZEFIELDS" |
| >Variable-Sized Fields</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >18.4. <A |
| HREF="#FORMWINDOWS" |
| >Form Windows</A |
| ></DT |
| ><DT |
| >18.5. <A |
| HREF="#FILEDVALIDATE" |
| >Field Validation</A |
| ></DT |
| ><DT |
| >18.6. <A |
| HREF="#FORMDRIVER" |
| >Form Driver: The work horse of the forms system</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >18.6.1. <A |
| HREF="#PAGENAVREQ" |
| >Page Navigation Requests</A |
| ></DT |
| ><DT |
| >18.6.2. <A |
| HREF="#INTERFIELDNAVREQ" |
| >Inter-Field Navigation Requests</A |
| ></DT |
| ><DT |
| >18.6.3. <A |
| HREF="#INTRAFIELDNAVREQ" |
| >Intra-Field Navigation Requests</A |
| ></DT |
| ><DT |
| >18.6.4. <A |
| HREF="#SCROLLREQ" |
| >Scrolling Requests</A |
| ></DT |
| ><DT |
| >18.6.5. <A |
| HREF="#EDITREQ" |
| >Editing Requests</A |
| ></DT |
| ><DT |
| >18.6.6. <A |
| HREF="#ORDERREQ" |
| >Order Requests</A |
| ></DT |
| ><DT |
| >18.6.7. <A |
| HREF="#APPLICCOMMANDS" |
| >Application Commands</A |
| ></DT |
| ></DL |
| ></DD |
| ></DL |
| ></DD |
| ><DT |
| >19. <A |
| HREF="#TOOLS" |
| >Tools and Widget Libraries</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >19.1. <A |
| HREF="#CDK" |
| >CDK (Curses Development Kit)</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >19.1.1. <A |
| HREF="#WIDGETLIST" |
| >Widget List</A |
| ></DT |
| ><DT |
| >19.1.2. <A |
| HREF="#CDKATTRACT" |
| >Some Attractive Features</A |
| ></DT |
| ><DT |
| >19.1.3. <A |
| HREF="#CDKCONCLUSION" |
| >Conclusion</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >19.2. <A |
| HREF="#DIALOG" |
| >The dialog</A |
| ></DT |
| ><DT |
| >19.3. <A |
| HREF="#PERLCURSES" |
| >Perl Curses Modules CURSES::FORM and CURSES::WIDGETS</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >20. <A |
| HREF="#JUSTFORFUN" |
| >Just For Fun !!!</A |
| ></DT |
| ><DD |
| ><DL |
| ><DT |
| >20.1. <A |
| HREF="#GAMEOFLIFE" |
| >The Game of Life</A |
| ></DT |
| ><DT |
| >20.2. <A |
| HREF="#MAGIC" |
| >Magic Square</A |
| ></DT |
| ><DT |
| >20.3. <A |
| HREF="#HANOI" |
| >Towers of Hanoi</A |
| ></DT |
| ><DT |
| >20.4. <A |
| HREF="#QUEENS" |
| >Queens Puzzle</A |
| ></DT |
| ><DT |
| >20.5. <A |
| HREF="#SHUFFLE" |
| >Shuffle</A |
| ></DT |
| ><DT |
| >20.6. <A |
| HREF="#TT" |
| >Typing Tutor</A |
| ></DT |
| ></DL |
| ></DD |
| ><DT |
| >21. <A |
| HREF="#REF" |
| >References</A |
| ></DT |
| ></DL |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="INTRO" |
| >1. Introduction</A |
| ></H2 |
| ><P |
| >In the olden days of teletype terminals, terminals were away from computers and |
| were connected to them through serial cables. The terminals could be configured |
| by sending a series of bytes. All the capabilities (such as |
| moving the cursor to a new location, erasing part of the screen, scrolling the |
| screen, changing modes etc.) of terminals could be accessed through these |
| series of bytes. These control seeuqnces are usually called escape sequences, |
| because they start |
| with an escape(0x1B) character. Even today, with proper emulation, we can send |
| escape sequences to the emulator and achieve the same effect on a terminal |
| window.</P |
| ><P |
| >Suppose you wanted to print a line in color. Try typing this on your console.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| >echo "^[[0;31;40mIn Color"</PRE |
| ><P |
| >The first character is an escape character, which looks like two characters ^ |
| and [. To be able to print it, you have to press CTRL+V and then the ESC key. |
| All the others are normal printable characters. You should be able to see the |
| string "In Color" in red. It stays that way and to revert back to the original |
| mode type this.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| >echo "^[[0;37;40m"</PRE |
| ><P |
| >Now, what do these magic characters mean? Difficult to comprehend? They might |
| even be different for different terminals. So the designers of UNIX invented a |
| mechanism named <TT |
| CLASS="LITERAL" |
| >termcap</TT |
| >. It is a file that |
| lists all the capabilities of a particular terminal, along with the escape |
| sequences needed to achieve a particular effect. In the later years, this was |
| replaced by <TT |
| CLASS="LITERAL" |
| >terminfo</TT |
| >. Without delving too |
| much into details, this mechanism allows application |
| programs to query the terminfo database and obtain the control characters to be |
| sent to a terminal or terminal emulator.</P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WHATIS" |
| >1.1. What is NCURSES?</A |
| ></H3 |
| ><P |
| > |
| You might be wondering, what the import of all this technical gibberish is. In |
| the above scenario, every application program is supposed to query the terminfo |
| and perform the necessary stuff (sending control characters etc.). It soon became |
| difficult to manage this complexity and this gave birth to 'CURSES'. Curses is |
| a pun on the name "cursor optimization". The Curses library forms a wrapper |
| over working with raw terminal codes, and provides highly flexible and |
| efficient API (Application Programming Interface). It provides functions to |
| move the cursor, create windows, produce colors, play with mouse etc. The |
| application programs need not worry about the underlying terminal capabilities.</P |
| ><P |
| >So what is NCURSES? NCURSES is a clone of the original System V Release 4.0 |
| (SVr4) curses. It is a freely distributable library, fully compatible with |
| older version of curses. In short, it is a library of functions that manages |
| an application's display on character-cell terminals. In the remainder of the |
| document, the terms curses and ncurses are used interchangeably. </P |
| ><P |
| >A detailed history of NCURSES can be found in the NEWS file from the source |
| distribution. The current package is maintained by |
| <A |
| HREF="mailto:dickey@his.com" |
| TARGET="_top" |
| >Thomas Dickey</A |
| >. |
| You can contact the maintainers at <A |
| HREF="mailto:bug-ncurses@gnu.org" |
| TARGET="_top" |
| >bug-ncurses@gnu.org</A |
| >.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WHATCANWEDO" |
| >1.2. What we can do with NCURSES</A |
| ></H3 |
| ><P |
| >NCURSES not only creates a wrapper over terminal capabilities, but also gives a |
| robust framework to create nice looking UI (User Interface)s in text mode. It |
| provides functions to create windows etc. Its sister libraries panel, menu and |
| form provide an extension to the basic curses library. These libraries usually |
| come along with curses. One can create applications that contain multiple |
| windows, menus, panels and forms. Windows can be managed independently, can |
| provide 'scrollability' and even can be hidden.</P |
| ><P |
| > |
| Menus provide the user with an easy command selection option. Forms allow the |
| creation of easy-to-use data entry and display windows. Panels extend the |
| capabilities of ncurses to deal with overlapping and stacked windows.</P |
| ><P |
| >These are just some of the basic things we can do with ncurses. As we move |
| along, We will see all the capabilities of these libraries. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WHERETOGETIT" |
| >1.3. Where to get it</A |
| ></H3 |
| ><P |
| >All right, now that you know what you can do with ncurses, you must be rearing |
| to get started. NCURSES is usually shipped with your installation. In case |
| you don't have the library or want to compile it on your own, read on.</P |
| ><P |
| ><SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >Compiling the package</I |
| ></SPAN |
| > </P |
| ><P |
| >NCURSES can be obtained from <A |
| HREF="ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz" |
| TARGET="_top" |
| >ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</A |
| > or any of the ftp |
| sites mentioned in <A |
| HREF="http://www.gnu.org/order/ftp.html" |
| TARGET="_top" |
| >http://www.gnu.org/order/ftp.html</A |
| >. </P |
| ><P |
| >Read the README and INSTALL files for details on to how to install it. It |
| usually involves the following operations.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > tar zxvf ncurses<version>.tar.gz # unzip and untar the archive |
| cd ncurses<version> # cd to the directory |
| ./configure # configure the build according to your |
| # environment |
| make # make it |
| su root # become root |
| make install # install it</PRE |
| ><P |
| ><SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >Using the RPM </I |
| ></SPAN |
| ></P |
| ><P |
| >NCURSES RPM can be found and downloaded from <A |
| HREF="http://rpmfind.net" |
| TARGET="_top" |
| >http://rpmfind.net </A |
| >. The RPM can be installed with the following |
| command after becoming root.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > rpm -i <downloaded rpm></PRE |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="PURPOSE" |
| >1.4. Purpose/Scope of the document</A |
| ></H3 |
| ><P |
| >This document is intended to be a "All in One" guide for programming with |
| ncurses and its sister libraries. We graduate from a simple "Hello World" |
| program to more complex form manipulation. No prior experience in ncurses is |
| assumed. The writing is informal, but a lot of detail is provided for |
| each of the examples.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ABOUTPROGRAMS" |
| >1.5. About the Programs</A |
| ></H3 |
| ><P |
| >All the programs in the document are available in zipped form |
| <A |
| HREF="http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz" |
| TARGET="_top" |
| >here</A |
| >. Unzip and untar it. The directory structure looks like this.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| >ncurses |
| | |
| |----> JustForFun -- just for fun programs |
| |----> basics -- basic programs |
| |----> demo -- output files go into this directory after make |
| | | |
| | |----> exe -- exe files of all example programs |
| |----> forms -- programs related to form library |
| |----> menus -- programs related to menus library |
| |----> panels -- programs related to panels library |
| |----> perl -- perl equivalents of the examples (contributed |
| | by Anuradha Ratnaweera) |
| |----> Makefile -- the top level Makefile |
| |----> README -- the top level README file. contains instructions |
| |----> COPYING -- copyright notice</PRE |
| ><P |
| >The individual directories contain the following files.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| >Description of files in each directory |
| -------------------------------------- |
| JustForFun |
| | |
| |----> hanoi.c -- The Towers of Hanoi Solver |
| |----> life.c -- The Game of Life demo |
| |----> magic.c -- An Odd Order Magic Square builder |
| |----> queens.c -- The famous N-Queens Solver |
| |----> shuffle.c -- A fun game, if you have time to kill |
| |----> tt.c -- A very trivial typing tutor |
| |
| basics |
| | |
| |----> acs_vars.c -- ACS_ variables example |
| |----> hello_world.c -- Simple "Hello World" Program |
| |----> init_func_example.c -- Initialization functions example |
| |----> key_code.c -- Shows the scan code of the key pressed |
| |----> mouse_menu.c -- A menu accessible by mouse |
| |----> other_border.c -- Shows usage of other border functions apa |
| | -- rt from box() |
| |----> printw_example.c -- A very simple printw() example |
| |----> scanw_example.c -- A very simple getstr() example |
| |----> simple_attr.c -- A program that can print a c file with |
| | -- comments in attribute |
| |----> simple_color.c -- A simple example demonstrating colors |
| |----> simple_key.c -- A menu accessible with keyboard UP, DOWN |
| | -- arrows |
| |----> temp_leave.c -- Demonstrates temporarily leaving curses mode |
| |----> win_border.c -- Shows Creation of windows and borders |
| |----> with_chgat.c -- chgat() usage example |
| |
| forms |
| | |
| |----> form_attrib.c -- Usage of field attributes |
| |----> form_options.c -- Usage of field options |
| |----> form_simple.c -- A simple form example |
| |----> form_win.c -- Demo of windows associated with forms |
| |
| menus |
| | |
| |----> menu_attrib.c -- Usage of menu attributes |
| |----> menu_item_data.c -- Usage of item_name() etc.. functions |
| |----> menu_multi_column.c -- Creates multi columnar menus |
| |----> menu_scroll.c -- Demonstrates scrolling capability of menus |
| |----> menu_simple.c -- A simple menu accessed by arrow keys |
| |----> menu_toggle.c -- Creates multi valued menus and explains |
| | -- REQ_TOGGLE_ITEM |
| |----> menu_userptr.c -- Usage of user pointer |
| |----> menu_win.c -- Demo of windows associated with menus |
| |
| panels |
| | |
| |----> panel_browse.c -- Panel browsing through tab. Usage of user |
| | -- pointer |
| |----> panel_hide.c -- Hiding and Un hiding of panels |
| |----> panel_resize.c -- Moving and resizing of panels |
| |----> panel_simple.c -- A simple panel example |
| |
| perl |
| |----> 01-10.pl -- Perl equivalents of first ten example programs</PRE |
| ><P |
| >There is a top level Makefile included in the main directory. It builds all the |
| files and puts the ready-to-use exes in demo/exe directory. You can also |
| do selective make by going into the corresponding directory. Each directory |
| contains a README file explaining the purpose of each c file in the directory.</P |
| ><P |
| >For every example, I have included path name for the file relative to the |
| examples directory. </P |
| ><P |
| > If you prefer browsing individual programs, point your browser to |
| <A |
| HREF="http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/" |
| TARGET="_top" |
| >http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</A |
| ></P |
| ><P |
| >All the programs are released under the same license that is used by ncurses |
| (MIT-style). This gives you the ability to do pretty much anything other than |
| claiming them as yours. Feel free to use them in your programs as appropriate.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="OTHERFORMATS" |
| >1.6. Other Formats of the document</A |
| ></H3 |
| ><P |
| >This howto is also availabe in various other formats on the tldp.org site. |
| Here are the links to other formats of this document.</P |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="LISTFORMATS" |
| >1.6.1. Readily available formats from tldp.org</A |
| ></H4 |
| ><P |
| ></P |
| ><UL |
| ><LI |
| ><P |
| ><A |
| HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf" |
| TARGET="_top" |
| >Acrobat PDF Format</A |
| ></P |
| ></LI |
| ><LI |
| ><P |
| ><A |
| HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz" |
| TARGET="_top" |
| >PostScript Format</A |
| ></P |
| ></LI |
| ><LI |
| ><P |
| ><A |
| HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz" |
| TARGET="_top" |
| >In Multiple HTML pages</A |
| ></P |
| ></LI |
| ><LI |
| ><P |
| ><A |
| HREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html" |
| TARGET="_top" |
| >In One big HTML format</A |
| ></P |
| ></LI |
| ></UL |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="BUILDSOURCE" |
| >1.6.2. Building from source</A |
| ></H4 |
| ><P |
| >If above links are broken or if you want to experiment with sgml read on. |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > Get both the source and the tar,gzipped programs, available at |
| http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ |
| NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml |
| http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ |
| NCURSES-HOWTO/ncurses_programs.tar.gz |
| |
| Unzip ncurses_programs.tar.gz with |
| tar zxvf ncurses_programs.tar.gz |
| |
| Use jade to create various formats. For example if you just want to create |
| the multiple html files, you would use |
| jade -t sgml -i html -d <path to docbook html stylesheet> |
| NCURSES-Programming-HOWTO.sgml |
| to get pdf, first create a single html file of the HOWTO with |
| jade -t sgml -i html -d <path to docbook html stylesheet> -V nochunks |
| NCURSES-Programming-HOWTO.sgml > NCURSES-ONE-BIG-FILE.html |
| then use htmldoc to get pdf file with |
| htmldoc --size universal -t pdf --firstpage p1 -f <output file name.pdf> |
| NCURSES-ONE-BIG-FILE.html |
| for ps, you would use |
| htmldoc --size universal -t ps --firstpage p1 -f <output file name.ps> |
| NCURSES-ONE-BIG-FILE.html</PRE |
| ></P |
| ><P |
| >See <A |
| HREF="http://www.tldp.org/LDP/LDP-Author-Guide/" |
| TARGET="_top" |
| >LDP Author guide</A |
| > for more details. If all else failes, mail me at |
| <A |
| HREF="ppadala@gmail.com" |
| TARGET="_top" |
| >ppadala@gmail.com</A |
| ></P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="CREDITS" |
| >1.7. Credits</A |
| ></H3 |
| ><P |
| >I thank <A |
| HREF="mailto:sharath_1@usa.net" |
| TARGET="_top" |
| >Sharath</A |
| > and Emre Akbas for |
| helping me with few sections. The introduction was initially written by sharath. |
| I rewrote it with few excerpts taken from his initial work. Emre helped in |
| writing printw and scanw sections.</P |
| ><P |
| >Perl equivalents of the example programs are contributed by <A |
| HREF="mailto:Aratnaweera@virtusa.com" |
| TARGET="_top" |
| >Anuradha Ratnaweera</A |
| >. </P |
| ><P |
| >Then comes <A |
| HREF="mailto:parimi@ece.arizona.edu" |
| TARGET="_top" |
| >Ravi Parimi</A |
| >, my |
| dearest friend, who has been on this project before even one line was written. |
| He constantly bombarded me with suggestions and patiently reviewed the whole |
| text. He also checked each program on Linux and Solaris. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WISHLIST" |
| >1.8. Wish List</A |
| ></H3 |
| ><P |
| >This is the wish list, in the order of priority. If you have a wish or you want |
| to work on completing the wish, mail <A |
| HREF="mailto:ppadala@gmail.com" |
| TARGET="_top" |
| >me</A |
| >. </P |
| ><P |
| ></P |
| ><UL |
| ><LI |
| ><P |
| >Add examples to last parts of forms section.</P |
| ></LI |
| ><LI |
| ><P |
| >Prepare a Demo showing all the programs and allow the user to browse through |
| description of each program. Let the user compile and see the program in action. |
| A dialog based interface is preferred.</P |
| ></LI |
| ><LI |
| ><P |
| >Add debug info. _tracef, _tracemouse stuff.</P |
| ></LI |
| ><LI |
| ><P |
| >Accessing termcap, terminfo using functions provided by ncurses |
| package.</P |
| ></LI |
| ><LI |
| ><P |
| >Working on two terminals simultaneously.</P |
| ></LI |
| ><LI |
| ><P |
| >Add more stuff to miscellaneous section.</P |
| ></LI |
| ></UL |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="COPYRIGHT" |
| >1.9. Copyright</A |
| ></H3 |
| ><P |
| >Copyright © 2001 by Pradeep Padala. </P |
| ><P |
| >Permission is hereby granted, free of charge, to any person obtaining a copy |
| of this software and associated documentation files (the "Software"), to deal |
| in the Software without restriction, including without limitation the rights |
| to use, copy, modify, merge, publish, distribute, distribute with |
| modifications, sublicense, and/or sell copies of the Software, and to permit |
| persons to whom the Software is furnished to do so, subject to the following |
| conditions:</P |
| ><P |
| >The above copyright notice and this permission notice shall be included in all |
| copies or substantial portions of the Software.</P |
| ><P |
| >THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR |
| IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</P |
| ><P |
| >Except as contained in this notice, the name(s) of the above copyright holders |
| shall not be used in advertising or otherwise to promote the sale, use or |
| other dealings in this Software without prior written authorization. </P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="HELLOWORLD" |
| >2. Hello World !!!</A |
| ></H2 |
| ><P |
| >Welcome to the world of curses. Before we plunge into the library and look into |
| its various features, let's write a simple program and say |
| hello to the world. </P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="COMPILECURSES" |
| >2.1. Compiling With the NCURSES Library</A |
| ></H3 |
| ><P |
| >To use ncurses library functions, you have to include ncurses.h in your |
| programs. To link the |
| program with ncurses the flag -lncurses should be added.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > #include <ncurses.h> |
| . |
| . |
| . |
| |
| compile and link: gcc <program file> -lncurses</PRE |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BHW" |
| ></A |
| ><P |
| ><B |
| >Example 1. The Hello World !!! Program </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| int main() |
| { |
| initscr(); /* Start curses mode */ |
| printw("Hello World !!!"); /* Print Hello World */ |
| refresh(); /* Print it on to the real screen */ |
| getch(); /* Wait for user input */ |
| endwin(); /* End curses mode */ |
| |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="DISSECTION" |
| >2.2. Dissection</A |
| ></H3 |
| ><P |
| > |
| The above program prints "Hello World !!!" to the screen and exits. This |
| program shows how to initialize curses and do screen manipulation and |
| end curses mode. Let's dissect it line by line. </P |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="ABOUT-INITSCR" |
| >2.2.1. About initscr()</A |
| ></H4 |
| ><P |
| >The function initscr() initializes the terminal in curses mode. In some |
| implementations, it clears the screen and presents a blank screen. To do any |
| screen manipulation using curses package this has to be called first. This |
| function initializes the curses system and allocates memory for our present |
| window (called <TT |
| CLASS="LITERAL" |
| >stdscr</TT |
| >) and some other data-structures. Under extreme |
| cases this function might fail due to insufficient memory to allocate memory |
| for curses library's data structures. </P |
| ><P |
| > |
| After this is done, we can do a variety of initializations to customize |
| our curses settings. These details will be explained <A |
| HREF="#INIT" |
| >later </A |
| >.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="MYST-REFRESH" |
| >2.2.2. The mysterious refresh()</A |
| ></H4 |
| ><P |
| >The next line printw prints the string "Hello World !!!" on to the screen. This |
| function is analogous to normal printf in all respects except that it prints |
| the data on a window called stdscr at the current (y,x) co-ordinates. Since our |
| present co-ordinates are at 0,0 the string is printed at the left hand corner |
| of the window.</P |
| ><P |
| >This brings us to that mysterious refresh(). Well, when we called printw |
| the data is actually written to an imaginary window, which is not updated |
| on the screen yet. The job of printw is to update a few flags |
| and data structures and write the data to a buffer corresponding to stdscr. |
| In order to show it on the screen, we need to call refresh() and tell the |
| curses system to dump the contents on the screen.</P |
| ><P |
| >The philosophy behind all this is to allow the programmer to do multiple updates |
| on the imaginary screen or windows and do a refresh once all his screen update |
| is done. refresh() checks the window and updates only the portion which has been |
| changed. This improves performance and offers greater flexibility too. But, it is |
| sometimes frustrating to beginners. A common mistake committed by beginners is |
| to forget to call refresh() after they did some update through printw() class of |
| functions. I still forget to add it sometimes :-) </P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="ABOUT-ENDWIN" |
| >2.2.3. About endwin()</A |
| ></H4 |
| ><P |
| >And finally don't forget to end the curses mode. Otherwise your terminal might |
| behave strangely after the program quits. endwin() frees the memory taken by |
| curses sub-system and its data structures and puts the terminal in normal |
| mode. This function must be called after you are done with the curses mode. </P |
| ></DIV |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="GORY" |
| >3. The Gory Details</A |
| ></H2 |
| ><P |
| >Now that we have seen how to write a simple curses program let's get into the |
| details. There are many functions that help customize what you see on screen and |
| many features which can be put to full use. </P |
| ><P |
| >Here we go...</P |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="INIT" |
| >4. Initialization</A |
| ></H2 |
| ><P |
| >We now know that to initialize curses system the function initscr() has to be |
| called. There are functions which can be called after this initialization to |
| customize our curses session. We may ask the curses system to set the terminal |
| in raw mode or initialize color or initialize the mouse etc.. Let's discuss some |
| of the functions that are normally called immediately after initscr();</P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ABOUTINIT" |
| >4.1. Initialization functions</A |
| ></H3 |
| ><P |
| > </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="RAWCBREAK" |
| >4.2. raw() and cbreak()</A |
| ></H3 |
| ><P |
| >Normally the terminal driver buffers the characters a user types until a new |
| line or carriage return is encountered. But most programs require that the |
| characters be available as soon as the user types them. The above two functions |
| are used to disable line buffering. The difference between these two functions |
| is in the way control characters like suspend (CTRL-Z), interrupt and quit |
| (CTRL-C) are passed to the program. In the raw() mode these characters are |
| directly passed to the program without generating a signal. In the |
| <TT |
| CLASS="LITERAL" |
| >cbreak()</TT |
| > mode these control characters are |
| interpreted as any other character by the terminal driver. I personally prefer |
| to use raw() as I can exercise greater control over what the user does.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ECHONOECHO" |
| >4.3. echo() and noecho()</A |
| ></H3 |
| ><P |
| > |
| These functions control the echoing of characters typed by the user to the |
| terminal. <TT |
| CLASS="LITERAL" |
| >noecho()</TT |
| > switches off echoing. The |
| reason you might want to do this is to gain more control over echoing or to |
| suppress unnecessary echoing while taking input from the user through the |
| getch() etc. functions. Most of the interactive programs call |
| <TT |
| CLASS="LITERAL" |
| >noecho()</TT |
| > at initialization and do the echoing |
| of characters in a controlled manner. It gives the programmer the flexibility |
| of echoing characters at any place in the window without updating current (y,x) |
| co-ordinates. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="KEYPAD" |
| >4.4. keypad()</A |
| ></H3 |
| ><P |
| >This is my favorite initialization function. It enables the reading of function |
| keys like F1, F2, arrow keys etc. Almost every interactive program enables this, |
| as arrow keys are a major part of any User Interface. Do |
| <TT |
| CLASS="LITERAL" |
| >keypad(stdscr, TRUE) </TT |
| > to enable this feature |
| for the regular screen (stdscr). You will learn more about key management in |
| later sections of this document.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="HALFDELAY" |
| >4.5. halfdelay()</A |
| ></H3 |
| ><P |
| >This function, though not used very often, is a useful one at times. |
| halfdelay()is called to enable the half-delay mode, which is similar to the |
| cbreak() mode in that characters typed are immediately available to program. |
| However, it waits for 'X' tenths of a second for input and then returns ERR, if |
| no input is available. 'X' is the timeout value passed to the function |
| halfdelay(). This function is useful when you want to ask the user for input, |
| and if he doesn't respond with in certain time, we can do some thing else. One |
| possible example is a timeout at the password prompt. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="MISCINIT" |
| >4.6. Miscellaneous Initialization functions</A |
| ></H3 |
| ><P |
| >There are few more functions which are called at initialization to |
| customize curses behavior. They are not used as extensively as those mentioned |
| above. Some of them are explained where appropriate.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="INITEX" |
| >4.7. An Example</A |
| ></H3 |
| ><P |
| >Let's write a program which will clarify the usage of these functions.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BINFU" |
| ></A |
| ><P |
| ><B |
| >Example 2. Initialization Function Usage example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| int main() |
| { int ch; |
| |
| initscr(); /* Start curses mode */ |
| raw(); /* Line buffering disabled */ |
| keypad(stdscr, TRUE); /* We get F1, F2 etc.. */ |
| noecho(); /* Don't echo() while we do getch */ |
| |
| printw("Type any character to see it in bold\n"); |
| ch = getch(); /* If raw() hadn't been called |
| * we have to press enter before it |
| * gets to the program */ |
| if(ch == KEY_F(1)) /* Without keypad enabled this will */ |
| printw("F1 Key pressed");/* not get to us either */ |
| /* Without noecho() some ugly escape |
| * charachters might have been printed |
| * on screen */ |
| else |
| { printw("The pressed key is "); |
| attron(A_BOLD); |
| printw("%c", ch); |
| attroff(A_BOLD); |
| } |
| refresh(); /* Print it on to the real screen */ |
| getch(); /* Wait for user input */ |
| endwin(); /* End curses mode */ |
| |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ><P |
| >This program is self-explanatory. But I used functions which aren't explained |
| yet. The function <TT |
| CLASS="LITERAL" |
| >getch()</TT |
| > is used to get a |
| character from user. It is equivalent to normal |
| <TT |
| CLASS="LITERAL" |
| >getchar()</TT |
| > except that we can disable the line |
| buffering to avoid <enter> after input. Look for more about |
| <TT |
| CLASS="LITERAL" |
| >getch()</TT |
| >and reading keys in the <A |
| HREF="#KEYS" |
| > key management section </A |
| >. The functions attron and attroff |
| are used to switch some attributes on and off respectively. In the example I |
| used them to print the character in bold. These functions are explained in detail |
| later.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="AWORDWINDOWS" |
| >5. A Word about Windows</A |
| ></H2 |
| ><P |
| > |
| Before we plunge into the myriad ncurses functions, let me clear few things |
| about windows. Windows are explained in detail in following <A |
| HREF="#WINDOWS" |
| > sections </A |
| ></P |
| ><P |
| >A Window is an imaginary screen defined by curses system. A window does not mean |
| a bordered window which you usually see on Win9X platforms. When curses is |
| initialized, it creates a default window named |
| <TT |
| CLASS="LITERAL" |
| >stdscr</TT |
| > which represents your 80x25 (or the size |
| of window in which you are running) screen. If you are doing simple tasks like |
| printing few strings, reading input etc., you can safely use this single window |
| for all of your purposes. You can also create windows and call functions which |
| explicitly work on the specified window.</P |
| ><P |
| >For example, if you call</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > printw("Hi There !!!"); |
| refresh();</PRE |
| ><P |
| >It prints the string on stdscr at the present cursor position. Similarly the |
| call to refresh(), works on stdscr only. </P |
| ><P |
| >Say you have created <A |
| HREF="#WINDOWS" |
| >windows</A |
| > then you have to |
| call a function with a 'w' added to the usual function.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > wprintw(win, "Hi There !!!"); |
| wrefresh(win);</PRE |
| ><P |
| >As you will see in the rest of the document, naming of functions follow the |
| same convention. For each function there usually are three more functions.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > printw(string); /* Print on stdscr at present cursor position */ |
| mvprintw(y, x, string);/* Move to (y, x) then print string */ |
| wprintw(win, string); /* Print on window win at present cursor position */ |
| /* in the window */ |
| mvwprintw(win, y, x, string); /* Move to (y, x) relative to window */ |
| /* co-ordinates and then print */</PRE |
| ><P |
| >Usually the w-less functions are macros which expand to corresponding w-function |
| with stdscr as the window parameter.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="PRINTW" |
| >6. Output functions</A |
| ></H2 |
| ><P |
| >I guess you can't wait any more to see some action. Back to our odyssey of |
| curses functions. Now that curses is initialized, let's interact with |
| world.</P |
| ><P |
| >There are three classes of functions which you can use to do output on screen. |
| <P |
| ></P |
| ><OL |
| TYPE="1" |
| ><LI |
| ><P |
| >addch() class: Print single character with attributes </P |
| ></LI |
| ><LI |
| ><P |
| >printw() class: Print formatted output similar to printf()</P |
| ></LI |
| ><LI |
| ><P |
| >addstr() class: Print strings</P |
| ></LI |
| ></OL |
| ></P |
| ><P |
| >These functions can be used interchangeably and it's a matter of style as to |
| which class is used. Let's see each one in detail.</P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ADDCHCLASS" |
| >6.1. addch() class of functions</A |
| ></H3 |
| ><P |
| >These functions put a single character into the current cursor location and |
| advance the position of the cursor. You can give the character to be printed but |
| they usually are used to print a character with some attributes. Attributes are |
| explained in detail in later <A |
| HREF="#ATTRIB" |
| > sections </A |
| > of the |
| document. If a character is associated with an attribute(bold, reverse video |
| etc.), when curses prints the character, it is printed in that attribute.</P |
| ><P |
| >In order to combine a character with some attributes, you have two options:</P |
| ><P |
| ></P |
| ><UL |
| ><LI |
| ><P |
| >By OR'ing a single character with the desired attribute macros. These attribute |
| macros could be found in the header file |
| <TT |
| CLASS="LITERAL" |
| >ncurses.h</TT |
| >. For example, you want to print a |
| character ch(of type char) bold and underlined, you would call addch() as below. |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > addch(ch | A_BOLD | A_UNDERLINE);</PRE |
| ></P |
| ></LI |
| ><LI |
| ><P |
| >By using functions like <TT |
| CLASS="LITERAL" |
| >attrset(),attron(),attroff()</TT |
| >. These functions are explained in the <A |
| HREF="#ATTRIB" |
| >Attributes</A |
| > section. Briefly, they manipulate the current attributes of |
| the given window. Once set, the character printed in the window are associated |
| with the attributes until it is turned off.</P |
| ></LI |
| ></UL |
| ><P |
| >Additionally, <TT |
| CLASS="LITERAL" |
| >curses</TT |
| > provides some special |
| characters for character-based graphics. You can draw tables, horizontal or |
| vertical lines, etc. You can find all avaliable characters in the header file |
| <TT |
| CLASS="LITERAL" |
| >ncurses.h</TT |
| >. Try looking for macros beginning |
| with <TT |
| CLASS="LITERAL" |
| >ACS_</TT |
| > in this file. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="AEN298" |
| >6.2. mvaddch(), waddch() and mvwaddch()</A |
| ></H3 |
| ><P |
| ><TT |
| CLASS="LITERAL" |
| >mvaddch()</TT |
| > is used to move the cursor to a |
| given point, and then print. Thus, the calls: |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > move(row,col); /* moves the cursor to row<SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >th</I |
| ></SPAN |
| > row and col<SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >th</I |
| ></SPAN |
| > column */ |
| addch(ch);</PRE |
| > |
| can be replaced by |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > mvaddch(row,col,ch);</PRE |
| ></P |
| ><P |
| ><TT |
| CLASS="LITERAL" |
| >waddch()</TT |
| > is similar to |
| <TT |
| CLASS="LITERAL" |
| >addch()</TT |
| >, except that it adds a character into |
| the given window. (Note that <TT |
| CLASS="LITERAL" |
| >addch()</TT |
| > adds a |
| character into the window <TT |
| CLASS="LITERAL" |
| >stdscr</TT |
| >.)</P |
| ><P |
| >In a similar fashion <TT |
| CLASS="LITERAL" |
| >mvwaddch()</TT |
| > function is |
| used to add a character into the given window at the given coordinates.</P |
| ><P |
| >Now, we are familiar with the basic output function |
| <TT |
| CLASS="LITERAL" |
| >addch()</TT |
| >. But, if we want to print a string, it |
| would be very annoying to print it character by character. Fortunately, |
| <TT |
| CLASS="LITERAL" |
| >ncurses</TT |
| > provides <TT |
| CLASS="LITERAL" |
| >printf</TT |
| ><SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >-like</I |
| ></SPAN |
| > or |
| <TT |
| CLASS="LITERAL" |
| >puts</TT |
| ><SPAN |
| CLASS="emphasis" |
| ><I |
| CLASS="EMPHASIS" |
| >-like</I |
| ></SPAN |
| > functions.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="PRINTWCLASS" |
| >6.3. printw() class of functions</A |
| ></H3 |
| ><P |
| >These functions are similar to <TT |
| CLASS="LITERAL" |
| >printf()</TT |
| > with |
| the added capability of printing at any position on the screen. </P |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="PRINTWMVPRINTW" |
| >6.3.1. printw() and mvprintw</A |
| ></H4 |
| ><P |
| >These two functions work much like <TT |
| CLASS="LITERAL" |
| >printf()</TT |
| >. |
| <TT |
| CLASS="LITERAL" |
| >mvprintw()</TT |
| > can be used to move the cursor to a |
| position and then print. If you want to move the cursor first and then print |
| using <TT |
| CLASS="LITERAL" |
| >printw()</TT |
| > function, use |
| <TT |
| CLASS="LITERAL" |
| >move() </TT |
| > first and then use |
| <TT |
| CLASS="LITERAL" |
| >printw()</TT |
| > though I see no point why one should |
| avoid using <TT |
| CLASS="LITERAL" |
| >mvprintw()</TT |
| >, you have the |
| flexibility to manipulate. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="WPRINTWMVWPRINTW" |
| >6.3.2. wprintw() and mvwprintw</A |
| ></H4 |
| ><P |
| >These two functions are similar to above two except that they print in the |
| corresponding window given as argument. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="VWPRINTW" |
| >6.3.3. vwprintw()</A |
| ></H4 |
| ><P |
| >This function is similar to <TT |
| CLASS="LITERAL" |
| >vprintf()</TT |
| >. This can |
| be used when variable number of arguments are to be printed.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="SIMPLEPRINTWEX" |
| >6.3.4. A Simple printw example</A |
| ></H4 |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BPREX" |
| ></A |
| ><P |
| ><B |
| >Example 3. A Simple printw example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> /* ncurses.h includes stdio.h */ |
| #include <string.h> |
| |
| int main() |
| { |
| char mesg[]="Just a string"; /* message to be appeared on the screen */ |
| int row,col; /* to store the number of rows and * |
| * the number of colums of the screen */ |
| initscr(); /* start the curses mode */ |
| getmaxyx(stdscr,row,col); /* get the number of rows and columns */ |
| mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); |
| /* print the message at the center of the screen */ |
| mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col); |
| printw("Try resizing your window(if possible) and then run this program again"); |
| refresh(); |
| getch(); |
| endwin(); |
| |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ><P |
| >Above program demonstrates how easy it is to use <TT |
| CLASS="LITERAL" |
| >printw</TT |
| >. You just feed the coordinates and the message to be appeared |
| on the screen, then it does what you want.</P |
| ><P |
| >The above program introduces us to a new function |
| <TT |
| CLASS="LITERAL" |
| >getmaxyx()</TT |
| >, a macro defined in |
| <TT |
| CLASS="LITERAL" |
| >ncurses.h</TT |
| >. It gives the number of columns and |
| the number of rows in a given window. |
| <TT |
| CLASS="LITERAL" |
| >getmaxyx()</TT |
| > does this by updating the variables |
| given to it. Since <TT |
| CLASS="LITERAL" |
| >getmaxyx()</TT |
| > is not a function |
| we don't pass pointers to it, we just give two integer variables. </P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ADDSTRCLASS" |
| >6.4. addstr() class of functions</A |
| ></H3 |
| ><P |
| ><TT |
| CLASS="LITERAL" |
| >addstr()</TT |
| > is used to put a character string into |
| a given window. This function is similar to calling |
| <TT |
| CLASS="LITERAL" |
| >addch()</TT |
| > once for each character in a given |
| string. This is true for all output functions. There are other functions from |
| this family such as <TT |
| CLASS="LITERAL" |
| >mvaddstr(),mvwaddstr()</TT |
| > and |
| <TT |
| CLASS="LITERAL" |
| >waddstr()</TT |
| >, which obey the naming convention of |
| curses.(e.g. mvaddstr() is similar to the respective calls move() and then |
| addstr().) Another function of this family is addnstr(), which takes an integer |
| parameter(say n) additionally. This function puts at most n characters into the |
| screen. If n is negative, then the entire string will be added. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ACAUTION" |
| >6.5. A word of caution</A |
| ></H3 |
| ><P |
| >All these functions take y co-ordinate first and then x in their arguments. |
| A common mistake by beginners is to pass x,y in that order. If you are |
| doing too many manipulations of (y,x) co-ordinates, think of dividing the |
| screen into windows and manipulate each one separately. Windows are explained |
| in the <A |
| HREF="#WINDOWS" |
| > windows </A |
| > section.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="SCANW" |
| >7. Input functions</A |
| ></H2 |
| ><P |
| >Well, printing without taking input, is boring. Let's see functions which |
| allow us to get input from user. These functions also can be divided into |
| three categories.</P |
| ><P |
| ></P |
| ><OL |
| TYPE="1" |
| ><LI |
| ><P |
| >getch() class: Get a character</P |
| ></LI |
| ><LI |
| ><P |
| >scanw() class: Get formatted input</P |
| ></LI |
| ><LI |
| ><P |
| >getstr() class: Get strings</P |
| ></LI |
| ></OL |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="GETCHCLASS" |
| >7.1. getch() class of functions</A |
| ></H3 |
| ><P |
| >These functions read a single character from the terminal. But there are several |
| subtle facts to consider. For example if you don't use the function cbreak(), |
| curses will not read your input characters contiguously but will begin read them |
| only after a new line or an EOF is encountered. In order to avoid this, the |
| cbreak() function must used so that characters are immediately available to your |
| program. Another widely used function is noecho(). As the name suggests, when |
| this function is set (used), the characters that are keyed in by the user will |
| not show up on the screen. The two functions cbreak() and noecho() are typical |
| examples of key management. Functions of this genre are explained in the |
| <A |
| HREF="#KEYS" |
| >key management section </A |
| >.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="SCANWCLASS" |
| >7.2. scanw() class of functions</A |
| ></H3 |
| ><P |
| >These functions are similar to <TT |
| CLASS="LITERAL" |
| >scanf()</TT |
| > with the |
| added capability of getting the input from any location on the screen.</P |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="SCANWMVSCANW" |
| >7.2.1. scanw() and mvscanw</A |
| ></H4 |
| ><P |
| >The usage of these functions is similar to that of |
| <TT |
| CLASS="LITERAL" |
| >sscanf()</TT |
| >, where the line to be scanned is |
| provided by <TT |
| CLASS="LITERAL" |
| >wgetstr()</TT |
| > function. That is, these |
| functions call to <TT |
| CLASS="LITERAL" |
| >wgetstr()</TT |
| > function(explained |
| below) and uses the resulting line for a scan. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="WSCANWMVWSCANW" |
| >7.2.2. wscanw() and mvwscanw()</A |
| ></H4 |
| ><P |
| >These are similar to above two functions except that they read from a window, |
| which is supplied as one of the arguments to these functions. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT3" |
| ><HR><H4 |
| CLASS="SECT3" |
| ><A |
| NAME="VWSCANW" |
| >7.2.3. vwscanw()</A |
| ></H4 |
| ><P |
| >This function is similar to <TT |
| CLASS="LITERAL" |
| >vscanf()</TT |
| >. This can |
| be used when a variable number of arguments are to be scanned.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="GETSTRCLASS" |
| >7.3. getstr() class of functions</A |
| ></H3 |
| ><P |
| >These functions are used to get strings from the terminal. In essence, this |
| function performs the same task as would be achieved by a series of calls to |
| <TT |
| CLASS="LITERAL" |
| >getch()</TT |
| > until a newline, carriage return, or |
| end-of-file is received. The resulting string of characters are pointed to by |
| <TT |
| CLASS="LITERAL" |
| >str</TT |
| >, which is a character pointer provided by |
| the user.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="GETSTREX" |
| >7.4. Some examples</A |
| ></H3 |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BSCEX" |
| ></A |
| ><P |
| ><B |
| >Example 4. A Simple scanw example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> /* ncurses.h includes stdio.h */ |
| #include <string.h> |
| |
| int main() |
| { |
| char mesg[]="Enter a string: "; /* message to be appeared on the screen */ |
| char str[80]; |
| int row,col; /* to store the number of rows and * |
| * the number of colums of the screen */ |
| initscr(); /* start the curses mode */ |
| getmaxyx(stdscr,row,col); /* get the number of rows and columns */ |
| mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); |
| /* print the message at the center of the screen */ |
| getstr(str); |
| mvprintw(LINES - 2, 0, "You Entered: %s", str); |
| getch(); |
| endwin(); |
| |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="ATTRIB" |
| >8. Attributes</A |
| ></H2 |
| ><P |
| >We have seen an example of how attributes can be used to print characters with |
| some special effects. Attributes, when set prudently, can present information in |
| an easy, understandable manner. The following program takes a C file as input |
| and prints the file with comments in bold. Scan through the code. </P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BSIAT" |
| ></A |
| ><P |
| ><B |
| >Example 5. A Simple Attributes example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >/* pager functionality by Joseph Spainhour" <spainhou@bellsouth.net> */ |
| #include <ncurses.h> |
| #include <stdlib.h> |
| |
| int main(int argc, char *argv[]) |
| { |
| int ch, prev, row, col; |
| prev = EOF; |
| FILE *fp; |
| int y, x; |
| |
| if(argc != 2) |
| { |
| printf("Usage: %s <a c file name>\n", argv[0]); |
| exit(1); |
| } |
| fp = fopen(argv[1], "r"); |
| if(fp == NULL) |
| { |
| perror("Cannot open input file"); |
| exit(1); |
| } |
| initscr(); /* Start curses mode */ |
| getmaxyx(stdscr, row, col); /* find the boundaries of the screeen */ |
| while((ch = fgetc(fp)) != EOF) /* read the file till we reach the end */ |
| { |
| getyx(stdscr, y, x); /* get the current curser position */ |
| if(y == (row - 1)) /* are we are at the end of the screen */ |
| { |
| printw("<-Press Any Key->"); /* tell the user to press a key */ |
| getch(); |
| clear(); /* clear the screen */ |
| move(0, 0); /* start at the beginning of the screen */ |
| } |
| if(prev == '/' && ch == '*') /* If it is / and * then only |
| * switch bold on */ |
| { |
| attron(A_BOLD); /* cut bold on */ |
| getyx(stdscr, y, x); /* get the current curser position */ |
| move(y, x - 1); /* back up one space */ |
| printw("%c%c", '/', ch); /* The actual printing is done here */ |
| } |
| else |
| printw("%c", ch); |
| refresh(); |
| if(prev == '*' && ch == '/') |
| attroff(A_BOLD); /* Switch it off once we got * |
| * and then / */ |
| prev = ch; |
| } |
| endwin(); /* End curses mode */ |
| fclose(fp); |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ><P |
| > |
| Don't worry about all those initialization and other crap. Concentrate on |
| the while loop. It reads each character in the file and searches for the |
| pattern /*. Once it spots the pattern, it switches the BOLD attribute on with |
| <TT |
| CLASS="LITERAL" |
| > attron()</TT |
| > . When we get the pattern */ it is |
| switched off by <TT |
| CLASS="LITERAL" |
| > attroff()</TT |
| > .</P |
| ><P |
| > |
| The above program also introduces us to two useful functions |
| <TT |
| CLASS="LITERAL" |
| >getyx() </TT |
| > and |
| <TT |
| CLASS="LITERAL" |
| >move()</TT |
| >. The first function gets the |
| co-ordinates of the present cursor into the variables y, x. Since getyx() is a |
| macro we don't have to pass pointers to variables. The function |
| <TT |
| CLASS="LITERAL" |
| >move()</TT |
| > moves the cursor to the co-ordinates |
| given to it. </P |
| ><P |
| > |
| The above program is really a simple one which doesn't do much. On these lines |
| one could write a more useful program which reads a C file, parses it and prints |
| it in different colors. One could even extend it to other languages as well.</P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ATTRIBDETAILS" |
| >8.1. The details</A |
| ></H3 |
| ><P |
| >Let's get into more details of attributes. The functions <TT |
| CLASS="LITERAL" |
| >attron(), attroff(), attrset() </TT |
| >, and their sister functions |
| <TT |
| CLASS="LITERAL" |
| > attr_get()</TT |
| > etc.. can be used to switch |
| attributes on/off , get attributes and produce a colorful display.</P |
| ><P |
| >The functions attron and attroff take a bit-mask of attributes and switch them |
| on or off, respectively. The following video attributes, which are defined in |
| <curses.h> can be passed to these functions. </P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > |
| A_NORMAL Normal display (no highlight) |
| A_STANDOUT Best highlighting mode of the terminal. |
| A_UNDERLINE Underlining |
| A_REVERSE Reverse video |
| A_BLINK Blinking |
| A_DIM Half bright |
| A_BOLD Extra bright or bold |
| A_PROTECT Protected mode |
| A_INVIS Invisible or blank mode |
| A_ALTCHARSET Alternate character set |
| A_CHARTEXT Bit-mask to extract a character |
| COLOR_PAIR(n) Color-pair number n |
| </PRE |
| ><P |
| > |
| The last one is the most colorful one :-) Colors are explained in the |
| <A |
| HREF="#color" |
| TARGET="_top" |
| >next sections</A |
| >.</P |
| ><P |
| >We can OR(|) any number of above attributes to get a combined effect. If you |
| wanted reverse video with blinking characters you can use</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > attron(A_REVERSE | A_BLINK);</PRE |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ATTRONVSATTRSET" |
| >8.2. attron() vs attrset()</A |
| ></H3 |
| ><P |
| >Then what is the difference between attron() and attrset()? attrset sets the |
| attributes of window whereas attron just switches on the attribute given to it. |
| So attrset() fully overrides whatever attributes the window previously had and |
| sets it to the new attribute(s). Similarly attroff() just switches off the |
| attribute(s) given to it as an argument. This gives us the flexibility of |
| managing attributes easily.But if you use them carelessly you may loose track of |
| what attributes the window has and garble the display. This is especially true |
| while managing menus with colors and highlighting. So decide on a consistent |
| policy and stick to it. You can always use <TT |
| CLASS="LITERAL" |
| > standend()</TT |
| > which is equivalent to <TT |
| CLASS="LITERAL" |
| > attrset(A_NORMAL)</TT |
| > which turns off all attributes and brings you to normal mode.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ATTR_GET" |
| >8.3. attr_get()</A |
| ></H3 |
| ><P |
| > The function attr_get() gets the current attributes and color pair of the |
| window. Though we might not use this as often as the above functions, this is |
| useful in scanning areas of screen. Say we wanted to do some complex update on |
| screen and we are not sure what attribute each character is associated with. |
| Then this function can be used with either attrset or attron to produce the |
| desired effect. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="ATTR_FUNCS" |
| >8.4. attr_ functions</A |
| ></H3 |
| ><P |
| >There are series of functions like attr_set(), attr_on etc.. These are similar |
| to above functions except that they take parameters of type |
| <TT |
| CLASS="LITERAL" |
| >attr_t</TT |
| >.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WATTRFUNCS" |
| >8.5. wattr functions</A |
| ></H3 |
| ><P |
| >For each of the above functions we have a corresponding function with 'w' which |
| operates on a particular window. The above functions operate on stdscr. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="CHGAT" |
| >8.6. chgat() functions</A |
| ></H3 |
| ><P |
| >The function chgat() is listed in the end of the man page curs_attr. It actually |
| is a useful one. This function can be used to set attributes for a group of |
| characters without moving. I mean it !!! without moving the cursor :-) It |
| changes the attributes of a given number of characters starting at the current |
| cursor location.</P |
| ><P |
| >We can give -1 as the character count to update till end of line. If you want to |
| change attributes of characters from current position to end of line, just use |
| this.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > chgat(-1, A_REVERSE, 0, NULL);</PRE |
| ><P |
| > |
| This function is useful when changing attributes for characters that are |
| already on the screen. Move to the character from which you want to change and |
| change the attribute. </P |
| ><P |
| >Other functions wchgat(), mvchgat(), wchgat() behave similarly except that the w |
| functions operate on the particular window. The mv functions first move the |
| cursor then perform the work given to them. Actually chgat is a macro which is |
| replaced by a wchgat() with stdscr as the window. Most of the "w-less" functions |
| are macros.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BWICH" |
| ></A |
| ><P |
| ><B |
| >Example 6. Chgat() Usage example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| int main(int argc, char *argv[]) |
| { initscr(); /* Start curses mode */ |
| start_color(); /* Start color functionality */ |
| |
| init_pair(1, COLOR_CYAN, COLOR_BLACK); |
| printw("A Big string which i didn't care to type fully "); |
| mvchgat(0, 0, -1, A_BLINK, 1, NULL); |
| /* |
| * First two parameters specify the position at which to start |
| * Third parameter number of characters to update. -1 means till |
| * end of line |
| * Forth parameter is the normal attribute you wanted to give |
| * to the charcter |
| * Fifth is the color index. It is the index given during init_pair() |
| * use 0 if you didn't want color |
| * Sixth one is always NULL |
| */ |
| refresh(); |
| getch(); |
| endwin(); /* End curses mode */ |
| return 0; |
| }</SPAN |
| ></PRE |
| ></DIV |
| ><P |
| >This example also introduces us to the color world of curses. Colors will be |
| explained in detail later. Use 0 for no color.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="WINDOWS" |
| >9. Windows</A |
| ></H2 |
| ><P |
| >Windows form the most important concept in curses. You have seen the standard |
| window stdscr above where all the functions implicitly operated on this window. |
| Now to make design even a simplest GUI, you need to resort to windows. The main |
| reason you may want to use windows is to manipulate parts of the screen |
| separately, for better efficiency, by updating only the windows that need to be |
| changed and for a better design. I would say the last reason is the most |
| important in going for windows. You should always strive for a better and |
| easy-to-manage design in your programs. If you are writing big, complex GUIs |
| this is of pivotal importance before you start doing anything.</P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WINDOWBASICS" |
| >9.1. The basics</A |
| ></H3 |
| ><P |
| >A Window can be created by calling the function |
| <TT |
| CLASS="LITERAL" |
| >newwin()</TT |
| >. It doesn't create any thing on the |
| screen actually. It allocates memory for a structure to manipulate the window |
| and updates the structure with data regarding the window like it's size, beginy, |
| beginx etc.. Hence in curses, a window is just an abstraction of an imaginary |
| window, which can be manipulated independent of other parts of screen. The |
| function newwin() returns a pointer to structure WINDOW, which can be passed to |
| window related functions like wprintw() etc.. Finally the window can be |
| destroyed with delwin(). It will deallocate the memory associated with the |
| window structure.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="LETBEWINDOW" |
| >9.2. Let there be a Window !!!</A |
| ></H3 |
| ><P |
| >What fun is it, if a window is created and we can't see it. So the fun part |
| begins by displaying the window. The function |
| <TT |
| CLASS="LITERAL" |
| >box()</TT |
| > can be used to draw a border around the |
| window. Let's explore these functions in more detail in this example.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BWIBO" |
| ></A |
| ><P |
| ><B |
| >Example 7. Window Border example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| |
| WINDOW *create_newwin(int height, int width, int starty, int startx); |
| void destroy_win(WINDOW *local_win); |
| |
| int main(int argc, char *argv[]) |
| { WINDOW *my_win; |
| int startx, starty, width, height; |
| int ch; |
| |
| initscr(); /* Start curses mode */ |
| cbreak(); /* Line buffering disabled, Pass on |
| * everty thing to me */ |
| keypad(stdscr, TRUE); /* I need that nifty F1 */ |
| |
| height = 3; |
| width = 10; |
| starty = (LINES - height) / 2; /* Calculating for a center placement */ |
| startx = (COLS - width) / 2; /* of the window */ |
| printw("Press F1 to exit"); |
| refresh(); |
| my_win = create_newwin(height, width, starty, startx); |
| |
| while((ch = getch()) != KEY_F(1)) |
| { switch(ch) |
| { case KEY_LEFT: |
| destroy_win(my_win); |
| my_win = create_newwin(height, width, starty,--startx); |
| break; |
| case KEY_RIGHT: |
| destroy_win(my_win); |
| my_win = create_newwin(height, width, starty,++startx); |
| break; |
| case KEY_UP: |
| destroy_win(my_win); |
| my_win = create_newwin(height, width, --starty,startx); |
| break; |
| case KEY_DOWN: |
| destroy_win(my_win); |
| my_win = create_newwin(height, width, ++starty,startx); |
| break; |
| } |
| } |
| |
| endwin(); /* End curses mode */ |
| return 0; |
| } |
| |
| WINDOW *create_newwin(int height, int width, int starty, int startx) |
| { WINDOW *local_win; |
| |
| local_win = newwin(height, width, starty, startx); |
| box(local_win, 0 , 0); /* 0, 0 gives default characters |
| * for the vertical and horizontal |
| * lines */ |
| wrefresh(local_win); /* Show that box */ |
| |
| return local_win; |
| } |
| |
| void destroy_win(WINDOW *local_win) |
| { |
| /* box(local_win, ' ', ' '); : This won't produce the desired |
| * result of erasing the window. It will leave it's four corners |
| * and so an ugly remnant of window. |
| */ |
| wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' '); |
| /* The parameters taken are |
| * 1. win: the window on which to operate |
| * 2. ls: character to be used for the left side of the window |
| * 3. rs: character to be used for the right side of the window |
| * 4. ts: character to be used for the top side of the window |
| * 5. bs: character to be used for the bottom side of the window |
| * 6. tl: character to be used for the top left corner of the window |
| * 7. tr: character to be used for the top right corner of the window |
| * 8. bl: character to be used for the bottom left corner of the window |
| * 9. br: character to be used for the bottom right corner of the window |
| */ |
| wrefresh(local_win); |
| delwin(local_win); |
| }</SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="BORDEREXEXPL" |
| >9.3. Explanation</A |
| ></H3 |
| ><P |
| >Don't scream. I know it's a big example. But I have to explain some important |
| things here :-). This program creates a rectangular window that can be moved |
| with left, right, up, down arrow keys. It repeatedly creates and destroys |
| windows as user press a key. Don't go beyond the screen limits. Checking for |
| those limits is left as an exercise for the reader. Let's dissect it by line by line.</P |
| ><P |
| >The <TT |
| CLASS="LITERAL" |
| >create_newwin()</TT |
| > function creates a window |
| with <TT |
| CLASS="LITERAL" |
| >newwin() </TT |
| > and displays a border around it |
| with box. The function <TT |
| CLASS="LITERAL" |
| > destroy_win()</TT |
| > first |
| erases the window from screen by painting a border with ' ' character and then |
| calling <TT |
| CLASS="LITERAL" |
| >delwin()</TT |
| > to deallocate memory related |
| to it. Depending on the key the user presses, starty or startx is changed and a |
| new window is created.</P |
| ><P |
| >In the destroy_win, as you can see, I used wborder instead of box. The reason is |
| written in the comments (You missed it. I know. Read the code :-)). wborder |
| draws a border around the window with the characters given to it as the 4 corner |
| points and the 4 lines. To put it clearly, if you have called wborder as below: |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');</PRE |
| ></P |
| ><P |
| >it produces some thing like </P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > +------------+ |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| +------------+</PRE |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="OTHERSTUFF" |
| >9.4. The other stuff in the example</A |
| ></H3 |
| ><P |
| >You can also see in the above examples, that I have used the variables COLS, |
| LINES which are initialized to the screen sizes after initscr(). They can be |
| useful in finding screen dimensions and finding the center co-ordinate of the |
| screen as above. The function <TT |
| CLASS="LITERAL" |
| >getch()</TT |
| > as usual |
| gets the key from keyboard and according to the key it does the corresponding |
| work. This type of switch- case is very common in any GUI based programs.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="OTHERBORDERFUNCS" |
| >9.5. Other Border functions</A |
| ></H3 |
| ><P |
| >Above program is grossly inefficient in that with each press of a key, a window |
| is destroyed and another is created. So let's write a more efficient program |
| which uses other border related functions.</P |
| ><P |
| >The following program uses <TT |
| CLASS="LITERAL" |
| >mvhline()</TT |
| > and |
| <TT |
| CLASS="LITERAL" |
| >mvvline()</TT |
| > to achieve similar effect. These two |
| functions are simple. They create a horizontal or vertical line of the specified |
| length at the specified position.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BOTBO" |
| ></A |
| ><P |
| ><B |
| >Example 8. More border functions</B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| typedef struct _win_border_struct { |
| chtype ls, rs, ts, bs, |
| tl, tr, bl, br; |
| }WIN_BORDER; |
| |
| typedef struct _WIN_struct { |
| |
| int startx, starty; |
| int height, width; |
| WIN_BORDER border; |
| }WIN; |
| |
| void init_win_params(WIN *p_win); |
| void print_win_params(WIN *p_win); |
| void create_box(WIN *win, bool flag); |
| |
| int main(int argc, char *argv[]) |
| { WIN win; |
| int ch; |
| |
| initscr(); /* Start curses mode */ |
| start_color(); /* Start the color functionality */ |
| cbreak(); /* Line buffering disabled, Pass on |
| * everty thing to me */ |
| keypad(stdscr, TRUE); /* I need that nifty F1 */ |
| noecho(); |
| init_pair(1, COLOR_CYAN, COLOR_BLACK); |
| |
| /* Initialize the window parameters */ |
| init_win_params(&win); |
| print_win_params(&win); |
| |
| attron(COLOR_PAIR(1)); |
| printw("Press F1 to exit"); |
| refresh(); |
| attroff(COLOR_PAIR(1)); |
| |
| create_box(&win, TRUE); |
| while((ch = getch()) != KEY_F(1)) |
| { switch(ch) |
| { case KEY_LEFT: |
| create_box(&win, FALSE); |
| --win.startx; |
| create_box(&win, TRUE); |
| break; |
| case KEY_RIGHT: |
| create_box(&win, FALSE); |
| ++win.startx; |
| create_box(&win, TRUE); |
| break; |
| case KEY_UP: |
| create_box(&win, FALSE); |
| --win.starty; |
| create_box(&win, TRUE); |
| break; |
| case KEY_DOWN: |
| create_box(&win, FALSE); |
| ++win.starty; |
| create_box(&win, TRUE); |
| break; |
| } |
| } |
| endwin(); /* End curses mode */ |
| return 0; |
| } |
| void init_win_params(WIN *p_win) |
| { |
| p_win->height = 3; |
| p_win->width = 10; |
| p_win->starty = (LINES - p_win->height)/2; |
| p_win->startx = (COLS - p_win->width)/2; |
| |
| p_win->border.ls = '|'; |
| p_win->border.rs = '|'; |
| p_win->border.ts = '-'; |
| p_win->border.bs = '-'; |
| p_win->border.tl = '+'; |
| p_win->border.tr = '+'; |
| p_win->border.bl = '+'; |
| p_win->border.br = '+'; |
| |
| } |
| void print_win_params(WIN *p_win) |
| { |
| #ifdef _DEBUG |
| mvprintw(25, 0, "%d %d %d %d", p_win->startx, p_win->starty, |
| p_win->width, p_win->height); |
| refresh(); |
| #endif |
| } |
| void create_box(WIN *p_win, bool flag) |
| { int i, j; |
| int x, y, w, h; |
| |
| x = p_win->startx; |
| y = p_win->starty; |
| w = p_win->width; |
| h = p_win->height; |
| |
| if(flag == TRUE) |
| { mvaddch(y, x, p_win->border.tl); |
| mvaddch(y, x + w, p_win->border.tr); |
| mvaddch(y + h, x, p_win->border.bl); |
| mvaddch(y + h, x + w, p_win->border.br); |
| mvhline(y, x + 1, p_win->border.ts, w - 1); |
| mvhline(y + h, x + 1, p_win->border.bs, w - 1); |
| mvvline(y + 1, x, p_win->border.ls, h - 1); |
| mvvline(y + 1, x + w, p_win->border.rs, h - 1); |
| |
| } |
| else |
| for(j = y; j <= y + h; ++j) |
| for(i = x; i <= x + w; ++i) |
| mvaddch(j, i, ' '); |
| |
| refresh(); |
| |
| }</SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="COLOR" |
| >10. Colors</A |
| ></H2 |
| ><DIV |
| CLASS="SECT2" |
| ><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="COLORBASICS" |
| >10.1. The basics</A |
| ></H3 |
| ><P |
| >Life seems dull with no colors. Curses has a nice mechanism to handle colors. |
| Let's get into the thick of the things with a small program.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BSICO" |
| ></A |
| ><P |
| ><B |
| >Example 9. A Simple Color example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string); |
| int main(int argc, char *argv[]) |
| { initscr(); /* Start curses mode */ |
| if(has_colors() == FALSE) |
| { endwin(); |
| printf("Your terminal does not support color\n"); |
| exit(1); |
| } |
| start_color(); /* Start color */ |
| init_pair(1, COLOR_RED, COLOR_BLACK); |
| |
| attron(COLOR_PAIR(1)); |
| print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ..."); |
| attroff(COLOR_PAIR(1)); |
| getch(); |
| endwin(); |
| } |
| void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string) |
| { int length, x, y; |
| float temp; |
| |
| if(win == NULL) |
| win = stdscr; |
| getyx(win, y, x); |
| if(startx != 0) |
| x = startx; |
| if(starty != 0) |
| y = starty; |
| if(width == 0) |
| width = 80; |
| |
| length = strlen(string); |
| temp = (width - length)/ 2; |
| x = startx + (int)temp; |
| mvwprintw(win, y, x, "%s", string); |
| refresh(); |
| } |
| </SPAN |
| ></PRE |
| ></DIV |
| ><P |
| >As you can see, to start using color, you should first call the function |
| <TT |
| CLASS="LITERAL" |
| > start_color()</TT |
| >. After that, you can use color |
| capabilities of your terminals using various functions. To find out whether a |
| terminal has color capabilities or not, you can use |
| <TT |
| CLASS="LITERAL" |
| >has_colors()</TT |
| > function, which returns FALSE if |
| the terminal does not support color. </P |
| ><P |
| >Curses initializes all the colors supported by terminal when start_color() is |
| called. These can be accessed by the define constants like |
| <TT |
| CLASS="LITERAL" |
| >COLOR_BLACK </TT |
| > etc. Now to actually start using |
| colors, you have to define pairs. Colors are always used in pairs. That means |
| you have to use the function <TT |
| CLASS="LITERAL" |
| >init_pair() </TT |
| > to |
| define the foreground and background for the pair number you give. After that |
| that pair number can be used as a normal attribute with <TT |
| CLASS="LITERAL" |
| >COLOR_PAIR()</TT |
| >function. This may seem to be cumbersome at first. |
| But this elegant solution allows us to manage color pairs very easily. To |
| appreciate it, you have to look into the the source code of "dialog", a utility |
| for displaying dialog boxes from shell scripts. The developers have defined |
| foreground and background combinations for all the colors they might need and |
| initialized at the beginning. This makes it very easy to set attributes just by |
| accessing a pair which we already have defined as a constant.</P |
| ><P |
| >The following colors are defined in <TT |
| CLASS="LITERAL" |
| >curses.h</TT |
| >. |
| You can use these as parameters for various color functions. |
| <PRE |
| CLASS="PROGRAMLISTING" |
| > COLOR_BLACK 0 |
| COLOR_RED 1 |
| COLOR_GREEN 2 |
| COLOR_YELLOW 3 |
| COLOR_BLUE 4 |
| COLOR_MAGENTA 5 |
| COLOR_CYAN 6 |
| COLOR_WHITE 7</PRE |
| ></P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="CHANGECOLORDEFS" |
| >10.2. Changing Color Definitions</A |
| ></H3 |
| ><P |
| >The function <TT |
| CLASS="LITERAL" |
| >init_color()</TT |
| >can be used to change |
| the rgb values for the colors defined by curses initially. Say you wanted to |
| lighten the intensity of red color by a minuscule. Then you can use this |
| function as</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > init_color(COLOR_RED, 700, 0, 0); |
| /* param 1 : color name |
| * param 2, 3, 4 : rgb content min = 0, max = 1000 */</PRE |
| ><P |
| >If your terminal cannot change the color definitions, the function returns ERR. |
| The function <TT |
| CLASS="LITERAL" |
| >can_change_color()</TT |
| > can be used to |
| find out whether the terminal has the capability of changing color content or |
| not. The rgb content is scaled from 0 to 1000. Initially RED color is defined |
| with content 1000(r), 0(g), 0(b). </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="COLORCONTENT" |
| >10.3. Color Content</A |
| ></H3 |
| ><P |
| >The functions <TT |
| CLASS="LITERAL" |
| >color_content()</TT |
| > and |
| <TT |
| CLASS="LITERAL" |
| >pair_content()</TT |
| > can be used to find the color |
| content and foreground, background combination for the pair. </P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="KEYS" |
| >11. Interfacing with the key board</A |
| ></H2 |
| ><DIV |
| CLASS="SECT2" |
| ><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="KEYSBASICS" |
| >11.1. The Basics</A |
| ></H3 |
| ><P |
| >No GUI is complete without a strong user interface and to interact with the |
| user, a curses program should be sensitive to key presses or the mouse actions |
| done by the user. Let's deal with the keys first.</P |
| ><P |
| >As you have seen in almost all of the above examples, it's very easy to get key |
| input from the user. A simple way of getting key presses is to use |
| <TT |
| CLASS="LITERAL" |
| >getch()</TT |
| > function. The cbreak mode should be |
| enabled to read keys when you are interested in reading individual key hits |
| rather than complete lines of text (which usually end with a carriage return). |
| keypad should be enabled to get the Functions keys, arrow keys etc. See the |
| initialization section for details.</P |
| ><P |
| ><TT |
| CLASS="LITERAL" |
| >getch()</TT |
| > returns an integer corresponding to the |
| key pressed. If it is a normal character, the integer value will be equivalent |
| to the character. Otherwise it returns a number which can be matched with the |
| constants defined in <TT |
| CLASS="LITERAL" |
| >curses.h</TT |
| >. For example if |
| the user presses F1, the integer returned is 265. This can be checked using the |
| macro KEY_F() defined in curses.h. This makes reading keys portable and easy to |
| manage.</P |
| ><P |
| >For example, if you call getch() like this</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > int ch; |
| |
| ch = getch();</PRE |
| ><P |
| >getch() will wait for the user to press a key, (unless you specified a timeout) |
| and when user presses a key, the corresponding integer is returned. Then you can |
| check the value returned with the constants defined in curses.h to match against |
| the keys you want.</P |
| ><P |
| >The following code piece will do that job.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > if(ch == KEY_LEFT) |
| printw("Left arrow is pressed\n");</PRE |
| ><P |
| >Let's write a small program which creates a menu which can be navigated by up |
| and down arrows.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="SIMPLEKEYEX" |
| >11.2. A Simple Key Usage example</A |
| ></H3 |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BSIKE" |
| ></A |
| ><P |
| ><B |
| >Example 10. A Simple Key Usage example </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <stdio.h> |
| #include <ncurses.h> |
| |
| #define WIDTH 30 |
| #define HEIGHT 10 |
| |
| int startx = 0; |
| int starty = 0; |
| |
| char *choices[] = { |
| "Choice 1", |
| "Choice 2", |
| "Choice 3", |
| "Choice 4", |
| "Exit", |
| }; |
| int n_choices = sizeof(choices) / sizeof(char *); |
| void print_menu(WINDOW *menu_win, int highlight); |
| |
| int main() |
| { WINDOW *menu_win; |
| int highlight = 1; |
| int choice = 0; |
| int c; |
| |
| initscr(); |
| clear(); |
| noecho(); |
| cbreak(); /* Line buffering disabled. pass on everything */ |
| startx = (80 - WIDTH) / 2; |
| starty = (24 - HEIGHT) / 2; |
| |
| menu_win = newwin(HEIGHT, WIDTH, starty, startx); |
| keypad(menu_win, TRUE); |
| mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice"); |
| refresh(); |
| print_menu(menu_win, highlight); |
| while(1) |
| { c = wgetch(menu_win); |
| switch(c) |
| { case KEY_UP: |
| if(highlight == 1) |
| highlight = n_choices; |
| else |
| --highlight; |
| break; |
| case KEY_DOWN: |
| if(highlight == n_choices) |
| highlight = 1; |
| else |
| ++highlight; |
| break; |
| case 10: |
| choice = highlight; |
| break; |
| default: |
| mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c); |
| refresh(); |
| break; |
| } |
| print_menu(menu_win, highlight); |
| if(choice != 0) /* User did a choice come out of the infinite loop */ |
| break; |
| } |
| mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]); |
| clrtoeol(); |
| refresh(); |
| endwin(); |
| return 0; |
| } |
| |
| |
| void print_menu(WINDOW *menu_win, int highlight) |
| { |
| int x, y, i; |
| |
| x = 2; |
| y = 2; |
| box(menu_win, 0, 0); |
| for(i = 0; i < n_choices; ++i) |
| { if(highlight == i + 1) /* High light the present choice */ |
| { wattron(menu_win, A_REVERSE); |
| mvwprintw(menu_win, y, x, "%s", choices[i]); |
| wattroff(menu_win, A_REVERSE); |
| } |
| else |
| mvwprintw(menu_win, y, x, "%s", choices[i]); |
| ++y; |
| } |
| wrefresh(menu_win); |
| } |
| </SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="MOUSE" |
| >12. Interfacing with the mouse</A |
| ></H2 |
| ><P |
| >Now that you have seen how to get keys, lets do the same thing from mouse. |
| Usually each UI allows the user to interact with both keyboard and mouse. </P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="MOUSEBASICS" |
| >12.1. The Basics</A |
| ></H3 |
| ><P |
| >Before you do any thing else, the events you want to receive have to be enabled |
| with <TT |
| CLASS="LITERAL" |
| >mousemask()</TT |
| >.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > mousemask( mmask_t newmask, /* The events you want to listen to */ |
| mmask_t *oldmask) /* The old events mask */</PRE |
| ><P |
| >The first parameter to above function is a bit mask of events you would like to |
| listen. By default, all the events are turned off. The bit mask <TT |
| CLASS="LITERAL" |
| > ALL_MOUSE_EVENTS</TT |
| > can be used to get all the events.</P |
| ><P |
| >The following are all the event masks:</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > Name Description |
| --------------------------------------------------------------------- |
| BUTTON1_PRESSED mouse button 1 down |
| BUTTON1_RELEASED mouse button 1 up |
| BUTTON1_CLICKED mouse button 1 clicked |
| BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked |
| BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked |
| BUTTON2_PRESSED mouse button 2 down |
| BUTTON2_RELEASED mouse button 2 up |
| BUTTON2_CLICKED mouse button 2 clicked |
| BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked |
| BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked |
| BUTTON3_PRESSED mouse button 3 down |
| BUTTON3_RELEASED mouse button 3 up |
| BUTTON3_CLICKED mouse button 3 clicked |
| BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked |
| BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked |
| BUTTON4_PRESSED mouse button 4 down |
| BUTTON4_RELEASED mouse button 4 up |
| BUTTON4_CLICKED mouse button 4 clicked |
| BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked |
| BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked |
| BUTTON_SHIFT shift was down during button state change |
| BUTTON_CTRL control was down during button state change |
| BUTTON_ALT alt was down during button state change |
| ALL_MOUSE_EVENTS report all button state changes |
| REPORT_MOUSE_POSITION report mouse movement</PRE |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="GETTINGEVENTS" |
| >12.2. Getting the events</A |
| ></H3 |
| ><P |
| >Once a class of mouse events have been enabled, getch() class of functions |
| return KEY_MOUSE every time some mouse event happens. Then the mouse event can |
| be retrieved with <TT |
| CLASS="LITERAL" |
| >getmouse()</TT |
| >.</P |
| ><P |
| >The code approximately looks like this:</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > MEVENT event; |
| |
| ch = getch(); |
| if(ch == KEY_MOUSE) |
| if(getmouse(&event) == OK) |
| . /* Do some thing with the event */ |
| . |
| .</PRE |
| ><P |
| > |
| getmouse() returns the event into the pointer given to it. It's a structure |
| which contains</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > typedef struct |
| { |
| short id; /* ID to distinguish multiple devices */ |
| int x, y, z; /* event coordinates */ |
| mmask_t bstate; /* button state bits */ |
| } </PRE |
| ><P |
| >The <TT |
| CLASS="LITERAL" |
| >bstate</TT |
| > is the main variable we are |
| interested in. It tells the button state of the mouse.</P |
| ><P |
| >Then with a code snippet like the following, we can find out what happened.</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > if(event.bstate & BUTTON1_PRESSED) |
| printw("Left Button Pressed");</PRE |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="MOUSETOGETHER" |
| >12.3. Putting it all Together</A |
| ></H3 |
| ><P |
| >That's pretty much interfacing with mouse. Let's create the same menu and enable |
| mouse interaction. To make things simpler, key handling is removed.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="BMOME" |
| ></A |
| ><P |
| ><B |
| >Example 11. Access the menu with mouse !!! </B |
| ></P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| ><SPAN |
| CLASS="INLINEMEDIAOBJECT" |
| >#include <ncurses.h> |
| |
| #define WIDTH 30 |
| #define HEIGHT 10 |
| |
| int startx = 0; |
| int starty = 0; |
| |
| char *choices[] = { "Choice 1", |
| "Choice 2", |
| "Choice 3", |
| "Choice 4", |
| "Exit", |
| }; |
| |
| int n_choices = sizeof(choices) / sizeof(char *); |
| |
| void print_menu(WINDOW *menu_win, int highlight); |
| void report_choice(int mouse_x, int mouse_y, int *p_choice); |
| |
| int main() |
| { int c, choice = 0; |
| WINDOW *menu_win; |
| MEVENT event; |
| |
| /* Initialize curses */ |
| initscr(); |
| clear(); |
| noecho(); |
| cbreak(); //Line buffering disabled. pass on everything |
| |
| /* Try to put the window in the middle of screen */ |
| startx = (80 - WIDTH) / 2; |
| starty = (24 - HEIGHT) / 2; |
| |
| attron(A_REVERSE); |
| mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)"); |
| refresh(); |
| attroff(A_REVERSE); |
| |
| /* Print the menu for the first time */ |
| menu_win = newwin(HEIGHT, WIDTH, starty, startx); |
| print_menu(menu_win, 1); |
| /* Get all the mouse events */ |
| mousemask(ALL_MOUSE_EVENTS, NULL); |
| |
| while(1) |
| { c = wgetch(menu_win); |
| switch(c) |
| { case KEY_MOUSE: |
| if(getmouse(&event) == OK) |
| { /* When the user clicks left mouse button */ |
| if(event.bstate & BUTTON1_PRESSED) |
| { report_choice(event.x + 1, event.y + 1, &choice); |
| if(choice == -1) //Exit chosen |
| goto end; |
| mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]); |
| refresh(); |
| } |
| } |
| print_menu(menu_win, choice); |
| break; |
| } |
| } |
| end: |
| endwin(); |
| return 0; |
| } |
| |
| |
| void print_menu(WINDOW *menu_win, int highlight) |
| { |
| int x, y, i; |
| |
| x = 2; |
| y = 2; |
| box(menu_win, 0, 0); |
| for(i = 0; i < n_choices; ++i) |
| { if(highlight == i + 1) |
| { wattron(menu_win, A_REVERSE); |
| mvwprintw(menu_win, y, x, "%s", choices[i]); |
| wattroff(menu_win, A_REVERSE); |
| } |
| else |
| mvwprintw(menu_win, y, x, "%s", choices[i]); |
| ++y; |
| } |
| wrefresh(menu_win); |
| } |
| |
| /* Report the choice according to mouse position */ |
| void report_choice(int mouse_x, int mouse_y, int *p_choice) |
| { int i,j, choice; |
| |
| i = startx + 2; |
| j = starty + 3; |
| |
| for(choice = 0; choice < n_choices; ++choice) |
| if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice])) |
| { if(choice == n_choices - 1) |
| *p_choice = -1; |
| else |
| *p_choice = choice + 1; |
| break; |
| } |
| }</SPAN |
| ></PRE |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="MISCMOUSEFUNCS" |
| >12.4. Miscellaneous Functions</A |
| ></H3 |
| ><P |
| >The functions mouse_trafo() and wmouse_trafo() can be used to convert to mouse |
| co-ordinates to screen relative co-ordinates. See curs_mouse(3X) man page for details.</P |
| ><P |
| >The mouseinterval function sets the maximum time (in thousands of a |
| second) that can elapse between press and release events in order for |
| them to be recognized as a click. This function returns the previous |
| interval value. The default is one fifth of a second.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
| ><A |
| NAME="SCREEN" |
| >13. Screen Manipulation</A |
| ></H2 |
| ><P |
| >In this section, we will look into some functions, which allow us to manage the |
| screen efficiently and to write some fancy programs. This is especially |
| important in writing games. </P |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="GETYX" |
| >13.1. getyx() functions</A |
| ></H3 |
| ><P |
| > The function <TT |
| CLASS="LITERAL" |
| >getyx()</TT |
| > can be used to find out |
| the present cursor co-ordinates. It will fill the values of x and y co-ordinates |
| in the arguments given to it. Since getyx() is a macro you don't have to pass |
| the address of the variables. It can be called as</P |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > getyx(win, y, x); |
| /* win: window pointer |
| * y, x: y, x co-ordinates will be put into this variables |
| */</PRE |
| ><P |
| >The function getparyx() gets the beginning co-ordinates of the sub window |
| relative to the main window. This is some times useful to update a sub window. |
| When designing fancy stuff like writing multiple menus, it becomes difficult to |
| store the menu positions, their first option co-ordinates etc. A simple solution |
| to this problem, is to create menus in sub windows and later find the starting |
| co-ordinates of the menus by using getparyx().</P |
| ><P |
| >The functions getbegyx() and getmaxyx() store current window's beginning and |
| maximum co-ordinates. These functions are useful in the same way as above in |
| managing the windows and sub windows effectively.</P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="SCREENDUMP" |
| >13.2. Screen Dumping</A |
| ></H3 |
| ><P |
| >While writing games, some times it becomes necessary to store the state of the |
| screen and restore it back to the same state. The function scr_dump() can be |
| used to dump the screen contents to a file given as an argument. Later it can be |
| restored by scr_restore function. These two simple functions can be used |
| effectively to maintain a fast moving game with changing scenarios. </P |
| ></DIV |
| ><DIV |
| CLASS="SECT2" |
| ><HR><H3 |
| CLASS="SECT2" |
| ><A |
| NAME="WINDOWDUMP" |
| >13.3. Window Dumping</A |
| ></H3 |
| ><P |
| >To store and restore windows, the functions |
| <TT |
| CLASS="LITERAL" |
| >putwin()</TT |
| > and <TT |
| CLASS="LITERAL" |
| >getwin()</TT |
| > can be used. <TT |
| CLASS="LITERAL" |
| >putwin()</TT |
| > puts |
| the present window state into a file, which can be later restored by |
| <TT |
| CLASS="LITERAL" |
| >getwin()</TT |
| >.</P |
| ><P |
| > |
| The function <TT |
| CLASS="LITERAL" |
| >copywin()</TT |
| > can be used to copy a |
| window completely onto another window. It takes the source and destination |
| windows as parameters and according to the rectangle specified, it copies the |
| rectangular region from source to destination window. It's last parameter |
| specifies whether to overwrite or just overlay the contents on to the |
| destination window. If this argument is true, then the copying is |
| non-destructive.</P |
| ></DIV |
| ></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><HR><H2 |
| CLASS="SECT1" |
|