1*4a1a9510SRong-En Fan<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 2*4a1a9510SRong-En Fan"http://www.w3.org/TR/html4/strict.dtd"> 3*4a1a9510SRong-En Fan 4*4a1a9510SRong-En Fan<html> 5*4a1a9510SRong-En Fan<head> 6*4a1a9510SRong-En Fan <meta name="generator" content= 7*4a1a9510SRong-En Fan "HTML Tidy for Linux (vers 25 March 2009), see www.w3.org"> 8*4a1a9510SRong-En Fan 9*4a1a9510SRong-En Fan <title>NCURSES Programming HOWTO</title> 10*4a1a9510SRong-En Fan <meta name="GENERATOR" content= 11*4a1a9510SRong-En Fan "Modular DocBook HTML Stylesheet Version 1.79"> 12*4a1a9510SRong-En Fan</head> 13*4a1a9510SRong-En Fan 14*4a1a9510SRong-En Fan<body class="ARTICLE" bgcolor="#FFFFFF" text="#000000" link= 15*4a1a9510SRong-En Fan"#0000FF" vlink="#840084" alink="#0000FF"> 16*4a1a9510SRong-En Fan <div class="ARTICLE"> 17*4a1a9510SRong-En Fan <div class="TITLEPAGE"> 18*4a1a9510SRong-En Fan <h1 class="TITLE"><a name="AEN2" id="AEN2">NCURSES 19*4a1a9510SRong-En Fan Programming HOWTO</a></h1> 20*4a1a9510SRong-En Fan 21*4a1a9510SRong-En Fan <h3 class="AUTHOR"><a name="AEN4" id="AEN4">Pradeep 22*4a1a9510SRong-En Fan Padala</a></h3> 23*4a1a9510SRong-En Fan 24*4a1a9510SRong-En Fan <div class="AFFILIATION"> 25*4a1a9510SRong-En Fan <div class="ADDRESS"> 26*4a1a9510SRong-En Fan <p class="ADDRESS"><code class="EMAIL"><<a href= 27*4a1a9510SRong-En Fan "mailto:[email protected]">[email protected]</a>></code></p> 28*4a1a9510SRong-En Fan </div> 29*4a1a9510SRong-En Fan </div> 30*4a1a9510SRong-En Fan 31*4a1a9510SRong-En Fan <p class="PUBDATE">v1.9, 2005-06-20<br></p> 32*4a1a9510SRong-En Fan 33*4a1a9510SRong-En Fan <div class="REVHISTORY"> 34*4a1a9510SRong-En Fan <table width="100%" border="0" summary="revisions"> 35*4a1a9510SRong-En Fan <tr> 36*4a1a9510SRong-En Fan <th align="left" valign="top" colspan="3"><b>Revision 37*4a1a9510SRong-En Fan History</b></th> 38*4a1a9510SRong-En Fan </tr> 39*4a1a9510SRong-En Fan 40*4a1a9510SRong-En Fan <tr> 41*4a1a9510SRong-En Fan <td align="left">Revision 1.9</td> 42*4a1a9510SRong-En Fan 43*4a1a9510SRong-En Fan <td align="left">2005-06-20</td> 44*4a1a9510SRong-En Fan 45*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 46*4a1a9510SRong-En Fan </tr> 47*4a1a9510SRong-En Fan 48*4a1a9510SRong-En Fan <tr> 49*4a1a9510SRong-En Fan <td align="left" colspan="3">The license has been 50*4a1a9510SRong-En Fan changed to the MIT-style license used by NCURSES. Note 51*4a1a9510SRong-En Fan that the programs are also re-licensed under this.</td> 52*4a1a9510SRong-En Fan </tr> 53*4a1a9510SRong-En Fan 54*4a1a9510SRong-En Fan <tr> 55*4a1a9510SRong-En Fan <td align="left">Revision 1.8</td> 56*4a1a9510SRong-En Fan 57*4a1a9510SRong-En Fan <td align="left">2005-06-17</td> 58*4a1a9510SRong-En Fan 59*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 60*4a1a9510SRong-En Fan </tr> 61*4a1a9510SRong-En Fan 62*4a1a9510SRong-En Fan <tr> 63*4a1a9510SRong-En Fan <td align="left" colspan="3">Lots of updates. Added 64*4a1a9510SRong-En Fan references and perl examples. Changes to examples. Many 65*4a1a9510SRong-En Fan grammatical and stylistic changes to the content. 66*4a1a9510SRong-En Fan Changes to NCURSES history.</td> 67*4a1a9510SRong-En Fan </tr> 68*4a1a9510SRong-En Fan 69*4a1a9510SRong-En Fan <tr> 70*4a1a9510SRong-En Fan <td align="left">Revision 1.7.1</td> 71*4a1a9510SRong-En Fan 72*4a1a9510SRong-En Fan <td align="left">2002-06-25</td> 73*4a1a9510SRong-En Fan 74*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 75*4a1a9510SRong-En Fan </tr> 76*4a1a9510SRong-En Fan 77*4a1a9510SRong-En Fan <tr> 78*4a1a9510SRong-En Fan <td align="left" colspan="3">Added a README file for 79*4a1a9510SRong-En Fan building and instructions for building from 80*4a1a9510SRong-En Fan source.</td> 81*4a1a9510SRong-En Fan </tr> 82*4a1a9510SRong-En Fan 83*4a1a9510SRong-En Fan <tr> 84*4a1a9510SRong-En Fan <td align="left">Revision 1.7</td> 85*4a1a9510SRong-En Fan 86*4a1a9510SRong-En Fan <td align="left">2002-06-25</td> 87*4a1a9510SRong-En Fan 88*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 89*4a1a9510SRong-En Fan </tr> 90*4a1a9510SRong-En Fan 91*4a1a9510SRong-En Fan <tr> 92*4a1a9510SRong-En Fan <td align="left" colspan="3">Added "Other formats" 93*4a1a9510SRong-En Fan section and made a lot of fancy changes to the 94*4a1a9510SRong-En Fan programs. Inlining of programs is gone.</td> 95*4a1a9510SRong-En Fan </tr> 96*4a1a9510SRong-En Fan 97*4a1a9510SRong-En Fan <tr> 98*4a1a9510SRong-En Fan <td align="left">Revision 1.6.1</td> 99*4a1a9510SRong-En Fan 100*4a1a9510SRong-En Fan <td align="left">2002-02-24</td> 101*4a1a9510SRong-En Fan 102*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 103*4a1a9510SRong-En Fan </tr> 104*4a1a9510SRong-En Fan 105*4a1a9510SRong-En Fan <tr> 106*4a1a9510SRong-En Fan <td align="left" colspan="3">Removed the old Changelog 107*4a1a9510SRong-En Fan section, cleaned the makefiles</td> 108*4a1a9510SRong-En Fan </tr> 109*4a1a9510SRong-En Fan 110*4a1a9510SRong-En Fan <tr> 111*4a1a9510SRong-En Fan <td align="left">Revision 1.6</td> 112*4a1a9510SRong-En Fan 113*4a1a9510SRong-En Fan <td align="left">2002-02-16</td> 114*4a1a9510SRong-En Fan 115*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 116*4a1a9510SRong-En Fan </tr> 117*4a1a9510SRong-En Fan 118*4a1a9510SRong-En Fan <tr> 119*4a1a9510SRong-En Fan <td align="left" colspan="3">Corrected a lot of 120*4a1a9510SRong-En Fan spelling mistakes, added ACS variables section</td> 121*4a1a9510SRong-En Fan </tr> 122*4a1a9510SRong-En Fan 123*4a1a9510SRong-En Fan <tr> 124*4a1a9510SRong-En Fan <td align="left">Revision 1.5</td> 125*4a1a9510SRong-En Fan 126*4a1a9510SRong-En Fan <td align="left">2002-01-05</td> 127*4a1a9510SRong-En Fan 128*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 129*4a1a9510SRong-En Fan </tr> 130*4a1a9510SRong-En Fan 131*4a1a9510SRong-En Fan <tr> 132*4a1a9510SRong-En Fan <td align="left" colspan="3">Changed structure to 133*4a1a9510SRong-En Fan present proper TOC</td> 134*4a1a9510SRong-En Fan </tr> 135*4a1a9510SRong-En Fan 136*4a1a9510SRong-En Fan <tr> 137*4a1a9510SRong-En Fan <td align="left">Revision 1.3.1</td> 138*4a1a9510SRong-En Fan 139*4a1a9510SRong-En Fan <td align="left">2001-07-26</td> 140*4a1a9510SRong-En Fan 141*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 142*4a1a9510SRong-En Fan </tr> 143*4a1a9510SRong-En Fan 144*4a1a9510SRong-En Fan <tr> 145*4a1a9510SRong-En Fan <td align="left" colspan="3">Corrected maintainers 146*4a1a9510SRong-En Fan paragraph, Corrected stable release number</td> 147*4a1a9510SRong-En Fan </tr> 148*4a1a9510SRong-En Fan 149*4a1a9510SRong-En Fan <tr> 150*4a1a9510SRong-En Fan <td align="left">Revision 1.3</td> 151*4a1a9510SRong-En Fan 152*4a1a9510SRong-En Fan <td align="left">2001-07-24</td> 153*4a1a9510SRong-En Fan 154*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 155*4a1a9510SRong-En Fan </tr> 156*4a1a9510SRong-En Fan 157*4a1a9510SRong-En Fan <tr> 158*4a1a9510SRong-En Fan <td align="left" colspan="3">Added copyright notices to 159*4a1a9510SRong-En Fan main document (LDP license) and programs (GPL), 160*4a1a9510SRong-En Fan Corrected printw_example.</td> 161*4a1a9510SRong-En Fan </tr> 162*4a1a9510SRong-En Fan 163*4a1a9510SRong-En Fan <tr> 164*4a1a9510SRong-En Fan <td align="left">Revision 1.2</td> 165*4a1a9510SRong-En Fan 166*4a1a9510SRong-En Fan <td align="left">2001-06-05</td> 167*4a1a9510SRong-En Fan 168*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 169*4a1a9510SRong-En Fan </tr> 170*4a1a9510SRong-En Fan 171*4a1a9510SRong-En Fan <tr> 172*4a1a9510SRong-En Fan <td align="left" colspan="3">Incorporated ravi's 173*4a1a9510SRong-En Fan changes. Mainly to introduction, menu, form, justforfun 174*4a1a9510SRong-En Fan sections</td> 175*4a1a9510SRong-En Fan </tr> 176*4a1a9510SRong-En Fan 177*4a1a9510SRong-En Fan <tr> 178*4a1a9510SRong-En Fan <td align="left">Revision 1.1</td> 179*4a1a9510SRong-En Fan 180*4a1a9510SRong-En Fan <td align="left">2001-05-22</td> 181*4a1a9510SRong-En Fan 182*4a1a9510SRong-En Fan <td align="left">Revised by: ppadala</td> 183*4a1a9510SRong-En Fan </tr> 184*4a1a9510SRong-En Fan 185*4a1a9510SRong-En Fan <tr> 186*4a1a9510SRong-En Fan <td align="left" colspan="3">Added "a word about 187*4a1a9510SRong-En Fan window" section, Added scanw_example.</td> 188*4a1a9510SRong-En Fan </tr> 189*4a1a9510SRong-En Fan </table> 190*4a1a9510SRong-En Fan </div> 191*4a1a9510SRong-En Fan 192*4a1a9510SRong-En Fan <div> 193*4a1a9510SRong-En Fan <div class="ABSTRACT"> 194*4a1a9510SRong-En Fan <a name="AEN67" id="AEN67"></a> 195*4a1a9510SRong-En Fan 196*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">This 197*4a1a9510SRong-En Fan document is intended to be an "All in One" guide for 198*4a1a9510SRong-En Fan programming with ncurses and its sister libraries. We 199*4a1a9510SRong-En Fan graduate from a simple "Hello World" program to more 200*4a1a9510SRong-En Fan complex form manipulation. No prior experience in ncurses 201*4a1a9510SRong-En Fan is assumed. Send comments to <a href= 202*4a1a9510SRong-En Fan "mailto:[email protected]" target="_top">this 203*4a1a9510SRong-En Fan address</a></i></span></p> 204*4a1a9510SRong-En Fan </div> 205*4a1a9510SRong-En Fan </div> 206*4a1a9510SRong-En Fan <hr> 207*4a1a9510SRong-En Fan </div> 208*4a1a9510SRong-En Fan 209*4a1a9510SRong-En Fan <div class="TOC"> 210*4a1a9510SRong-En Fan <dl> 211*4a1a9510SRong-En Fan <dt><b>Table of Contents</b></dt> 212*4a1a9510SRong-En Fan 213*4a1a9510SRong-En Fan <dt>1. <a href="#INTRO">Introduction</a></dt> 214*4a1a9510SRong-En Fan 215*4a1a9510SRong-En Fan <dd> 216*4a1a9510SRong-En Fan <dl> 217*4a1a9510SRong-En Fan <dt>1.1. <a href="#WHATIS">What is NCURSES?</a></dt> 218*4a1a9510SRong-En Fan 219*4a1a9510SRong-En Fan <dt>1.2. <a href="#WHATCANWEDO">What we can do with 220*4a1a9510SRong-En Fan NCURSES</a></dt> 221*4a1a9510SRong-En Fan 222*4a1a9510SRong-En Fan <dt>1.3. <a href="#WHERETOGETIT">Where to get 223*4a1a9510SRong-En Fan it</a></dt> 224*4a1a9510SRong-En Fan 225*4a1a9510SRong-En Fan <dt>1.4. <a href="#PURPOSE">Purpose/Scope of the 226*4a1a9510SRong-En Fan document</a></dt> 227*4a1a9510SRong-En Fan 228*4a1a9510SRong-En Fan <dt>1.5. <a href="#ABOUTPROGRAMS">About the 229*4a1a9510SRong-En Fan Programs</a></dt> 230*4a1a9510SRong-En Fan 231*4a1a9510SRong-En Fan <dt>1.6. <a href="#OTHERFORMATS">Other Formats of the 232*4a1a9510SRong-En Fan document</a></dt> 233*4a1a9510SRong-En Fan 234*4a1a9510SRong-En Fan <dd> 235*4a1a9510SRong-En Fan <dl> 236*4a1a9510SRong-En Fan <dt>1.6.1. <a href="#LISTFORMATS">Readily available 237*4a1a9510SRong-En Fan formats from tldp.org</a></dt> 238*4a1a9510SRong-En Fan 239*4a1a9510SRong-En Fan <dt>1.6.2. <a href="#BUILDSOURCE">Building from 240*4a1a9510SRong-En Fan source</a></dt> 241*4a1a9510SRong-En Fan </dl> 242*4a1a9510SRong-En Fan </dd> 243*4a1a9510SRong-En Fan 244*4a1a9510SRong-En Fan <dt>1.7. <a href="#CREDITS">Credits</a></dt> 245*4a1a9510SRong-En Fan 246*4a1a9510SRong-En Fan <dt>1.8. <a href="#WISHLIST">Wish List</a></dt> 247*4a1a9510SRong-En Fan 248*4a1a9510SRong-En Fan <dt>1.9. <a href="#COPYRIGHT">Copyright</a></dt> 249*4a1a9510SRong-En Fan </dl> 250*4a1a9510SRong-En Fan </dd> 251*4a1a9510SRong-En Fan 252*4a1a9510SRong-En Fan <dt>2. <a href="#HELLOWORLD">Hello World !!!</a></dt> 253*4a1a9510SRong-En Fan 254*4a1a9510SRong-En Fan <dd> 255*4a1a9510SRong-En Fan <dl> 256*4a1a9510SRong-En Fan <dt>2.1. <a href="#COMPILECURSES">Compiling With the 257*4a1a9510SRong-En Fan NCURSES Library</a></dt> 258*4a1a9510SRong-En Fan 259*4a1a9510SRong-En Fan <dt>2.2. <a href="#DISSECTION">Dissection</a></dt> 260*4a1a9510SRong-En Fan 261*4a1a9510SRong-En Fan <dd> 262*4a1a9510SRong-En Fan <dl> 263*4a1a9510SRong-En Fan <dt>2.2.1. <a href="#ABOUT-INITSCR">About 264*4a1a9510SRong-En Fan initscr()</a></dt> 265*4a1a9510SRong-En Fan 266*4a1a9510SRong-En Fan <dt>2.2.2. <a href="#MYST-REFRESH">The mysterious 267*4a1a9510SRong-En Fan refresh()</a></dt> 268*4a1a9510SRong-En Fan 269*4a1a9510SRong-En Fan <dt>2.2.3. <a href="#ABOUT-ENDWIN">About 270*4a1a9510SRong-En Fan endwin()</a></dt> 271*4a1a9510SRong-En Fan </dl> 272*4a1a9510SRong-En Fan </dd> 273*4a1a9510SRong-En Fan </dl> 274*4a1a9510SRong-En Fan </dd> 275*4a1a9510SRong-En Fan 276*4a1a9510SRong-En Fan <dt>3. <a href="#GORY">The Gory Details</a></dt> 277*4a1a9510SRong-En Fan 278*4a1a9510SRong-En Fan <dt>4. <a href="#INIT">Initialization</a></dt> 279*4a1a9510SRong-En Fan 280*4a1a9510SRong-En Fan <dd> 281*4a1a9510SRong-En Fan <dl> 282*4a1a9510SRong-En Fan <dt>4.1. <a href="#ABOUTINIT">Initialization 283*4a1a9510SRong-En Fan functions</a></dt> 284*4a1a9510SRong-En Fan 285*4a1a9510SRong-En Fan <dt>4.2. <a href="#RAWCBREAK">raw() and 286*4a1a9510SRong-En Fan cbreak()</a></dt> 287*4a1a9510SRong-En Fan 288*4a1a9510SRong-En Fan <dt>4.3. <a href="#ECHONOECHO">echo() and 289*4a1a9510SRong-En Fan noecho()</a></dt> 290*4a1a9510SRong-En Fan 291*4a1a9510SRong-En Fan <dt>4.4. <a href="#KEYPAD">keypad()</a></dt> 292*4a1a9510SRong-En Fan 293*4a1a9510SRong-En Fan <dt>4.5. <a href="#HALFDELAY">halfdelay()</a></dt> 294*4a1a9510SRong-En Fan 295*4a1a9510SRong-En Fan <dt>4.6. <a href="#MISCINIT">Miscellaneous 296*4a1a9510SRong-En Fan Initialization functions</a></dt> 297*4a1a9510SRong-En Fan 298*4a1a9510SRong-En Fan <dt>4.7. <a href="#INITEX">An Example</a></dt> 299*4a1a9510SRong-En Fan </dl> 300*4a1a9510SRong-En Fan </dd> 301*4a1a9510SRong-En Fan 302*4a1a9510SRong-En Fan <dt>5. <a href="#AWORDWINDOWS">A Word about 303*4a1a9510SRong-En Fan Windows</a></dt> 304*4a1a9510SRong-En Fan 305*4a1a9510SRong-En Fan <dt>6. <a href="#PRINTW">Output functions</a></dt> 306*4a1a9510SRong-En Fan 307*4a1a9510SRong-En Fan <dd> 308*4a1a9510SRong-En Fan <dl> 309*4a1a9510SRong-En Fan <dt>6.1. <a href="#ADDCHCLASS">addch() class of 310*4a1a9510SRong-En Fan functions</a></dt> 311*4a1a9510SRong-En Fan 312*4a1a9510SRong-En Fan <dt>6.2. <a href="#AEN298">mvaddch(), waddch() and 313*4a1a9510SRong-En Fan mvwaddch()</a></dt> 314*4a1a9510SRong-En Fan 315*4a1a9510SRong-En Fan <dt>6.3. <a href="#PRINTWCLASS">printw() class of 316*4a1a9510SRong-En Fan functions</a></dt> 317*4a1a9510SRong-En Fan 318*4a1a9510SRong-En Fan <dd> 319*4a1a9510SRong-En Fan <dl> 320*4a1a9510SRong-En Fan <dt>6.3.1. <a href="#PRINTWMVPRINTW">printw() and 321*4a1a9510SRong-En Fan mvprintw</a></dt> 322*4a1a9510SRong-En Fan 323*4a1a9510SRong-En Fan <dt>6.3.2. <a href="#WPRINTWMVWPRINTW">wprintw() 324*4a1a9510SRong-En Fan and mvwprintw</a></dt> 325*4a1a9510SRong-En Fan 326*4a1a9510SRong-En Fan <dt>6.3.3. <a href="#VWPRINTW">vw_printw()</a></dt> 327*4a1a9510SRong-En Fan 328*4a1a9510SRong-En Fan <dt>6.3.4. <a href="#SIMPLEPRINTWEX">A Simple 329*4a1a9510SRong-En Fan printw example</a></dt> 330*4a1a9510SRong-En Fan </dl> 331*4a1a9510SRong-En Fan </dd> 332*4a1a9510SRong-En Fan 333*4a1a9510SRong-En Fan <dt>6.4. <a href="#ADDSTRCLASS">addstr() class of 334*4a1a9510SRong-En Fan functions</a></dt> 335*4a1a9510SRong-En Fan 336*4a1a9510SRong-En Fan <dt>6.5. <a href="#ACAUTION">A word of caution</a></dt> 337*4a1a9510SRong-En Fan </dl> 338*4a1a9510SRong-En Fan </dd> 339*4a1a9510SRong-En Fan 340*4a1a9510SRong-En Fan <dt>7. <a href="#SCANW">Input functions</a></dt> 341*4a1a9510SRong-En Fan 342*4a1a9510SRong-En Fan <dd> 343*4a1a9510SRong-En Fan <dl> 344*4a1a9510SRong-En Fan <dt>7.1. <a href="#GETCHCLASS">getch() class of 345*4a1a9510SRong-En Fan functions</a></dt> 346*4a1a9510SRong-En Fan 347*4a1a9510SRong-En Fan <dt>7.2. <a href="#SCANWCLASS">scanw() class of 348*4a1a9510SRong-En Fan functions</a></dt> 349*4a1a9510SRong-En Fan 350*4a1a9510SRong-En Fan <dd> 351*4a1a9510SRong-En Fan <dl> 352*4a1a9510SRong-En Fan <dt>7.2.1. <a href="#SCANWMVSCANW">scanw() and 353*4a1a9510SRong-En Fan mvscanw</a></dt> 354*4a1a9510SRong-En Fan 355*4a1a9510SRong-En Fan <dt>7.2.2. <a href="#WSCANWMVWSCANW">wscanw() and 356*4a1a9510SRong-En Fan mvwscanw()</a></dt> 357*4a1a9510SRong-En Fan 358*4a1a9510SRong-En Fan <dt>7.2.3. <a href="#VWSCANW">vw_scanw()</a></dt> 359*4a1a9510SRong-En Fan </dl> 360*4a1a9510SRong-En Fan </dd> 361*4a1a9510SRong-En Fan 362*4a1a9510SRong-En Fan <dt>7.3. <a href="#GETSTRCLASS">getstr() class of 363*4a1a9510SRong-En Fan functions</a></dt> 364*4a1a9510SRong-En Fan 365*4a1a9510SRong-En Fan <dt>7.4. <a href="#GETSTREX">Some examples</a></dt> 366*4a1a9510SRong-En Fan </dl> 367*4a1a9510SRong-En Fan </dd> 368*4a1a9510SRong-En Fan 369*4a1a9510SRong-En Fan <dt>8. <a href="#ATTRIB">Attributes</a></dt> 370*4a1a9510SRong-En Fan 371*4a1a9510SRong-En Fan <dd> 372*4a1a9510SRong-En Fan <dl> 373*4a1a9510SRong-En Fan <dt>8.1. <a href="#ATTRIBDETAILS">The details</a></dt> 374*4a1a9510SRong-En Fan 375*4a1a9510SRong-En Fan <dt>8.2. <a href="#ATTRONVSATTRSET">attron() vs 376*4a1a9510SRong-En Fan attrset()</a></dt> 377*4a1a9510SRong-En Fan 378*4a1a9510SRong-En Fan <dt>8.3. <a href="#ATTRGET">attr_get()</a></dt> 379*4a1a9510SRong-En Fan 380*4a1a9510SRong-En Fan <dt>8.4. <a href="#ATTRFUNCS">attr_ functions</a></dt> 381*4a1a9510SRong-En Fan 382*4a1a9510SRong-En Fan <dt>8.5. <a href="#WATTRFUNCS">wattr functions</a></dt> 383*4a1a9510SRong-En Fan 384*4a1a9510SRong-En Fan <dt>8.6. <a href="#CHGAT">chgat() functions</a></dt> 385*4a1a9510SRong-En Fan </dl> 386*4a1a9510SRong-En Fan </dd> 387*4a1a9510SRong-En Fan 388*4a1a9510SRong-En Fan <dt>9. <a href="#WINDOWS">Windows</a></dt> 389*4a1a9510SRong-En Fan 390*4a1a9510SRong-En Fan <dd> 391*4a1a9510SRong-En Fan <dl> 392*4a1a9510SRong-En Fan <dt>9.1. <a href="#WINDOWBASICS">The basics</a></dt> 393*4a1a9510SRong-En Fan 394*4a1a9510SRong-En Fan <dt>9.2. <a href="#LETBEWINDOW">Let there be a Window 395*4a1a9510SRong-En Fan !!!</a></dt> 396*4a1a9510SRong-En Fan 397*4a1a9510SRong-En Fan <dt>9.3. <a href="#BORDEREXEXPL">Explanation</a></dt> 398*4a1a9510SRong-En Fan 399*4a1a9510SRong-En Fan <dt>9.4. <a href="#OTHERSTUFF">The other stuff in the 400*4a1a9510SRong-En Fan example</a></dt> 401*4a1a9510SRong-En Fan 402*4a1a9510SRong-En Fan <dt>9.5. <a href="#OTHERBORDERFUNCS">Other Border 403*4a1a9510SRong-En Fan functions</a></dt> 404*4a1a9510SRong-En Fan </dl> 405*4a1a9510SRong-En Fan </dd> 406*4a1a9510SRong-En Fan 407*4a1a9510SRong-En Fan <dt>10. <a href="#COLOR">Colors</a></dt> 408*4a1a9510SRong-En Fan 409*4a1a9510SRong-En Fan <dd> 410*4a1a9510SRong-En Fan <dl> 411*4a1a9510SRong-En Fan <dt>10.1. <a href="#COLORBASICS">The basics</a></dt> 412*4a1a9510SRong-En Fan 413*4a1a9510SRong-En Fan <dt>10.2. <a href="#CHANGECOLORDEFS">Changing Color 414*4a1a9510SRong-En Fan Definitions</a></dt> 415*4a1a9510SRong-En Fan 416*4a1a9510SRong-En Fan <dt>10.3. <a href="#COLORCONTENT">Color 417*4a1a9510SRong-En Fan Content</a></dt> 418*4a1a9510SRong-En Fan </dl> 419*4a1a9510SRong-En Fan </dd> 420*4a1a9510SRong-En Fan 421*4a1a9510SRong-En Fan <dt>11. <a href="#KEYS">Interfacing with the key 422*4a1a9510SRong-En Fan board</a></dt> 423*4a1a9510SRong-En Fan 424*4a1a9510SRong-En Fan <dd> 425*4a1a9510SRong-En Fan <dl> 426*4a1a9510SRong-En Fan <dt>11.1. <a href="#KEYSBASICS">The Basics</a></dt> 427*4a1a9510SRong-En Fan 428*4a1a9510SRong-En Fan <dt>11.2. <a href="#SIMPLEKEYEX">A Simple Key Usage 429*4a1a9510SRong-En Fan example</a></dt> 430*4a1a9510SRong-En Fan </dl> 431*4a1a9510SRong-En Fan </dd> 432*4a1a9510SRong-En Fan 433*4a1a9510SRong-En Fan <dt>12. <a href="#MOUSE">Interfacing with the 434*4a1a9510SRong-En Fan mouse</a></dt> 435*4a1a9510SRong-En Fan 436*4a1a9510SRong-En Fan <dd> 437*4a1a9510SRong-En Fan <dl> 438*4a1a9510SRong-En Fan <dt>12.1. <a href="#MOUSEBASICS">The Basics</a></dt> 439*4a1a9510SRong-En Fan 440*4a1a9510SRong-En Fan <dt>12.2. <a href="#GETTINGEVENTS">Getting the 441*4a1a9510SRong-En Fan events</a></dt> 442*4a1a9510SRong-En Fan 443*4a1a9510SRong-En Fan <dt>12.3. <a href="#MOUSETOGETHER">Putting it all 444*4a1a9510SRong-En Fan Together</a></dt> 445*4a1a9510SRong-En Fan 446*4a1a9510SRong-En Fan <dt>12.4. <a href="#MISCMOUSEFUNCS">Miscellaneous 447*4a1a9510SRong-En Fan Functions</a></dt> 448*4a1a9510SRong-En Fan </dl> 449*4a1a9510SRong-En Fan </dd> 450*4a1a9510SRong-En Fan 451*4a1a9510SRong-En Fan <dt>13. <a href="#SCREEN">Screen Manipulation</a></dt> 452*4a1a9510SRong-En Fan 453*4a1a9510SRong-En Fan <dd> 454*4a1a9510SRong-En Fan <dl> 455*4a1a9510SRong-En Fan <dt>13.1. <a href="#GETYX">getyx() functions</a></dt> 456*4a1a9510SRong-En Fan 457*4a1a9510SRong-En Fan <dt>13.2. <a href="#SCREENDUMP">Screen Dumping</a></dt> 458*4a1a9510SRong-En Fan 459*4a1a9510SRong-En Fan <dt>13.3. <a href="#WINDOWDUMP">Window Dumping</a></dt> 460*4a1a9510SRong-En Fan </dl> 461*4a1a9510SRong-En Fan </dd> 462*4a1a9510SRong-En Fan 463*4a1a9510SRong-En Fan <dt>14. <a href="#MISC">Miscellaneous features</a></dt> 464*4a1a9510SRong-En Fan 465*4a1a9510SRong-En Fan <dd> 466*4a1a9510SRong-En Fan <dl> 467*4a1a9510SRong-En Fan <dt>14.1. <a href="#CURSSET">curs_set()</a></dt> 468*4a1a9510SRong-En Fan 469*4a1a9510SRong-En Fan <dt>14.2. <a href="#TEMPLEAVE">Temporarily Leaving 470*4a1a9510SRong-En Fan Curses mode</a></dt> 471*4a1a9510SRong-En Fan 472*4a1a9510SRong-En Fan <dt>14.3. <a href="#ACSVARS">ACS_ variables</a></dt> 473*4a1a9510SRong-En Fan </dl> 474*4a1a9510SRong-En Fan </dd> 475*4a1a9510SRong-En Fan 476*4a1a9510SRong-En Fan <dt>15. <a href="#OTHERLIB">Other libraries</a></dt> 477*4a1a9510SRong-En Fan 478*4a1a9510SRong-En Fan <dt>16. <a href="#PANELS">Panel Library</a></dt> 479*4a1a9510SRong-En Fan 480*4a1a9510SRong-En Fan <dd> 481*4a1a9510SRong-En Fan <dl> 482*4a1a9510SRong-En Fan <dt>16.1. <a href="#PANELBASICS">The Basics</a></dt> 483*4a1a9510SRong-En Fan 484*4a1a9510SRong-En Fan <dt>16.2. <a href="#COMPILEPANELS">Compiling With the 485*4a1a9510SRong-En Fan Panels Library</a></dt> 486*4a1a9510SRong-En Fan 487*4a1a9510SRong-En Fan <dt>16.3. <a href="#PANELBROWSING">Panel Window 488*4a1a9510SRong-En Fan Browsing</a></dt> 489*4a1a9510SRong-En Fan 490*4a1a9510SRong-En Fan <dt>16.4. <a href="#USERPTRUSING">Using User 491*4a1a9510SRong-En Fan Pointers</a></dt> 492*4a1a9510SRong-En Fan 493*4a1a9510SRong-En Fan <dt>16.5. <a href="#PANELMOVERESIZE">Moving and 494*4a1a9510SRong-En Fan Resizing Panels</a></dt> 495*4a1a9510SRong-En Fan 496*4a1a9510SRong-En Fan <dt>16.6. <a href="#PANELSHOWHIDE">Hiding and Showing 497*4a1a9510SRong-En Fan Panels</a></dt> 498*4a1a9510SRong-En Fan 499*4a1a9510SRong-En Fan <dt>16.7. <a href="#PANELABOVE">panel_above() and 500*4a1a9510SRong-En Fan panel_below() Functions</a></dt> 501*4a1a9510SRong-En Fan </dl> 502*4a1a9510SRong-En Fan </dd> 503*4a1a9510SRong-En Fan 504*4a1a9510SRong-En Fan <dt>17. <a href="#MENUS">Menus Library</a></dt> 505*4a1a9510SRong-En Fan 506*4a1a9510SRong-En Fan <dd> 507*4a1a9510SRong-En Fan <dl> 508*4a1a9510SRong-En Fan <dt>17.1. <a href="#MENUBASICS">The Basics</a></dt> 509*4a1a9510SRong-En Fan 510*4a1a9510SRong-En Fan <dt>17.2. <a href="#COMPILEMENUS">Compiling With the 511*4a1a9510SRong-En Fan Menu Library</a></dt> 512*4a1a9510SRong-En Fan 513*4a1a9510SRong-En Fan <dt>17.3. <a href="#MENUDRIVER">Menu Driver: The work 514*4a1a9510SRong-En Fan horse of the menu system</a></dt> 515*4a1a9510SRong-En Fan 516*4a1a9510SRong-En Fan <dt>17.4. <a href="#MENUWINDOWS">Menu Windows</a></dt> 517*4a1a9510SRong-En Fan 518*4a1a9510SRong-En Fan <dt>17.5. <a href="#SCROLLMENUS">Scrolling 519*4a1a9510SRong-En Fan Menus</a></dt> 520*4a1a9510SRong-En Fan 521*4a1a9510SRong-En Fan <dt>17.6. <a href="#MULTICOLUMN">Multi Columnar 522*4a1a9510SRong-En Fan Menus</a></dt> 523*4a1a9510SRong-En Fan 524*4a1a9510SRong-En Fan <dt>17.7. <a href="#MULTIVALUEMENUS">Multi Valued 525*4a1a9510SRong-En Fan Menus</a></dt> 526*4a1a9510SRong-En Fan 527*4a1a9510SRong-En Fan <dt>17.8. <a href="#MENUOPT">Menu Options</a></dt> 528*4a1a9510SRong-En Fan 529*4a1a9510SRong-En Fan <dt>17.9. <a href="#MENUUSERPTR">The useful User 530*4a1a9510SRong-En Fan Pointer</a></dt> 531*4a1a9510SRong-En Fan </dl> 532*4a1a9510SRong-En Fan </dd> 533*4a1a9510SRong-En Fan 534*4a1a9510SRong-En Fan <dt>18. <a href="#FORMS">Forms Library</a></dt> 535*4a1a9510SRong-En Fan 536*4a1a9510SRong-En Fan <dd> 537*4a1a9510SRong-En Fan <dl> 538*4a1a9510SRong-En Fan <dt>18.1. <a href="#FORMBASICS">The Basics</a></dt> 539*4a1a9510SRong-En Fan 540*4a1a9510SRong-En Fan <dt>18.2. <a href="#COMPILEFORMS">Compiling With the 541*4a1a9510SRong-En Fan Forms Library</a></dt> 542*4a1a9510SRong-En Fan 543*4a1a9510SRong-En Fan <dt>18.3. <a href="#PLAYFIELDS">Playing with 544*4a1a9510SRong-En Fan Fields</a></dt> 545*4a1a9510SRong-En Fan 546*4a1a9510SRong-En Fan <dd> 547*4a1a9510SRong-En Fan <dl> 548*4a1a9510SRong-En Fan <dt>18.3.1. <a href="#FETCHINFO">Fetching Size and 549*4a1a9510SRong-En Fan Location of Field</a></dt> 550*4a1a9510SRong-En Fan 551*4a1a9510SRong-En Fan <dt>18.3.2. <a href="#MOVEFIELD">Moving the 552*4a1a9510SRong-En Fan field</a></dt> 553*4a1a9510SRong-En Fan 554*4a1a9510SRong-En Fan <dt>18.3.3. <a href="#JUSTIFYFIELD">Field 555*4a1a9510SRong-En Fan Justification</a></dt> 556*4a1a9510SRong-En Fan 557*4a1a9510SRong-En Fan <dt>18.3.4. <a href="#FIELDDISPATTRIB">Field 558*4a1a9510SRong-En Fan Display Attributes</a></dt> 559*4a1a9510SRong-En Fan 560*4a1a9510SRong-En Fan <dt>18.3.5. <a href="#FIELDOPTIONBITS">Field Option 561*4a1a9510SRong-En Fan Bits</a></dt> 562*4a1a9510SRong-En Fan 563*4a1a9510SRong-En Fan <dt>18.3.6. <a href="#FIELDSTATUS">Field 564*4a1a9510SRong-En Fan Status</a></dt> 565*4a1a9510SRong-En Fan 566*4a1a9510SRong-En Fan <dt>18.3.7. <a href="#FIELDUSERPTR">Field User 567*4a1a9510SRong-En Fan Pointer</a></dt> 568*4a1a9510SRong-En Fan 569*4a1a9510SRong-En Fan <dt>18.3.8. <a href= 570*4a1a9510SRong-En Fan "#VARIABLESIZEFIELDS">Variable-Sized 571*4a1a9510SRong-En Fan Fields</a></dt> 572*4a1a9510SRong-En Fan </dl> 573*4a1a9510SRong-En Fan </dd> 574*4a1a9510SRong-En Fan 575*4a1a9510SRong-En Fan <dt>18.4. <a href="#FORMWINDOWS">Form Windows</a></dt> 576*4a1a9510SRong-En Fan 577*4a1a9510SRong-En Fan <dt>18.5. <a href="#FILEDVALIDATE">Field 578*4a1a9510SRong-En Fan Validation</a></dt> 579*4a1a9510SRong-En Fan 580*4a1a9510SRong-En Fan <dt>18.6. <a href="#FORMDRIVER">Form Driver: The work 581*4a1a9510SRong-En Fan horse of the forms system</a></dt> 582*4a1a9510SRong-En Fan 583*4a1a9510SRong-En Fan <dd> 584*4a1a9510SRong-En Fan <dl> 585*4a1a9510SRong-En Fan <dt>18.6.1. <a href="#PAGENAVREQ">Page Navigation 586*4a1a9510SRong-En Fan Requests</a></dt> 587*4a1a9510SRong-En Fan 588*4a1a9510SRong-En Fan <dt>18.6.2. <a href="#INTERFIELDNAVREQ">Inter-Field 589*4a1a9510SRong-En Fan Navigation Requests</a></dt> 590*4a1a9510SRong-En Fan 591*4a1a9510SRong-En Fan <dt>18.6.3. <a href="#INTRAFIELDNAVREQ">Intra-Field 592*4a1a9510SRong-En Fan Navigation Requests</a></dt> 593*4a1a9510SRong-En Fan 594*4a1a9510SRong-En Fan <dt>18.6.4. <a href="#SCROLLREQ">Scrolling 595*4a1a9510SRong-En Fan Requests</a></dt> 596*4a1a9510SRong-En Fan 597*4a1a9510SRong-En Fan <dt>18.6.5. <a href="#EDITREQ">Editing 598*4a1a9510SRong-En Fan Requests</a></dt> 599*4a1a9510SRong-En Fan 600*4a1a9510SRong-En Fan <dt>18.6.6. <a href="#ORDERREQ">Order 601*4a1a9510SRong-En Fan Requests</a></dt> 602*4a1a9510SRong-En Fan 603*4a1a9510SRong-En Fan <dt>18.6.7. <a href="#APPLICCOMMANDS">Application 604*4a1a9510SRong-En Fan Commands</a></dt> 605*4a1a9510SRong-En Fan </dl> 606*4a1a9510SRong-En Fan </dd> 607*4a1a9510SRong-En Fan </dl> 608*4a1a9510SRong-En Fan </dd> 609*4a1a9510SRong-En Fan 610*4a1a9510SRong-En Fan <dt>19. <a href="#TOOLS">Tools and Widget 611*4a1a9510SRong-En Fan Libraries</a></dt> 612*4a1a9510SRong-En Fan 613*4a1a9510SRong-En Fan <dd> 614*4a1a9510SRong-En Fan <dl> 615*4a1a9510SRong-En Fan <dt>19.1. <a href="#CDK">CDK (Curses Development 616*4a1a9510SRong-En Fan Kit)</a></dt> 617*4a1a9510SRong-En Fan 618*4a1a9510SRong-En Fan <dd> 619*4a1a9510SRong-En Fan <dl> 620*4a1a9510SRong-En Fan <dt>19.1.1. <a href="#WIDGETLIST">Widget 621*4a1a9510SRong-En Fan List</a></dt> 622*4a1a9510SRong-En Fan 623*4a1a9510SRong-En Fan <dt>19.1.2. <a href="#CDKATTRACT">Some Attractive 624*4a1a9510SRong-En Fan Features</a></dt> 625*4a1a9510SRong-En Fan 626*4a1a9510SRong-En Fan <dt>19.1.3. <a href= 627*4a1a9510SRong-En Fan "#CDKCONCLUSION">Conclusion</a></dt> 628*4a1a9510SRong-En Fan </dl> 629*4a1a9510SRong-En Fan </dd> 630*4a1a9510SRong-En Fan 631*4a1a9510SRong-En Fan <dt>19.2. <a href="#DIALOG">The dialog</a></dt> 632*4a1a9510SRong-En Fan 633*4a1a9510SRong-En Fan <dt>19.3. <a href="#PERLCURSES">Perl Curses Modules 634*4a1a9510SRong-En Fan CURSES::FORM and CURSES::WIDGETS</a></dt> 635*4a1a9510SRong-En Fan </dl> 636*4a1a9510SRong-En Fan </dd> 637*4a1a9510SRong-En Fan 638*4a1a9510SRong-En Fan <dt>20. <a href="#JUSTFORFUN">Just For Fun !!!</a></dt> 639*4a1a9510SRong-En Fan 640*4a1a9510SRong-En Fan <dd> 641*4a1a9510SRong-En Fan <dl> 642*4a1a9510SRong-En Fan <dt>20.1. <a href="#GAMEOFLIFE">The Game of 643*4a1a9510SRong-En Fan Life</a></dt> 644*4a1a9510SRong-En Fan 645*4a1a9510SRong-En Fan <dt>20.2. <a href="#MAGIC">Magic Square</a></dt> 646*4a1a9510SRong-En Fan 647*4a1a9510SRong-En Fan <dt>20.3. <a href="#HANOI">Towers of Hanoi</a></dt> 648*4a1a9510SRong-En Fan 649*4a1a9510SRong-En Fan <dt>20.4. <a href="#QUEENS">Queens Puzzle</a></dt> 650*4a1a9510SRong-En Fan 651*4a1a9510SRong-En Fan <dt>20.5. <a href="#SHUFFLE">Shuffle</a></dt> 652*4a1a9510SRong-En Fan 653*4a1a9510SRong-En Fan <dt>20.6. <a href="#TT">Typing Tutor</a></dt> 654*4a1a9510SRong-En Fan </dl> 655*4a1a9510SRong-En Fan </dd> 656*4a1a9510SRong-En Fan 657*4a1a9510SRong-En Fan <dt>21. <a href="#REF">References</a></dt> 658*4a1a9510SRong-En Fan </dl> 659*4a1a9510SRong-En Fan </div> 660*4a1a9510SRong-En Fan 661*4a1a9510SRong-En Fan <div class="SECT1"> 662*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="INTRO" id="INTRO">1. 663*4a1a9510SRong-En Fan Introduction</a></h2> 664*4a1a9510SRong-En Fan 665*4a1a9510SRong-En Fan <p>In the olden days of teletype terminals, terminals were 666*4a1a9510SRong-En Fan away from computers and were connected to them through serial 667*4a1a9510SRong-En Fan cables. The terminals could be configured by sending a series 668*4a1a9510SRong-En Fan of bytes. All the capabilities (such as moving the cursor to 669*4a1a9510SRong-En Fan a new location, erasing part of the screen, scrolling the 670*4a1a9510SRong-En Fan screen, changing modes etc.) of terminals could be accessed 671*4a1a9510SRong-En Fan through these series of bytes. These control seeuqnces are 672*4a1a9510SRong-En Fan usually called escape sequences, because they start with an 673*4a1a9510SRong-En Fan escape(0x1B) character. Even today, with proper emulation, we 674*4a1a9510SRong-En Fan can send escape sequences to the emulator and achieve the 675*4a1a9510SRong-En Fan same effect on a terminal window.</p> 676*4a1a9510SRong-En Fan 677*4a1a9510SRong-En Fan <p>Suppose you wanted to print a line in color. Try typing 678*4a1a9510SRong-En Fan this on your console.</p> 679*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 680*4a1a9510SRong-En Fanecho "^[[0;31;40mIn Color" 681*4a1a9510SRong-En Fan</pre> 682*4a1a9510SRong-En Fan 683*4a1a9510SRong-En Fan <p>The first character is an escape character, which looks 684*4a1a9510SRong-En Fan like two characters ^ and [. To be able to print it, you have 685*4a1a9510SRong-En Fan to press CTRL+V and then the ESC key. All the others are 686*4a1a9510SRong-En Fan normal printable characters. You should be able to see the 687*4a1a9510SRong-En Fan string "In Color" in red. It stays that way and to revert 688*4a1a9510SRong-En Fan back to the original mode type this.</p> 689*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 690*4a1a9510SRong-En Fanecho "^[[0;37;40m" 691*4a1a9510SRong-En Fan</pre> 692*4a1a9510SRong-En Fan 693*4a1a9510SRong-En Fan <p>Now, what do these magic characters mean? Difficult to 694*4a1a9510SRong-En Fan comprehend? They might even be different for different 695*4a1a9510SRong-En Fan terminals. So the designers of UNIX invented a mechanism 696*4a1a9510SRong-En Fan named <tt class="LITERAL">termcap</tt>. It is a file that 697*4a1a9510SRong-En Fan lists all the capabilities of a particular terminal, along 698*4a1a9510SRong-En Fan with the escape sequences needed to achieve a particular 699*4a1a9510SRong-En Fan effect. In the later years, this was replaced by <tt class= 700*4a1a9510SRong-En Fan "LITERAL">terminfo</tt>. Without delving too much into 701*4a1a9510SRong-En Fan details, this mechanism allows application programs to query 702*4a1a9510SRong-En Fan the terminfo database and obtain the control characters to be 703*4a1a9510SRong-En Fan sent to a terminal or terminal emulator.</p> 704*4a1a9510SRong-En Fan 705*4a1a9510SRong-En Fan <div class="SECT2"> 706*4a1a9510SRong-En Fan <hr> 707*4a1a9510SRong-En Fan 708*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WHATIS" id="WHATIS">1.1. What is 709*4a1a9510SRong-En Fan NCURSES?</a></h3> 710*4a1a9510SRong-En Fan 711*4a1a9510SRong-En Fan <p>You might be wondering, what the import of all this 712*4a1a9510SRong-En Fan technical gibberish is. In the above scenario, every 713*4a1a9510SRong-En Fan application program is supposed to query the terminfo and 714*4a1a9510SRong-En Fan perform the necessary stuff (sending control characters 715*4a1a9510SRong-En Fan etc.). It soon became difficult to manage this complexity 716*4a1a9510SRong-En Fan and this gave birth to 'CURSES'. Curses is a pun on the 717*4a1a9510SRong-En Fan name "cursor optimization". The Curses library forms a 718*4a1a9510SRong-En Fan wrapper over working with raw terminal codes, and provides 719*4a1a9510SRong-En Fan highly flexible and efficient API (Application Programming 720*4a1a9510SRong-En Fan Interface). It provides functions to move the cursor, 721*4a1a9510SRong-En Fan create windows, produce colors, play with mouse etc. The 722*4a1a9510SRong-En Fan application programs need not worry about the underlying 723*4a1a9510SRong-En Fan terminal capabilities.</p> 724*4a1a9510SRong-En Fan 725*4a1a9510SRong-En Fan <p>So what is NCURSES? NCURSES is a clone of the original 726*4a1a9510SRong-En Fan System V Release 4.0 (SVr4) curses. It is a freely 727*4a1a9510SRong-En Fan distributable library, fully compatible with older version 728*4a1a9510SRong-En Fan of curses. In short, it is a library of functions that 729*4a1a9510SRong-En Fan manages an application's display on character-cell 730*4a1a9510SRong-En Fan terminals. In the remainder of the document, the terms 731*4a1a9510SRong-En Fan curses and ncurses are used interchangeably.</p> 732*4a1a9510SRong-En Fan 733*4a1a9510SRong-En Fan <p>A detailed history of NCURSES can be found in the NEWS 734*4a1a9510SRong-En Fan file from the source distribution. The current package is 735*4a1a9510SRong-En Fan maintained by <a href="mailto:[email protected]" target= 736*4a1a9510SRong-En Fan "_top">Thomas Dickey</a>. You can contact the maintainers 737*4a1a9510SRong-En Fan at <a href="mailto:[email protected]" target= 738*4a1a9510SRong-En Fan "_top">[email protected]</a>.</p> 739*4a1a9510SRong-En Fan </div> 740*4a1a9510SRong-En Fan 741*4a1a9510SRong-En Fan <div class="SECT2"> 742*4a1a9510SRong-En Fan <hr> 743*4a1a9510SRong-En Fan 744*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WHATCANWEDO" id= 745*4a1a9510SRong-En Fan "WHATCANWEDO">1.2. What we can do with NCURSES</a></h3> 746*4a1a9510SRong-En Fan 747*4a1a9510SRong-En Fan <p>NCURSES not only creates a wrapper over terminal 748*4a1a9510SRong-En Fan capabilities, but also gives a robust framework to create 749*4a1a9510SRong-En Fan nice looking UI (User Interface)s in text mode. It provides 750*4a1a9510SRong-En Fan functions to create windows etc. Its sister libraries 751*4a1a9510SRong-En Fan panel, menu and form provide an extension to the basic 752*4a1a9510SRong-En Fan curses library. These libraries usually come along with 753*4a1a9510SRong-En Fan curses. One can create applications that contain multiple 754*4a1a9510SRong-En Fan windows, menus, panels and forms. Windows can be managed 755*4a1a9510SRong-En Fan independently, can provide 'scrollability' and even can be 756*4a1a9510SRong-En Fan hidden.</p> 757*4a1a9510SRong-En Fan 758*4a1a9510SRong-En Fan <p>Menus provide the user with an easy command selection 759*4a1a9510SRong-En Fan option. Forms allow the creation of easy-to-use data entry 760*4a1a9510SRong-En Fan and display windows. Panels extend the capabilities of 761*4a1a9510SRong-En Fan ncurses to deal with overlapping and stacked windows.</p> 762*4a1a9510SRong-En Fan 763*4a1a9510SRong-En Fan <p>These are just some of the basic things we can do with 764*4a1a9510SRong-En Fan ncurses. As we move along, We will see all the capabilities 765*4a1a9510SRong-En Fan of these libraries.</p> 766*4a1a9510SRong-En Fan </div> 767*4a1a9510SRong-En Fan 768*4a1a9510SRong-En Fan <div class="SECT2"> 769*4a1a9510SRong-En Fan <hr> 770*4a1a9510SRong-En Fan 771*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WHERETOGETIT" id= 772*4a1a9510SRong-En Fan "WHERETOGETIT">1.3. Where to get it</a></h3> 773*4a1a9510SRong-En Fan 774*4a1a9510SRong-En Fan <p>All right, now that you know what you can do with 775*4a1a9510SRong-En Fan ncurses, you must be rearing to get started. NCURSES is 776*4a1a9510SRong-En Fan usually shipped with your installation. In case you don't 777*4a1a9510SRong-En Fan have the library or want to compile it on your own, read 778*4a1a9510SRong-En Fan on.</p> 779*4a1a9510SRong-En Fan 780*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">Compiling the 781*4a1a9510SRong-En Fan package</i></span></p> 782*4a1a9510SRong-En Fan 783*4a1a9510SRong-En Fan <p>NCURSES can be obtained from <a href= 784*4a1a9510SRong-En Fan "ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz" target= 785*4a1a9510SRong-En Fan "_top">ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</a> 786*4a1a9510SRong-En Fan or any of the ftp sites mentioned in <a href= 787*4a1a9510SRong-En Fan "http://www.gnu.org/order/ftp.html" target= 788*4a1a9510SRong-En Fan "_top">http://www.gnu.org/order/ftp.html</a>.</p> 789*4a1a9510SRong-En Fan 790*4a1a9510SRong-En Fan <p>Read the README and INSTALL files for details on to how 791*4a1a9510SRong-En Fan to install it. It usually involves the following 792*4a1a9510SRong-En Fan operations.</p> 793*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 794*4a1a9510SRong-En Fan tar zxvf ncurses<version>.tar.gz # unzip and untar the archive 795*4a1a9510SRong-En Fan cd ncurses<version> # cd to the directory 796*4a1a9510SRong-En Fan ./configure # configure the build according to your 797*4a1a9510SRong-En Fan # environment 798*4a1a9510SRong-En Fan make # make it 799*4a1a9510SRong-En Fan su root # become root 800*4a1a9510SRong-En Fan make install # install it 801*4a1a9510SRong-En Fan</pre> 802*4a1a9510SRong-En Fan 803*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">Using the 804*4a1a9510SRong-En Fan RPM</i></span></p> 805*4a1a9510SRong-En Fan 806*4a1a9510SRong-En Fan <p>NCURSES RPM can be found and downloaded from <a href= 807*4a1a9510SRong-En Fan "http://rpmfind.net" target="_top">http://rpmfind.net</a> . 808*4a1a9510SRong-En Fan The RPM can be installed with the following command after 809*4a1a9510SRong-En Fan becoming root.</p> 810*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 811*4a1a9510SRong-En Fan rpm -i <downloaded rpm> 812*4a1a9510SRong-En Fan</pre> 813*4a1a9510SRong-En Fan </div> 814*4a1a9510SRong-En Fan 815*4a1a9510SRong-En Fan <div class="SECT2"> 816*4a1a9510SRong-En Fan <hr> 817*4a1a9510SRong-En Fan 818*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PURPOSE" id="PURPOSE">1.4. 819*4a1a9510SRong-En Fan Purpose/Scope of the document</a></h3> 820*4a1a9510SRong-En Fan 821*4a1a9510SRong-En Fan <p>This document is intended to be a "All in One" guide for 822*4a1a9510SRong-En Fan programming with ncurses and its sister libraries. We 823*4a1a9510SRong-En Fan graduate from a simple "Hello World" program to more 824*4a1a9510SRong-En Fan complex form manipulation. No prior experience in ncurses 825*4a1a9510SRong-En Fan is assumed. The writing is informal, but a lot of detail is 826*4a1a9510SRong-En Fan provided for each of the examples.</p> 827*4a1a9510SRong-En Fan </div> 828*4a1a9510SRong-En Fan 829*4a1a9510SRong-En Fan <div class="SECT2"> 830*4a1a9510SRong-En Fan <hr> 831*4a1a9510SRong-En Fan 832*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ABOUTPROGRAMS" id= 833*4a1a9510SRong-En Fan "ABOUTPROGRAMS">1.5. About the Programs</a></h3> 834*4a1a9510SRong-En Fan 835*4a1a9510SRong-En Fan <p>All the programs in the document are available in zipped 836*4a1a9510SRong-En Fan form <a href= 837*4a1a9510SRong-En Fan "http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz" 838*4a1a9510SRong-En Fan target="_top">here</a>. Unzip and untar it. The directory 839*4a1a9510SRong-En Fan structure looks like this.</p> 840*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 841*4a1a9510SRong-En Fanncurses 842*4a1a9510SRong-En Fan | 843*4a1a9510SRong-En Fan |----> JustForFun -- just for fun programs 844*4a1a9510SRong-En Fan |----> basics -- basic programs 845*4a1a9510SRong-En Fan |----> demo -- output files go into this directory after make 846*4a1a9510SRong-En Fan | | 847*4a1a9510SRong-En Fan | |----> exe -- exe files of all example programs 848*4a1a9510SRong-En Fan |----> forms -- programs related to form library 849*4a1a9510SRong-En Fan |----> menus -- programs related to menus library 850*4a1a9510SRong-En Fan |----> panels -- programs related to panels library 851*4a1a9510SRong-En Fan |----> perl -- perl equivalents of the examples (contributed 852*4a1a9510SRong-En Fan | by Anuradha Ratnaweera) 853*4a1a9510SRong-En Fan |----> Makefile -- the top level Makefile 854*4a1a9510SRong-En Fan |----> README -- the top level README file. contains instructions 855*4a1a9510SRong-En Fan |----> COPYING -- copyright notice 856*4a1a9510SRong-En Fan</pre> 857*4a1a9510SRong-En Fan 858*4a1a9510SRong-En Fan <p>The individual directories contain the following 859*4a1a9510SRong-En Fan files.</p> 860*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 861*4a1a9510SRong-En FanDescription of files in each directory 862*4a1a9510SRong-En Fan-------------------------------------- 863*4a1a9510SRong-En FanJustForFun 864*4a1a9510SRong-En Fan | 865*4a1a9510SRong-En Fan |----> hanoi.c -- The Towers of Hanoi Solver 866*4a1a9510SRong-En Fan |----> life.c -- The Game of Life demo 867*4a1a9510SRong-En Fan |----> magic.c -- An Odd Order Magic Square builder 868*4a1a9510SRong-En Fan |----> queens.c -- The famous N-Queens Solver 869*4a1a9510SRong-En Fan |----> shuffle.c -- A fun game, if you have time to kill 870*4a1a9510SRong-En Fan |----> tt.c -- A very trivial typing tutor 871*4a1a9510SRong-En Fan 872*4a1a9510SRong-En Fan basics 873*4a1a9510SRong-En Fan | 874*4a1a9510SRong-En Fan |----> acs_vars.c -- ACS_ variables example 875*4a1a9510SRong-En Fan |----> hello_world.c -- Simple "Hello World" Program 876*4a1a9510SRong-En Fan |----> init_func_example.c -- Initialization functions example 877*4a1a9510SRong-En Fan |----> key_code.c -- Shows the scan code of the key pressed 878*4a1a9510SRong-En Fan |----> mouse_menu.c -- A menu accessible by mouse 879*4a1a9510SRong-En Fan |----> other_border.c -- Shows usage of other border functions apa 880*4a1a9510SRong-En Fan | -- rt from box() 881*4a1a9510SRong-En Fan |----> printw_example.c -- A very simple printw() example 882*4a1a9510SRong-En Fan |----> scanw_example.c -- A very simple getstr() example 883*4a1a9510SRong-En Fan |----> simple_attr.c -- A program that can print a c file with 884*4a1a9510SRong-En Fan | -- comments in attribute 885*4a1a9510SRong-En Fan |----> simple_color.c -- A simple example demonstrating colors 886*4a1a9510SRong-En Fan |----> simple_key.c -- A menu accessible with keyboard UP, DOWN 887*4a1a9510SRong-En Fan | -- arrows 888*4a1a9510SRong-En Fan |----> temp_leave.c -- Demonstrates temporarily leaving curses mode 889*4a1a9510SRong-En Fan |----> win_border.c -- Shows Creation of windows and borders 890*4a1a9510SRong-En Fan |----> with_chgat.c -- chgat() usage example 891*4a1a9510SRong-En Fan 892*4a1a9510SRong-En Fan forms 893*4a1a9510SRong-En Fan | 894*4a1a9510SRong-En Fan |----> form_attrib.c -- Usage of field attributes 895*4a1a9510SRong-En Fan |----> form_options.c -- Usage of field options 896*4a1a9510SRong-En Fan |----> form_simple.c -- A simple form example 897*4a1a9510SRong-En Fan |----> form_win.c -- Demo of windows associated with forms 898*4a1a9510SRong-En Fan 899*4a1a9510SRong-En Fan menus 900*4a1a9510SRong-En Fan | 901*4a1a9510SRong-En Fan |----> menu_attrib.c -- Usage of menu attributes 902*4a1a9510SRong-En Fan |----> menu_item_data.c -- Usage of item_name() etc.. functions 903*4a1a9510SRong-En Fan |----> menu_multi_column.c -- Creates multi columnar menus 904*4a1a9510SRong-En Fan |----> menu_scroll.c -- Demonstrates scrolling capability of menus 905*4a1a9510SRong-En Fan |----> menu_simple.c -- A simple menu accessed by arrow keys 906*4a1a9510SRong-En Fan |----> menu_toggle.c -- Creates multi valued menus and explains 907*4a1a9510SRong-En Fan | -- REQ_TOGGLE_ITEM 908*4a1a9510SRong-En Fan |----> menu_userptr.c -- Usage of user pointer 909*4a1a9510SRong-En Fan |----> menu_win.c -- Demo of windows associated with menus 910*4a1a9510SRong-En Fan 911*4a1a9510SRong-En Fan panels 912*4a1a9510SRong-En Fan | 913*4a1a9510SRong-En Fan |----> panel_browse.c -- Panel browsing through tab. Usage of user 914*4a1a9510SRong-En Fan | -- pointer 915*4a1a9510SRong-En Fan |----> panel_hide.c -- Hiding and Un hiding of panels 916*4a1a9510SRong-En Fan |----> panel_resize.c -- Moving and resizing of panels 917*4a1a9510SRong-En Fan |----> panel_simple.c -- A simple panel example 918*4a1a9510SRong-En Fan 919*4a1a9510SRong-En Fan perl 920*4a1a9510SRong-En Fan |----> 01-10.pl -- Perl equivalents of first ten example programs 921*4a1a9510SRong-En Fan</pre> 922*4a1a9510SRong-En Fan 923*4a1a9510SRong-En Fan <p>There is a top level Makefile included in the main 924*4a1a9510SRong-En Fan directory. It builds all the files and puts the 925*4a1a9510SRong-En Fan ready-to-use exes in demo/exe directory. You can also do 926*4a1a9510SRong-En Fan selective make by going into the corresponding directory. 927*4a1a9510SRong-En Fan Each directory contains a README file explaining the 928*4a1a9510SRong-En Fan purpose of each c file in the directory.</p> 929*4a1a9510SRong-En Fan 930*4a1a9510SRong-En Fan <p>For every example, I have included path name for the 931*4a1a9510SRong-En Fan file relative to the examples directory.</p> 932*4a1a9510SRong-En Fan 933*4a1a9510SRong-En Fan <p>If you prefer browsing individual programs, point your 934*4a1a9510SRong-En Fan browser to <a href= 935*4a1a9510SRong-En Fan "http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/" 936*4a1a9510SRong-En Fan target= 937*4a1a9510SRong-En Fan "_top">http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</a></p> 938*4a1a9510SRong-En Fan 939*4a1a9510SRong-En Fan <p>All the programs are released under the same license 940*4a1a9510SRong-En Fan that is used by ncurses (MIT-style). This gives you the 941*4a1a9510SRong-En Fan ability to do pretty much anything other than claiming them 942*4a1a9510SRong-En Fan as yours. Feel free to use them in your programs as 943*4a1a9510SRong-En Fan appropriate.</p> 944*4a1a9510SRong-En Fan </div> 945*4a1a9510SRong-En Fan 946*4a1a9510SRong-En Fan <div class="SECT2"> 947*4a1a9510SRong-En Fan <hr> 948*4a1a9510SRong-En Fan 949*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="OTHERFORMATS" id= 950*4a1a9510SRong-En Fan "OTHERFORMATS">1.6. Other Formats of the document</a></h3> 951*4a1a9510SRong-En Fan 952*4a1a9510SRong-En Fan <p>This howto is also availabe in various other formats on 953*4a1a9510SRong-En Fan the tldp.org site. Here are the links to other formats of 954*4a1a9510SRong-En Fan this document.</p> 955*4a1a9510SRong-En Fan 956*4a1a9510SRong-En Fan <div class="SECT3"> 957*4a1a9510SRong-En Fan <hr> 958*4a1a9510SRong-En Fan 959*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="LISTFORMATS" id= 960*4a1a9510SRong-En Fan "LISTFORMATS">1.6.1. Readily available formats from 961*4a1a9510SRong-En Fan tldp.org</a></h4> 962*4a1a9510SRong-En Fan 963*4a1a9510SRong-En Fan <ul> 964*4a1a9510SRong-En Fan <li> 965*4a1a9510SRong-En Fan <p><a href= 966*4a1a9510SRong-En Fan "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf" 967*4a1a9510SRong-En Fan target="_top">Acrobat PDF Format</a></p> 968*4a1a9510SRong-En Fan </li> 969*4a1a9510SRong-En Fan 970*4a1a9510SRong-En Fan <li> 971*4a1a9510SRong-En Fan <p><a href= 972*4a1a9510SRong-En Fan "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz" 973*4a1a9510SRong-En Fan target="_top">PostScript Format</a></p> 974*4a1a9510SRong-En Fan </li> 975*4a1a9510SRong-En Fan 976*4a1a9510SRong-En Fan <li> 977*4a1a9510SRong-En Fan <p><a href= 978*4a1a9510SRong-En Fan "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz" 979*4a1a9510SRong-En Fan target="_top">In Multiple HTML pages</a></p> 980*4a1a9510SRong-En Fan </li> 981*4a1a9510SRong-En Fan 982*4a1a9510SRong-En Fan <li> 983*4a1a9510SRong-En Fan <p><a href= 984*4a1a9510SRong-En Fan "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html" 985*4a1a9510SRong-En Fan target="_top">In One big HTML format</a></p> 986*4a1a9510SRong-En Fan </li> 987*4a1a9510SRong-En Fan </ul> 988*4a1a9510SRong-En Fan </div> 989*4a1a9510SRong-En Fan 990*4a1a9510SRong-En Fan <div class="SECT3"> 991*4a1a9510SRong-En Fan <hr> 992*4a1a9510SRong-En Fan 993*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="BUILDSOURCE" id= 994*4a1a9510SRong-En Fan "BUILDSOURCE">1.6.2. Building from source</a></h4> 995*4a1a9510SRong-En Fan 996*4a1a9510SRong-En Fan <p>If above links are broken or if you want to experiment 997*4a1a9510SRong-En Fan with sgml read on.</p> 998*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 999*4a1a9510SRong-En Fan Get both the source and the tar,gzipped programs, available at 1000*4a1a9510SRong-En Fan http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ 1001*4a1a9510SRong-En Fan NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml 1002*4a1a9510SRong-En Fan http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ 1003*4a1a9510SRong-En Fan NCURSES-HOWTO/ncurses_programs.tar.gz 1004*4a1a9510SRong-En Fan 1005*4a1a9510SRong-En Fan Unzip ncurses_programs.tar.gz with 1006*4a1a9510SRong-En Fan tar zxvf ncurses_programs.tar.gz 1007*4a1a9510SRong-En Fan 1008*4a1a9510SRong-En Fan Use jade to create various formats. For example if you just want to create 1009*4a1a9510SRong-En Fan the multiple html files, you would use 1010*4a1a9510SRong-En Fan jade -t sgml -i html -d <path to docbook html stylesheet> 1011*4a1a9510SRong-En Fan NCURSES-Programming-HOWTO.sgml 1012*4a1a9510SRong-En Fan to get pdf, first create a single html file of the HOWTO with 1013*4a1a9510SRong-En Fan jade -t sgml -i html -d <path to docbook html stylesheet> -V nochunks 1014*4a1a9510SRong-En Fan NCURSES-Programming-HOWTO.sgml > NCURSES-ONE-BIG-FILE.html 1015*4a1a9510SRong-En Fan then use htmldoc to get pdf file with 1016*4a1a9510SRong-En Fan htmldoc --size universal -t pdf --firstpage p1 -f <output file name.pdf> 1017*4a1a9510SRong-En Fan NCURSES-ONE-BIG-FILE.html 1018*4a1a9510SRong-En Fan for ps, you would use 1019*4a1a9510SRong-En Fan htmldoc --size universal -t ps --firstpage p1 -f <output file name.ps> 1020*4a1a9510SRong-En Fan NCURSES-ONE-BIG-FILE.html 1021*4a1a9510SRong-En Fan</pre> 1022*4a1a9510SRong-En Fan 1023*4a1a9510SRong-En Fan <p>See <a href= 1024*4a1a9510SRong-En Fan "http://www.tldp.org/LDP/LDP-Author-Guide/" target= 1025*4a1a9510SRong-En Fan "_top">LDP Author guide</a> for more details. If all else 1026*4a1a9510SRong-En Fan failes, mail me at <a href="[email protected]" target= 1027*4a1a9510SRong-En Fan "_top">[email protected]</a></p> 1028*4a1a9510SRong-En Fan </div> 1029*4a1a9510SRong-En Fan </div> 1030*4a1a9510SRong-En Fan 1031*4a1a9510SRong-En Fan <div class="SECT2"> 1032*4a1a9510SRong-En Fan <hr> 1033*4a1a9510SRong-En Fan 1034*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="CREDITS" id="CREDITS">1.7. 1035*4a1a9510SRong-En Fan Credits</a></h3> 1036*4a1a9510SRong-En Fan 1037*4a1a9510SRong-En Fan <p>I thank <a href="mailto:[email protected]" target= 1038*4a1a9510SRong-En Fan "_top">Sharath</a> and Emre Akbas for helping me with few 1039*4a1a9510SRong-En Fan sections. The introduction was initially written by 1040*4a1a9510SRong-En Fan sharath. I rewrote it with few excerpts taken from his 1041*4a1a9510SRong-En Fan initial work. Emre helped in writing printw and scanw 1042*4a1a9510SRong-En Fan sections.</p> 1043*4a1a9510SRong-En Fan 1044*4a1a9510SRong-En Fan <p>Perl equivalents of the example programs are contributed 1045*4a1a9510SRong-En Fan by <a href="mailto:[email protected]" target= 1046*4a1a9510SRong-En Fan "_top">Anuradha Ratnaweera</a>.</p> 1047*4a1a9510SRong-En Fan 1048*4a1a9510SRong-En Fan <p>Then comes <a href="mailto:[email protected]" 1049*4a1a9510SRong-En Fan target="_top">Ravi Parimi</a>, my dearest friend, who has 1050*4a1a9510SRong-En Fan been on this project before even one line was written. He 1051*4a1a9510SRong-En Fan constantly bombarded me with suggestions and patiently 1052*4a1a9510SRong-En Fan reviewed the whole text. He also checked each program on 1053*4a1a9510SRong-En Fan Linux and Solaris.</p> 1054*4a1a9510SRong-En Fan </div> 1055*4a1a9510SRong-En Fan 1056*4a1a9510SRong-En Fan <div class="SECT2"> 1057*4a1a9510SRong-En Fan <hr> 1058*4a1a9510SRong-En Fan 1059*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WISHLIST" id="WISHLIST">1.8. 1060*4a1a9510SRong-En Fan Wish List</a></h3> 1061*4a1a9510SRong-En Fan 1062*4a1a9510SRong-En Fan <p>This is the wish list, in the order of priority. If you 1063*4a1a9510SRong-En Fan have a wish or you want to work on completing the wish, 1064*4a1a9510SRong-En Fan mail <a href="mailto:[email protected]" target= 1065*4a1a9510SRong-En Fan "_top">me</a>.</p> 1066*4a1a9510SRong-En Fan 1067*4a1a9510SRong-En Fan <ul> 1068*4a1a9510SRong-En Fan <li> 1069*4a1a9510SRong-En Fan <p>Add examples to last parts of forms section.</p> 1070*4a1a9510SRong-En Fan </li> 1071*4a1a9510SRong-En Fan 1072*4a1a9510SRong-En Fan <li> 1073*4a1a9510SRong-En Fan <p>Prepare a Demo showing all the programs and allow 1074*4a1a9510SRong-En Fan the user to browse through description of each program. 1075*4a1a9510SRong-En Fan Let the user compile and see the program in action. A 1076*4a1a9510SRong-En Fan dialog based interface is preferred.</p> 1077*4a1a9510SRong-En Fan </li> 1078*4a1a9510SRong-En Fan 1079*4a1a9510SRong-En Fan <li> 1080*4a1a9510SRong-En Fan <p>Add debug info. _tracef, _tracemouse stuff.</p> 1081*4a1a9510SRong-En Fan </li> 1082*4a1a9510SRong-En Fan 1083*4a1a9510SRong-En Fan <li> 1084*4a1a9510SRong-En Fan <p>Accessing termcap, terminfo using functions provided 1085*4a1a9510SRong-En Fan by ncurses package.</p> 1086*4a1a9510SRong-En Fan </li> 1087*4a1a9510SRong-En Fan 1088*4a1a9510SRong-En Fan <li> 1089*4a1a9510SRong-En Fan <p>Working on two terminals simultaneously.</p> 1090*4a1a9510SRong-En Fan </li> 1091*4a1a9510SRong-En Fan 1092*4a1a9510SRong-En Fan <li> 1093*4a1a9510SRong-En Fan <p>Add more stuff to miscellaneous section.</p> 1094*4a1a9510SRong-En Fan </li> 1095*4a1a9510SRong-En Fan </ul> 1096*4a1a9510SRong-En Fan </div> 1097*4a1a9510SRong-En Fan 1098*4a1a9510SRong-En Fan <div class="SECT2"> 1099*4a1a9510SRong-En Fan <hr> 1100*4a1a9510SRong-En Fan 1101*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COPYRIGHT" id="COPYRIGHT">1.9. 1102*4a1a9510SRong-En Fan Copyright</a></h3> 1103*4a1a9510SRong-En Fan 1104*4a1a9510SRong-En Fan <p>Copyright © 2001 by Pradeep Padala.</p> 1105*4a1a9510SRong-En Fan 1106*4a1a9510SRong-En Fan <p>Permission is hereby granted, free of charge, to any 1107*4a1a9510SRong-En Fan person obtaining a copy of this software and associated 1108*4a1a9510SRong-En Fan documentation files (the "Software"), to deal in the 1109*4a1a9510SRong-En Fan Software without restriction, including without limitation 1110*4a1a9510SRong-En Fan the rights to use, copy, modify, merge, publish, 1111*4a1a9510SRong-En Fan distribute, distribute with modifications, sublicense, 1112*4a1a9510SRong-En Fan and/or sell copies of the Software, and to permit persons 1113*4a1a9510SRong-En Fan to whom the Software is furnished to do so, subject to the 1114*4a1a9510SRong-En Fan following conditions:</p> 1115*4a1a9510SRong-En Fan 1116*4a1a9510SRong-En Fan <p>The above copyright notice and this permission notice 1117*4a1a9510SRong-En Fan shall be included in all copies or substantial portions of 1118*4a1a9510SRong-En Fan the Software.</p> 1119*4a1a9510SRong-En Fan 1120*4a1a9510SRong-En Fan <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 1121*4a1a9510SRong-En Fan ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 1122*4a1a9510SRong-En Fan THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 1123*4a1a9510SRong-En Fan PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE 1124*4a1a9510SRong-En Fan COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1125*4a1a9510SRong-En Fan LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 1126*4a1a9510SRong-En Fan OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 1127*4a1a9510SRong-En Fan SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p> 1128*4a1a9510SRong-En Fan 1129*4a1a9510SRong-En Fan <p>Except as contained in this notice, the name(s) of the 1130*4a1a9510SRong-En Fan above copyright holders shall not be used in advertising or 1131*4a1a9510SRong-En Fan otherwise to promote the sale, use or other dealings in 1132*4a1a9510SRong-En Fan this Software without prior written authorization.</p> 1133*4a1a9510SRong-En Fan </div> 1134*4a1a9510SRong-En Fan </div> 1135*4a1a9510SRong-En Fan 1136*4a1a9510SRong-En Fan <div class="SECT1"> 1137*4a1a9510SRong-En Fan <hr> 1138*4a1a9510SRong-En Fan 1139*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="HELLOWORLD" id="HELLOWORLD">2. 1140*4a1a9510SRong-En Fan Hello World !!!</a></h2> 1141*4a1a9510SRong-En Fan 1142*4a1a9510SRong-En Fan <p>Welcome to the world of curses. Before we plunge into the 1143*4a1a9510SRong-En Fan library and look into its various features, let's write a 1144*4a1a9510SRong-En Fan simple program and say hello to the world.</p> 1145*4a1a9510SRong-En Fan 1146*4a1a9510SRong-En Fan <div class="SECT2"> 1147*4a1a9510SRong-En Fan <hr> 1148*4a1a9510SRong-En Fan 1149*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COMPILECURSES" id= 1150*4a1a9510SRong-En Fan "COMPILECURSES">2.1. Compiling With the NCURSES 1151*4a1a9510SRong-En Fan Library</a></h3> 1152*4a1a9510SRong-En Fan 1153*4a1a9510SRong-En Fan <p>To use ncurses library functions, you have to include 1154*4a1a9510SRong-En Fan ncurses.h in your programs. To link the program with 1155*4a1a9510SRong-En Fan ncurses the flag -lncurses should be added.</p> 1156*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1157*4a1a9510SRong-En Fan #include <ncurses.h> 1158*4a1a9510SRong-En Fan . 1159*4a1a9510SRong-En Fan . 1160*4a1a9510SRong-En Fan . 1161*4a1a9510SRong-En Fan 1162*4a1a9510SRong-En Fan compile and link: gcc <program file> -lncurses 1163*4a1a9510SRong-En Fan</pre> 1164*4a1a9510SRong-En Fan 1165*4a1a9510SRong-En Fan <div class="EXAMPLE"> 1166*4a1a9510SRong-En Fan <a name="BHW" id="BHW"></a> 1167*4a1a9510SRong-En Fan 1168*4a1a9510SRong-En Fan <p><b>Example 1. The Hello World !!! Program</b></p> 1169*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1170*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 1171*4a1a9510SRong-En Fan 1172*4a1a9510SRong-En Fanint main() 1173*4a1a9510SRong-En Fan{ 1174*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 1175*4a1a9510SRong-En Fan printw("Hello World !!!"); /* Print Hello World */ 1176*4a1a9510SRong-En Fan refresh(); /* Print it on to the real screen */ 1177*4a1a9510SRong-En Fan getch(); /* Wait for user input */ 1178*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 1179*4a1a9510SRong-En Fan 1180*4a1a9510SRong-En Fan return 0; 1181*4a1a9510SRong-En Fan}</span> 1182*4a1a9510SRong-En Fan</pre> 1183*4a1a9510SRong-En Fan </div> 1184*4a1a9510SRong-En Fan </div> 1185*4a1a9510SRong-En Fan 1186*4a1a9510SRong-En Fan <div class="SECT2"> 1187*4a1a9510SRong-En Fan <hr> 1188*4a1a9510SRong-En Fan 1189*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="DISSECTION" id="DISSECTION">2.2. 1190*4a1a9510SRong-En Fan Dissection</a></h3> 1191*4a1a9510SRong-En Fan 1192*4a1a9510SRong-En Fan <p>The above program prints "Hello World !!!" to the screen 1193*4a1a9510SRong-En Fan and exits. This program shows how to initialize curses and 1194*4a1a9510SRong-En Fan do screen manipulation and end curses mode. Let's dissect 1195*4a1a9510SRong-En Fan it line by line.</p> 1196*4a1a9510SRong-En Fan 1197*4a1a9510SRong-En Fan <div class="SECT3"> 1198*4a1a9510SRong-En Fan <hr> 1199*4a1a9510SRong-En Fan 1200*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="ABOUT-INITSCR" id= 1201*4a1a9510SRong-En Fan "ABOUT-INITSCR">2.2.1. About initscr()</a></h4> 1202*4a1a9510SRong-En Fan 1203*4a1a9510SRong-En Fan <p>The function initscr() initializes the terminal in 1204*4a1a9510SRong-En Fan curses mode. In some implementations, it clears the 1205*4a1a9510SRong-En Fan screen and presents a blank screen. To do any screen 1206*4a1a9510SRong-En Fan manipulation using curses package this has to be called 1207*4a1a9510SRong-En Fan first. This function initializes the curses system and 1208*4a1a9510SRong-En Fan allocates memory for our present window (called 1209*4a1a9510SRong-En Fan <tt class="LITERAL">stdscr</tt>) and some other 1210*4a1a9510SRong-En Fan data-structures. Under extreme cases this function might 1211*4a1a9510SRong-En Fan fail due to insufficient memory to allocate memory for 1212*4a1a9510SRong-En Fan curses library's data structures.</p> 1213*4a1a9510SRong-En Fan 1214*4a1a9510SRong-En Fan <p>After this is done, we can do a variety of 1215*4a1a9510SRong-En Fan initializations to customize our curses settings. These 1216*4a1a9510SRong-En Fan details will be explained <a href="#INIT">later</a> .</p> 1217*4a1a9510SRong-En Fan </div> 1218*4a1a9510SRong-En Fan 1219*4a1a9510SRong-En Fan <div class="SECT3"> 1220*4a1a9510SRong-En Fan <hr> 1221*4a1a9510SRong-En Fan 1222*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="MYST-REFRESH" id= 1223*4a1a9510SRong-En Fan "MYST-REFRESH">2.2.2. The mysterious refresh()</a></h4> 1224*4a1a9510SRong-En Fan 1225*4a1a9510SRong-En Fan <p>The next line printw prints the string "Hello World 1226*4a1a9510SRong-En Fan !!!" on to the screen. This function is analogous to 1227*4a1a9510SRong-En Fan normal printf in all respects except that it prints the 1228*4a1a9510SRong-En Fan data on a window called stdscr at the current (y,x) 1229*4a1a9510SRong-En Fan co-ordinates. Since our present co-ordinates are at 0,0 1230*4a1a9510SRong-En Fan the string is printed at the left hand corner of the 1231*4a1a9510SRong-En Fan window.</p> 1232*4a1a9510SRong-En Fan 1233*4a1a9510SRong-En Fan <p>This brings us to that mysterious refresh(). Well, 1234*4a1a9510SRong-En Fan when we called printw the data is actually written to an 1235*4a1a9510SRong-En Fan imaginary window, which is not updated on the screen yet. 1236*4a1a9510SRong-En Fan The job of printw is to update a few flags and data 1237*4a1a9510SRong-En Fan structures and write the data to a buffer corresponding 1238*4a1a9510SRong-En Fan to stdscr. In order to show it on the screen, we need to 1239*4a1a9510SRong-En Fan call refresh() and tell the curses system to dump the 1240*4a1a9510SRong-En Fan contents on the screen.</p> 1241*4a1a9510SRong-En Fan 1242*4a1a9510SRong-En Fan <p>The philosophy behind all this is to allow the 1243*4a1a9510SRong-En Fan programmer to do multiple updates on the imaginary screen 1244*4a1a9510SRong-En Fan or windows and do a refresh once all his screen update is 1245*4a1a9510SRong-En Fan done. refresh() checks the window and updates only the 1246*4a1a9510SRong-En Fan portion which has been changed. This improves performance 1247*4a1a9510SRong-En Fan and offers greater flexibility too. But, it is sometimes 1248*4a1a9510SRong-En Fan frustrating to beginners. A common mistake committed by 1249*4a1a9510SRong-En Fan beginners is to forget to call refresh() after they did 1250*4a1a9510SRong-En Fan some update through printw() class of functions. I still 1251*4a1a9510SRong-En Fan forget to add it sometimes :-)</p> 1252*4a1a9510SRong-En Fan </div> 1253*4a1a9510SRong-En Fan 1254*4a1a9510SRong-En Fan <div class="SECT3"> 1255*4a1a9510SRong-En Fan <hr> 1256*4a1a9510SRong-En Fan 1257*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="ABOUT-ENDWIN" id= 1258*4a1a9510SRong-En Fan "ABOUT-ENDWIN">2.2.3. About endwin()</a></h4> 1259*4a1a9510SRong-En Fan 1260*4a1a9510SRong-En Fan <p>And finally don't forget to end the curses mode. 1261*4a1a9510SRong-En Fan Otherwise your terminal might behave strangely after the 1262*4a1a9510SRong-En Fan program quits. endwin() frees the memory taken by curses 1263*4a1a9510SRong-En Fan sub-system and its data structures and puts the terminal 1264*4a1a9510SRong-En Fan in normal mode. This function must be called after you 1265*4a1a9510SRong-En Fan are done with the curses mode.</p> 1266*4a1a9510SRong-En Fan </div> 1267*4a1a9510SRong-En Fan </div> 1268*4a1a9510SRong-En Fan </div> 1269*4a1a9510SRong-En Fan 1270*4a1a9510SRong-En Fan <div class="SECT1"> 1271*4a1a9510SRong-En Fan <hr> 1272*4a1a9510SRong-En Fan 1273*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="GORY" id="GORY">3. The Gory 1274*4a1a9510SRong-En Fan Details</a></h2> 1275*4a1a9510SRong-En Fan 1276*4a1a9510SRong-En Fan <p>Now that we have seen how to write a simple curses program 1277*4a1a9510SRong-En Fan let's get into the details. There are many functions that 1278*4a1a9510SRong-En Fan help customize what you see on screen and many features which 1279*4a1a9510SRong-En Fan can be put to full use.</p> 1280*4a1a9510SRong-En Fan 1281*4a1a9510SRong-En Fan <p>Here we go...</p> 1282*4a1a9510SRong-En Fan </div> 1283*4a1a9510SRong-En Fan 1284*4a1a9510SRong-En Fan <div class="SECT1"> 1285*4a1a9510SRong-En Fan <hr> 1286*4a1a9510SRong-En Fan 1287*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="INIT" id="INIT">4. 1288*4a1a9510SRong-En Fan Initialization</a></h2> 1289*4a1a9510SRong-En Fan 1290*4a1a9510SRong-En Fan <p>We now know that to initialize curses system the function 1291*4a1a9510SRong-En Fan initscr() has to be called. There are functions which can be 1292*4a1a9510SRong-En Fan called after this initialization to customize our curses 1293*4a1a9510SRong-En Fan session. We may ask the curses system to set the terminal in 1294*4a1a9510SRong-En Fan raw mode or initialize color or initialize the mouse etc.. 1295*4a1a9510SRong-En Fan Let's discuss some of the functions that are normally called 1296*4a1a9510SRong-En Fan immediately after initscr();</p> 1297*4a1a9510SRong-En Fan 1298*4a1a9510SRong-En Fan <div class="SECT2"> 1299*4a1a9510SRong-En Fan <hr> 1300*4a1a9510SRong-En Fan 1301*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ABOUTINIT" id="ABOUTINIT">4.1. 1302*4a1a9510SRong-En Fan Initialization functions</a></h3> 1303*4a1a9510SRong-En Fan </div> 1304*4a1a9510SRong-En Fan 1305*4a1a9510SRong-En Fan <div class="SECT2"> 1306*4a1a9510SRong-En Fan <hr> 1307*4a1a9510SRong-En Fan 1308*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="RAWCBREAK" id="RAWCBREAK">4.2. 1309*4a1a9510SRong-En Fan raw() and cbreak()</a></h3> 1310*4a1a9510SRong-En Fan 1311*4a1a9510SRong-En Fan <p>Normally the terminal driver buffers the characters a 1312*4a1a9510SRong-En Fan user types until a new line or carriage return is 1313*4a1a9510SRong-En Fan encountered. But most programs require that the characters 1314*4a1a9510SRong-En Fan be available as soon as the user types them. The above two 1315*4a1a9510SRong-En Fan functions are used to disable line buffering. The 1316*4a1a9510SRong-En Fan difference between these two functions is in the way 1317*4a1a9510SRong-En Fan control characters like suspend (CTRL-Z), interrupt and 1318*4a1a9510SRong-En Fan quit (CTRL-C) are passed to the program. In the raw() mode 1319*4a1a9510SRong-En Fan these characters are directly passed to the program without 1320*4a1a9510SRong-En Fan generating a signal. In the <tt class= 1321*4a1a9510SRong-En Fan "LITERAL">cbreak()</tt> mode these control characters are 1322*4a1a9510SRong-En Fan interpreted as any other character by the terminal driver. 1323*4a1a9510SRong-En Fan I personally prefer to use raw() as I can exercise greater 1324*4a1a9510SRong-En Fan control over what the user does.</p> 1325*4a1a9510SRong-En Fan </div> 1326*4a1a9510SRong-En Fan 1327*4a1a9510SRong-En Fan <div class="SECT2"> 1328*4a1a9510SRong-En Fan <hr> 1329*4a1a9510SRong-En Fan 1330*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ECHONOECHO" id="ECHONOECHO">4.3. 1331*4a1a9510SRong-En Fan echo() and noecho()</a></h3> 1332*4a1a9510SRong-En Fan 1333*4a1a9510SRong-En Fan <p>These functions control the echoing of characters typed 1334*4a1a9510SRong-En Fan by the user to the terminal. <tt class= 1335*4a1a9510SRong-En Fan "LITERAL">noecho()</tt> switches off echoing. The reason 1336*4a1a9510SRong-En Fan you might want to do this is to gain more control over 1337*4a1a9510SRong-En Fan echoing or to suppress unnecessary echoing while taking 1338*4a1a9510SRong-En Fan input from the user through the getch() etc. functions. 1339*4a1a9510SRong-En Fan Most of the interactive programs call <tt class= 1340*4a1a9510SRong-En Fan "LITERAL">noecho()</tt> at initialization and do the 1341*4a1a9510SRong-En Fan echoing of characters in a controlled manner. It gives the 1342*4a1a9510SRong-En Fan programmer the flexibility of echoing characters at any 1343*4a1a9510SRong-En Fan place in the window without updating current (y,x) 1344*4a1a9510SRong-En Fan co-ordinates.</p> 1345*4a1a9510SRong-En Fan </div> 1346*4a1a9510SRong-En Fan 1347*4a1a9510SRong-En Fan <div class="SECT2"> 1348*4a1a9510SRong-En Fan <hr> 1349*4a1a9510SRong-En Fan 1350*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="KEYPAD" id="KEYPAD">4.4. 1351*4a1a9510SRong-En Fan keypad()</a></h3> 1352*4a1a9510SRong-En Fan 1353*4a1a9510SRong-En Fan <p>This is my favorite initialization function. It enables 1354*4a1a9510SRong-En Fan the reading of function keys like F1, F2, arrow keys etc. 1355*4a1a9510SRong-En Fan Almost every interactive program enables this, as arrow 1356*4a1a9510SRong-En Fan keys are a major part of any User Interface. Do <tt class= 1357*4a1a9510SRong-En Fan "LITERAL">keypad(stdscr, TRUE)</tt> to enable this feature 1358*4a1a9510SRong-En Fan for the regular screen (stdscr). You will learn more about 1359*4a1a9510SRong-En Fan key management in later sections of this document.</p> 1360*4a1a9510SRong-En Fan </div> 1361*4a1a9510SRong-En Fan 1362*4a1a9510SRong-En Fan <div class="SECT2"> 1363*4a1a9510SRong-En Fan <hr> 1364*4a1a9510SRong-En Fan 1365*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="HALFDELAY" id="HALFDELAY">4.5. 1366*4a1a9510SRong-En Fan halfdelay()</a></h3> 1367*4a1a9510SRong-En Fan 1368*4a1a9510SRong-En Fan <p>This function, though not used very often, is a useful 1369*4a1a9510SRong-En Fan one at times. halfdelay()is called to enable the half-delay 1370*4a1a9510SRong-En Fan mode, which is similar to the cbreak() mode in that 1371*4a1a9510SRong-En Fan characters typed are immediately available to program. 1372*4a1a9510SRong-En Fan However, it waits for 'X' tenths of a second for input and 1373*4a1a9510SRong-En Fan then returns ERR, if no input is available. 'X' is the 1374*4a1a9510SRong-En Fan timeout value passed to the function halfdelay(). This 1375*4a1a9510SRong-En Fan function is useful when you want to ask the user for input, 1376*4a1a9510SRong-En Fan and if he doesn't respond with in certain time, we can do 1377*4a1a9510SRong-En Fan some thing else. One possible example is a timeout at the 1378*4a1a9510SRong-En Fan password prompt.</p> 1379*4a1a9510SRong-En Fan </div> 1380*4a1a9510SRong-En Fan 1381*4a1a9510SRong-En Fan <div class="SECT2"> 1382*4a1a9510SRong-En Fan <hr> 1383*4a1a9510SRong-En Fan 1384*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MISCINIT" id="MISCINIT">4.6. 1385*4a1a9510SRong-En Fan Miscellaneous Initialization functions</a></h3> 1386*4a1a9510SRong-En Fan 1387*4a1a9510SRong-En Fan <p>There are few more functions which are called at 1388*4a1a9510SRong-En Fan initialization to customize curses behavior. They are not 1389*4a1a9510SRong-En Fan used as extensively as those mentioned above. Some of them 1390*4a1a9510SRong-En Fan are explained where appropriate.</p> 1391*4a1a9510SRong-En Fan </div> 1392*4a1a9510SRong-En Fan 1393*4a1a9510SRong-En Fan <div class="SECT2"> 1394*4a1a9510SRong-En Fan <hr> 1395*4a1a9510SRong-En Fan 1396*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="INITEX" id="INITEX">4.7. An 1397*4a1a9510SRong-En Fan Example</a></h3> 1398*4a1a9510SRong-En Fan 1399*4a1a9510SRong-En Fan <p>Let's write a program which will clarify the usage of 1400*4a1a9510SRong-En Fan these functions.</p> 1401*4a1a9510SRong-En Fan 1402*4a1a9510SRong-En Fan <div class="EXAMPLE"> 1403*4a1a9510SRong-En Fan <a name="BINFU" id="BINFU"></a> 1404*4a1a9510SRong-En Fan 1405*4a1a9510SRong-En Fan <p><b>Example 2. Initialization Function Usage 1406*4a1a9510SRong-En Fan example</b></p> 1407*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1408*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 1409*4a1a9510SRong-En Fan 1410*4a1a9510SRong-En Fanint main() 1411*4a1a9510SRong-En Fan{ int ch; 1412*4a1a9510SRong-En Fan 1413*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 1414*4a1a9510SRong-En Fan raw(); /* Line buffering disabled */ 1415*4a1a9510SRong-En Fan keypad(stdscr, TRUE); /* We get F1, F2 etc.. */ 1416*4a1a9510SRong-En Fan noecho(); /* Don't echo() while we do getch */ 1417*4a1a9510SRong-En Fan 1418*4a1a9510SRong-En Fan printw("Type any character to see it in bold\n"); 1419*4a1a9510SRong-En Fan ch = getch(); /* If raw() hadn't been called 1420*4a1a9510SRong-En Fan * we have to press enter before it 1421*4a1a9510SRong-En Fan * gets to the program */ 1422*4a1a9510SRong-En Fan if(ch == KEY_F(1)) /* Without keypad enabled this will */ 1423*4a1a9510SRong-En Fan printw("F1 Key pressed");/* not get to us either */ 1424*4a1a9510SRong-En Fan /* Without noecho() some ugly escape 1425*4a1a9510SRong-En Fan * charachters might have been printed 1426*4a1a9510SRong-En Fan * on screen */ 1427*4a1a9510SRong-En Fan else 1428*4a1a9510SRong-En Fan { printw("The pressed key is "); 1429*4a1a9510SRong-En Fan attron(A_BOLD); 1430*4a1a9510SRong-En Fan printw("%c", ch); 1431*4a1a9510SRong-En Fan attroff(A_BOLD); 1432*4a1a9510SRong-En Fan } 1433*4a1a9510SRong-En Fan refresh(); /* Print it on to the real screen */ 1434*4a1a9510SRong-En Fan getch(); /* Wait for user input */ 1435*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 1436*4a1a9510SRong-En Fan 1437*4a1a9510SRong-En Fan return 0; 1438*4a1a9510SRong-En Fan}</span> 1439*4a1a9510SRong-En Fan</pre> 1440*4a1a9510SRong-En Fan </div> 1441*4a1a9510SRong-En Fan 1442*4a1a9510SRong-En Fan <p>This program is self-explanatory. But I used functions 1443*4a1a9510SRong-En Fan which aren't explained yet. The function <tt class= 1444*4a1a9510SRong-En Fan "LITERAL">getch()</tt> is used to get a character from 1445*4a1a9510SRong-En Fan user. It is equivalent to normal <tt class= 1446*4a1a9510SRong-En Fan "LITERAL">getchar()</tt> except that we can disable the 1447*4a1a9510SRong-En Fan line buffering to avoid <enter> after input. Look for 1448*4a1a9510SRong-En Fan more about <tt class="LITERAL">getch()</tt>and reading keys 1449*4a1a9510SRong-En Fan in the <a href="#KEYS">key management section</a> . The 1450*4a1a9510SRong-En Fan functions attron and attroff are used to switch some 1451*4a1a9510SRong-En Fan attributes on and off respectively. In the example I used 1452*4a1a9510SRong-En Fan them to print the character in bold. These functions are 1453*4a1a9510SRong-En Fan explained in detail later.</p> 1454*4a1a9510SRong-En Fan </div> 1455*4a1a9510SRong-En Fan </div> 1456*4a1a9510SRong-En Fan 1457*4a1a9510SRong-En Fan <div class="SECT1"> 1458*4a1a9510SRong-En Fan <hr> 1459*4a1a9510SRong-En Fan 1460*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="AWORDWINDOWS" id="AWORDWINDOWS">5. 1461*4a1a9510SRong-En Fan A Word about Windows</a></h2> 1462*4a1a9510SRong-En Fan 1463*4a1a9510SRong-En Fan <p>Before we plunge into the myriad ncurses functions, let me 1464*4a1a9510SRong-En Fan clear few things about windows. Windows are explained in 1465*4a1a9510SRong-En Fan detail in following <a href="#WINDOWS">sections</a></p> 1466*4a1a9510SRong-En Fan 1467*4a1a9510SRong-En Fan <p>A Window is an imaginary screen defined by curses system. 1468*4a1a9510SRong-En Fan A window does not mean a bordered window which you usually 1469*4a1a9510SRong-En Fan see on Win9X platforms. When curses is initialized, it 1470*4a1a9510SRong-En Fan creates a default window named <tt class= 1471*4a1a9510SRong-En Fan "LITERAL">stdscr</tt> which represents your 80x25 (or the 1472*4a1a9510SRong-En Fan size of window in which you are running) screen. If you are 1473*4a1a9510SRong-En Fan doing simple tasks like printing few strings, reading input 1474*4a1a9510SRong-En Fan etc., you can safely use this single window for all of your 1475*4a1a9510SRong-En Fan purposes. You can also create windows and call functions 1476*4a1a9510SRong-En Fan which explicitly work on the specified window.</p> 1477*4a1a9510SRong-En Fan 1478*4a1a9510SRong-En Fan <p>For example, if you call</p> 1479*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1480*4a1a9510SRong-En Fan printw("Hi There !!!"); 1481*4a1a9510SRong-En Fan refresh(); 1482*4a1a9510SRong-En Fan</pre> 1483*4a1a9510SRong-En Fan 1484*4a1a9510SRong-En Fan <p>It prints the string on stdscr at the present cursor 1485*4a1a9510SRong-En Fan position. Similarly the call to refresh(), works on stdscr 1486*4a1a9510SRong-En Fan only.</p> 1487*4a1a9510SRong-En Fan 1488*4a1a9510SRong-En Fan <p>Say you have created <a href="#WINDOWS">windows</a> then 1489*4a1a9510SRong-En Fan you have to call a function with a 'w' added to the usual 1490*4a1a9510SRong-En Fan function.</p> 1491*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1492*4a1a9510SRong-En Fan wprintw(win, "Hi There !!!"); 1493*4a1a9510SRong-En Fan wrefresh(win); 1494*4a1a9510SRong-En Fan</pre> 1495*4a1a9510SRong-En Fan 1496*4a1a9510SRong-En Fan <p>As you will see in the rest of the document, naming of 1497*4a1a9510SRong-En Fan functions follow the same convention. For each function there 1498*4a1a9510SRong-En Fan usually are three more functions.</p> 1499*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1500*4a1a9510SRong-En Fan printw(string); /* Print on stdscr at present cursor position */ 1501*4a1a9510SRong-En Fan mvprintw(y, x, string);/* Move to (y, x) then print string */ 1502*4a1a9510SRong-En Fan wprintw(win, string); /* Print on window win at present cursor position */ 1503*4a1a9510SRong-En Fan /* in the window */ 1504*4a1a9510SRong-En Fan mvwprintw(win, y, x, string); /* Move to (y, x) relative to window */ 1505*4a1a9510SRong-En Fan /* co-ordinates and then print */ 1506*4a1a9510SRong-En Fan</pre> 1507*4a1a9510SRong-En Fan 1508*4a1a9510SRong-En Fan <p>Usually the w-less functions are macros which expand to 1509*4a1a9510SRong-En Fan corresponding w-function with stdscr as the window 1510*4a1a9510SRong-En Fan parameter.</p> 1511*4a1a9510SRong-En Fan </div> 1512*4a1a9510SRong-En Fan 1513*4a1a9510SRong-En Fan <div class="SECT1"> 1514*4a1a9510SRong-En Fan <hr> 1515*4a1a9510SRong-En Fan 1516*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="PRINTW" id="PRINTW">6. Output 1517*4a1a9510SRong-En Fan functions</a></h2> 1518*4a1a9510SRong-En Fan 1519*4a1a9510SRong-En Fan <p>I guess you can't wait any more to see some action. Back 1520*4a1a9510SRong-En Fan to our odyssey of curses functions. Now that curses is 1521*4a1a9510SRong-En Fan initialized, let's interact with world.</p> 1522*4a1a9510SRong-En Fan 1523*4a1a9510SRong-En Fan <p>There are three classes of functions which you can use to 1524*4a1a9510SRong-En Fan do output on screen.</p> 1525*4a1a9510SRong-En Fan 1526*4a1a9510SRong-En Fan <ol type="1"> 1527*4a1a9510SRong-En Fan <li> 1528*4a1a9510SRong-En Fan <p>addch() class: Print single character with 1529*4a1a9510SRong-En Fan attributes</p> 1530*4a1a9510SRong-En Fan </li> 1531*4a1a9510SRong-En Fan 1532*4a1a9510SRong-En Fan <li> 1533*4a1a9510SRong-En Fan <p>printw() class: Print formatted output similar to 1534*4a1a9510SRong-En Fan printf()</p> 1535*4a1a9510SRong-En Fan </li> 1536*4a1a9510SRong-En Fan 1537*4a1a9510SRong-En Fan <li> 1538*4a1a9510SRong-En Fan <p>addstr() class: Print strings</p> 1539*4a1a9510SRong-En Fan </li> 1540*4a1a9510SRong-En Fan </ol> 1541*4a1a9510SRong-En Fan 1542*4a1a9510SRong-En Fan <p>These functions can be used interchangeably and it's a 1543*4a1a9510SRong-En Fan matter of style as to which class is used. Let's see each one 1544*4a1a9510SRong-En Fan in detail.</p> 1545*4a1a9510SRong-En Fan 1546*4a1a9510SRong-En Fan <div class="SECT2"> 1547*4a1a9510SRong-En Fan <hr> 1548*4a1a9510SRong-En Fan 1549*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ADDCHCLASS" id="ADDCHCLASS">6.1. 1550*4a1a9510SRong-En Fan addch() class of functions</a></h3> 1551*4a1a9510SRong-En Fan 1552*4a1a9510SRong-En Fan <p>These functions put a single character into the current 1553*4a1a9510SRong-En Fan cursor location and advance the position of the cursor. You 1554*4a1a9510SRong-En Fan can give the character to be printed but they usually are 1555*4a1a9510SRong-En Fan used to print a character with some attributes. Attributes 1556*4a1a9510SRong-En Fan are explained in detail in later <a href= 1557*4a1a9510SRong-En Fan "#ATTRIB">sections</a> of the document. If a character is 1558*4a1a9510SRong-En Fan associated with an attribute(bold, reverse video etc.), 1559*4a1a9510SRong-En Fan when curses prints the character, it is printed in that 1560*4a1a9510SRong-En Fan attribute.</p> 1561*4a1a9510SRong-En Fan 1562*4a1a9510SRong-En Fan <p>In order to combine a character with some attributes, 1563*4a1a9510SRong-En Fan you have two options:</p> 1564*4a1a9510SRong-En Fan 1565*4a1a9510SRong-En Fan <ul> 1566*4a1a9510SRong-En Fan <li> 1567*4a1a9510SRong-En Fan <p>By OR'ing a single character with the desired 1568*4a1a9510SRong-En Fan attribute macros. These attribute macros could be found 1569*4a1a9510SRong-En Fan in the header file <tt class="LITERAL">ncurses.h</tt>. 1570*4a1a9510SRong-En Fan For example, you want to print a character ch(of type 1571*4a1a9510SRong-En Fan char) bold and underlined, you would call addch() as 1572*4a1a9510SRong-En Fan below.</p> 1573*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1574*4a1a9510SRong-En Fan addch(ch | A_BOLD | A_UNDERLINE); 1575*4a1a9510SRong-En Fan</pre> 1576*4a1a9510SRong-En Fan </li> 1577*4a1a9510SRong-En Fan 1578*4a1a9510SRong-En Fan <li> 1579*4a1a9510SRong-En Fan <p>By using functions like <tt class= 1580*4a1a9510SRong-En Fan "LITERAL">attrset(),attron(),attroff()</tt>. These 1581*4a1a9510SRong-En Fan functions are explained in the <a href= 1582*4a1a9510SRong-En Fan "#ATTRIB">Attributes</a> section. Briefly, they 1583*4a1a9510SRong-En Fan manipulate the current attributes of the given window. 1584*4a1a9510SRong-En Fan Once set, the character printed in the window are 1585*4a1a9510SRong-En Fan associated with the attributes until it is turned 1586*4a1a9510SRong-En Fan off.</p> 1587*4a1a9510SRong-En Fan </li> 1588*4a1a9510SRong-En Fan </ul> 1589*4a1a9510SRong-En Fan 1590*4a1a9510SRong-En Fan <p>Additionally, <tt class="LITERAL">curses</tt> provides 1591*4a1a9510SRong-En Fan some special characters for character-based graphics. You 1592*4a1a9510SRong-En Fan can draw tables, horizontal or vertical lines, etc. You can 1593*4a1a9510SRong-En Fan find all avaliable characters in the header file <tt class= 1594*4a1a9510SRong-En Fan "LITERAL">ncurses.h</tt>. Try looking for macros beginning 1595*4a1a9510SRong-En Fan with <tt class="LITERAL">ACS_</tt> in this file.</p> 1596*4a1a9510SRong-En Fan </div> 1597*4a1a9510SRong-En Fan 1598*4a1a9510SRong-En Fan <div class="SECT2"> 1599*4a1a9510SRong-En Fan <hr> 1600*4a1a9510SRong-En Fan 1601*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="AEN298" id="AEN298">6.2. 1602*4a1a9510SRong-En Fan mvaddch(), waddch() and mvwaddch()</a></h3> 1603*4a1a9510SRong-En Fan 1604*4a1a9510SRong-En Fan <p><tt class="LITERAL">mvaddch()</tt> is used to move the 1605*4a1a9510SRong-En Fan cursor to a given point, and then print. Thus, the 1606*4a1a9510SRong-En Fan calls:</p> 1607*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1608*4a1a9510SRong-En Fan move(row,col); /* moves the cursor to row<span class= 1609*4a1a9510SRong-En Fan"emphasis"><i class= 1610*4a1a9510SRong-En Fan"EMPHASIS">th</i></span> row and col<span class="emphasis"><i class="EMPHASIS">th</i></span> column */ 1611*4a1a9510SRong-En Fan addch(ch); 1612*4a1a9510SRong-En Fan</pre>can be replaced by 1613*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1614*4a1a9510SRong-En Fan mvaddch(row,col,ch); 1615*4a1a9510SRong-En Fan</pre> 1616*4a1a9510SRong-En Fan 1617*4a1a9510SRong-En Fan <p><tt class="LITERAL">waddch()</tt> is similar to 1618*4a1a9510SRong-En Fan <tt class="LITERAL">addch()</tt>, except that it adds a 1619*4a1a9510SRong-En Fan character into the given window. (Note that <tt class= 1620*4a1a9510SRong-En Fan "LITERAL">addch()</tt> adds a character into the window 1621*4a1a9510SRong-En Fan <tt class="LITERAL">stdscr</tt>.)</p> 1622*4a1a9510SRong-En Fan 1623*4a1a9510SRong-En Fan <p>In a similar fashion <tt class="LITERAL">mvwaddch()</tt> 1624*4a1a9510SRong-En Fan function is used to add a character into the given window 1625*4a1a9510SRong-En Fan at the given coordinates.</p> 1626*4a1a9510SRong-En Fan 1627*4a1a9510SRong-En Fan <p>Now, we are familiar with the basic output function 1628*4a1a9510SRong-En Fan <tt class="LITERAL">addch()</tt>. But, if we want to print 1629*4a1a9510SRong-En Fan a string, it would be very annoying to print it character 1630*4a1a9510SRong-En Fan by character. Fortunately, <tt class="LITERAL">ncurses</tt> 1631*4a1a9510SRong-En Fan provides <tt class="LITERAL">printf</tt><span class= 1632*4a1a9510SRong-En Fan "emphasis"><i class="EMPHASIS">-like</i></span> or 1633*4a1a9510SRong-En Fan <tt class="LITERAL">puts</tt><span class= 1634*4a1a9510SRong-En Fan "emphasis"><i class="EMPHASIS">-like</i></span> 1635*4a1a9510SRong-En Fan functions.</p> 1636*4a1a9510SRong-En Fan </div> 1637*4a1a9510SRong-En Fan 1638*4a1a9510SRong-En Fan <div class="SECT2"> 1639*4a1a9510SRong-En Fan <hr> 1640*4a1a9510SRong-En Fan 1641*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PRINTWCLASS" id= 1642*4a1a9510SRong-En Fan "PRINTWCLASS">6.3. printw() class of functions</a></h3> 1643*4a1a9510SRong-En Fan 1644*4a1a9510SRong-En Fan <p>These functions are similar to <tt class= 1645*4a1a9510SRong-En Fan "LITERAL">printf()</tt> with the added capability of 1646*4a1a9510SRong-En Fan printing at any position on the screen.</p> 1647*4a1a9510SRong-En Fan 1648*4a1a9510SRong-En Fan <div class="SECT3"> 1649*4a1a9510SRong-En Fan <hr> 1650*4a1a9510SRong-En Fan 1651*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="PRINTWMVPRINTW" id= 1652*4a1a9510SRong-En Fan "PRINTWMVPRINTW">6.3.1. printw() and mvprintw</a></h4> 1653*4a1a9510SRong-En Fan 1654*4a1a9510SRong-En Fan <p>These two functions work much like <tt class= 1655*4a1a9510SRong-En Fan "LITERAL">printf()</tt>. <tt class= 1656*4a1a9510SRong-En Fan "LITERAL">mvprintw()</tt> can be used to move the cursor 1657*4a1a9510SRong-En Fan to a position and then print. If you want to move the 1658*4a1a9510SRong-En Fan cursor first and then print using <tt class= 1659*4a1a9510SRong-En Fan "LITERAL">printw()</tt> function, use <tt class= 1660*4a1a9510SRong-En Fan "LITERAL">move()</tt> first and then use <tt class= 1661*4a1a9510SRong-En Fan "LITERAL">printw()</tt> though I see no point why one 1662*4a1a9510SRong-En Fan should avoid using <tt class="LITERAL">mvprintw()</tt>, 1663*4a1a9510SRong-En Fan you have the flexibility to manipulate.</p> 1664*4a1a9510SRong-En Fan </div> 1665*4a1a9510SRong-En Fan 1666*4a1a9510SRong-En Fan <div class="SECT3"> 1667*4a1a9510SRong-En Fan <hr> 1668*4a1a9510SRong-En Fan 1669*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="WPRINTWMVWPRINTW" id= 1670*4a1a9510SRong-En Fan "WPRINTWMVWPRINTW">6.3.2. wprintw() and 1671*4a1a9510SRong-En Fan mvwprintw</a></h4> 1672*4a1a9510SRong-En Fan 1673*4a1a9510SRong-En Fan <p>These two functions are similar to above two except 1674*4a1a9510SRong-En Fan that they print in the corresponding window given as 1675*4a1a9510SRong-En Fan argument.</p> 1676*4a1a9510SRong-En Fan </div> 1677*4a1a9510SRong-En Fan 1678*4a1a9510SRong-En Fan <div class="SECT3"> 1679*4a1a9510SRong-En Fan <hr> 1680*4a1a9510SRong-En Fan 1681*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="VWPRINTW" id="VWPRINTW">6.3.3. 1682*4a1a9510SRong-En Fan vw_printw()</a></h4> 1683*4a1a9510SRong-En Fan 1684*4a1a9510SRong-En Fan <p>This function is similar to <tt class= 1685*4a1a9510SRong-En Fan "LITERAL">vprintf()</tt>. This can be used when variable 1686*4a1a9510SRong-En Fan number of arguments are to be printed.</p> 1687*4a1a9510SRong-En Fan </div> 1688*4a1a9510SRong-En Fan 1689*4a1a9510SRong-En Fan <div class="SECT3"> 1690*4a1a9510SRong-En Fan <hr> 1691*4a1a9510SRong-En Fan 1692*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="SIMPLEPRINTWEX" id= 1693*4a1a9510SRong-En Fan "SIMPLEPRINTWEX">6.3.4. A Simple printw example</a></h4> 1694*4a1a9510SRong-En Fan 1695*4a1a9510SRong-En Fan <div class="EXAMPLE"> 1696*4a1a9510SRong-En Fan <a name="BPREX" id="BPREX"></a> 1697*4a1a9510SRong-En Fan 1698*4a1a9510SRong-En Fan <p><b>Example 3. A Simple printw example</b></p> 1699*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1700*4a1a9510SRong-En Fan<span class= 1701*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">#include <ncurses.h> /* ncurses.h includes stdio.h */ 1702*4a1a9510SRong-En Fan#include <string.h> 1703*4a1a9510SRong-En Fan 1704*4a1a9510SRong-En Fanint main() 1705*4a1a9510SRong-En Fan{ 1706*4a1a9510SRong-En Fan char mesg[]="Just a string"; /* message to be appeared on the screen */ 1707*4a1a9510SRong-En Fan int row,col; /* to store the number of rows and * 1708*4a1a9510SRong-En Fan * the number of colums of the screen */ 1709*4a1a9510SRong-En Fan initscr(); /* start the curses mode */ 1710*4a1a9510SRong-En Fan getmaxyx(stdscr,row,col); /* get the number of rows and columns */ 1711*4a1a9510SRong-En Fan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); 1712*4a1a9510SRong-En Fan /* print the message at the center of the screen */ 1713*4a1a9510SRong-En Fan mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col); 1714*4a1a9510SRong-En Fan printw("Try resizing your window(if possible) and then run this program again"); 1715*4a1a9510SRong-En Fan refresh(); 1716*4a1a9510SRong-En Fan getch(); 1717*4a1a9510SRong-En Fan endwin(); 1718*4a1a9510SRong-En Fan 1719*4a1a9510SRong-En Fan return 0; 1720*4a1a9510SRong-En Fan}</span> 1721*4a1a9510SRong-En Fan</pre> 1722*4a1a9510SRong-En Fan </div> 1723*4a1a9510SRong-En Fan 1724*4a1a9510SRong-En Fan <p>Above program demonstrates how easy it is to use 1725*4a1a9510SRong-En Fan <tt class="LITERAL">printw</tt>. You just feed the 1726*4a1a9510SRong-En Fan coordinates and the message to be appeared on the screen, 1727*4a1a9510SRong-En Fan then it does what you want.</p> 1728*4a1a9510SRong-En Fan 1729*4a1a9510SRong-En Fan <p>The above program introduces us to a new function 1730*4a1a9510SRong-En Fan <tt class="LITERAL">getmaxyx()</tt>, a macro defined in 1731*4a1a9510SRong-En Fan <tt class="LITERAL">ncurses.h</tt>. It gives the number 1732*4a1a9510SRong-En Fan of columns and the number of rows in a given window. 1733*4a1a9510SRong-En Fan <tt class="LITERAL">getmaxyx()</tt> does this by updating 1734*4a1a9510SRong-En Fan the variables given to it. Since <tt class= 1735*4a1a9510SRong-En Fan "LITERAL">getmaxyx()</tt> is not a function we don't pass 1736*4a1a9510SRong-En Fan pointers to it, we just give two integer variables.</p> 1737*4a1a9510SRong-En Fan </div> 1738*4a1a9510SRong-En Fan </div> 1739*4a1a9510SRong-En Fan 1740*4a1a9510SRong-En Fan <div class="SECT2"> 1741*4a1a9510SRong-En Fan <hr> 1742*4a1a9510SRong-En Fan 1743*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ADDSTRCLASS" id= 1744*4a1a9510SRong-En Fan "ADDSTRCLASS">6.4. addstr() class of functions</a></h3> 1745*4a1a9510SRong-En Fan 1746*4a1a9510SRong-En Fan <p><tt class="LITERAL">addstr()</tt> is used to put a 1747*4a1a9510SRong-En Fan character string into a given window. This function is 1748*4a1a9510SRong-En Fan similar to calling <tt class="LITERAL">addch()</tt> once 1749*4a1a9510SRong-En Fan for each character in a given string. This is true for all 1750*4a1a9510SRong-En Fan output functions. There are other functions from this 1751*4a1a9510SRong-En Fan family such as <tt class= 1752*4a1a9510SRong-En Fan "LITERAL">mvaddstr(),mvwaddstr()</tt> and <tt class= 1753*4a1a9510SRong-En Fan "LITERAL">waddstr()</tt>, which obey the naming convention 1754*4a1a9510SRong-En Fan of curses.(e.g. mvaddstr() is similar to the respective 1755*4a1a9510SRong-En Fan calls move() and then addstr().) Another function of this 1756*4a1a9510SRong-En Fan family is addnstr(), which takes an integer parameter(say 1757*4a1a9510SRong-En Fan n) additionally. This function puts at most n characters 1758*4a1a9510SRong-En Fan into the screen. If n is negative, then the entire string 1759*4a1a9510SRong-En Fan will be added.</p> 1760*4a1a9510SRong-En Fan </div> 1761*4a1a9510SRong-En Fan 1762*4a1a9510SRong-En Fan <div class="SECT2"> 1763*4a1a9510SRong-En Fan <hr> 1764*4a1a9510SRong-En Fan 1765*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ACAUTION" id="ACAUTION">6.5. A 1766*4a1a9510SRong-En Fan word of caution</a></h3> 1767*4a1a9510SRong-En Fan 1768*4a1a9510SRong-En Fan <p>All these functions take y co-ordinate first and then x 1769*4a1a9510SRong-En Fan in their arguments. A common mistake by beginners is to 1770*4a1a9510SRong-En Fan pass x,y in that order. If you are doing too many 1771*4a1a9510SRong-En Fan manipulations of (y,x) co-ordinates, think of dividing the 1772*4a1a9510SRong-En Fan screen into windows and manipulate each one separately. 1773*4a1a9510SRong-En Fan Windows are explained in the <a href="#WINDOWS">windows</a> 1774*4a1a9510SRong-En Fan section.</p> 1775*4a1a9510SRong-En Fan </div> 1776*4a1a9510SRong-En Fan </div> 1777*4a1a9510SRong-En Fan 1778*4a1a9510SRong-En Fan <div class="SECT1"> 1779*4a1a9510SRong-En Fan <hr> 1780*4a1a9510SRong-En Fan 1781*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="SCANW" id="SCANW">7. Input 1782*4a1a9510SRong-En Fan functions</a></h2> 1783*4a1a9510SRong-En Fan 1784*4a1a9510SRong-En Fan <p>Well, printing without taking input, is boring. Let's see 1785*4a1a9510SRong-En Fan functions which allow us to get input from user. These 1786*4a1a9510SRong-En Fan functions also can be divided into three categories.</p> 1787*4a1a9510SRong-En Fan 1788*4a1a9510SRong-En Fan <ol type="1"> 1789*4a1a9510SRong-En Fan <li> 1790*4a1a9510SRong-En Fan <p>getch() class: Get a character</p> 1791*4a1a9510SRong-En Fan </li> 1792*4a1a9510SRong-En Fan 1793*4a1a9510SRong-En Fan <li> 1794*4a1a9510SRong-En Fan <p>scanw() class: Get formatted input</p> 1795*4a1a9510SRong-En Fan </li> 1796*4a1a9510SRong-En Fan 1797*4a1a9510SRong-En Fan <li> 1798*4a1a9510SRong-En Fan <p>getstr() class: Get strings</p> 1799*4a1a9510SRong-En Fan </li> 1800*4a1a9510SRong-En Fan </ol> 1801*4a1a9510SRong-En Fan 1802*4a1a9510SRong-En Fan <div class="SECT2"> 1803*4a1a9510SRong-En Fan <hr> 1804*4a1a9510SRong-En Fan 1805*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="GETCHCLASS" id="GETCHCLASS">7.1. 1806*4a1a9510SRong-En Fan getch() class of functions</a></h3> 1807*4a1a9510SRong-En Fan 1808*4a1a9510SRong-En Fan <p>These functions read a single character from the 1809*4a1a9510SRong-En Fan terminal. But there are several subtle facts to consider. 1810*4a1a9510SRong-En Fan For example if you don't use the function cbreak(), curses 1811*4a1a9510SRong-En Fan will not read your input characters contiguously but will 1812*4a1a9510SRong-En Fan begin read them only after a new line or an EOF is 1813*4a1a9510SRong-En Fan encountered. In order to avoid this, the cbreak() function 1814*4a1a9510SRong-En Fan must used so that characters are immediately available to 1815*4a1a9510SRong-En Fan your program. Another widely used function is noecho(). As 1816*4a1a9510SRong-En Fan the name suggests, when this function is set (used), the 1817*4a1a9510SRong-En Fan characters that are keyed in by the user will not show up 1818*4a1a9510SRong-En Fan on the screen. The two functions cbreak() and noecho() are 1819*4a1a9510SRong-En Fan typical examples of key management. Functions of this genre 1820*4a1a9510SRong-En Fan are explained in the <a href="#KEYS">key management 1821*4a1a9510SRong-En Fan section</a> .</p> 1822*4a1a9510SRong-En Fan </div> 1823*4a1a9510SRong-En Fan 1824*4a1a9510SRong-En Fan <div class="SECT2"> 1825*4a1a9510SRong-En Fan <hr> 1826*4a1a9510SRong-En Fan 1827*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="SCANWCLASS" id="SCANWCLASS">7.2. 1828*4a1a9510SRong-En Fan scanw() class of functions</a></h3> 1829*4a1a9510SRong-En Fan 1830*4a1a9510SRong-En Fan <p>These functions are similar to <tt class= 1831*4a1a9510SRong-En Fan "LITERAL">scanf()</tt> with the added capability of getting 1832*4a1a9510SRong-En Fan the input from any location on the screen.</p> 1833*4a1a9510SRong-En Fan 1834*4a1a9510SRong-En Fan <div class="SECT3"> 1835*4a1a9510SRong-En Fan <hr> 1836*4a1a9510SRong-En Fan 1837*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="SCANWMVSCANW" id= 1838*4a1a9510SRong-En Fan "SCANWMVSCANW">7.2.1. scanw() and mvscanw</a></h4> 1839*4a1a9510SRong-En Fan 1840*4a1a9510SRong-En Fan <p>The usage of these functions is similar to that of 1841*4a1a9510SRong-En Fan <tt class="LITERAL">sscanf()</tt>, where the line to be 1842*4a1a9510SRong-En Fan scanned is provided by <tt class="LITERAL">wgetstr()</tt> 1843*4a1a9510SRong-En Fan function. That is, these functions call to <tt class= 1844*4a1a9510SRong-En Fan "LITERAL">wgetstr()</tt> function(explained below) and 1845*4a1a9510SRong-En Fan uses the resulting line for a scan.</p> 1846*4a1a9510SRong-En Fan </div> 1847*4a1a9510SRong-En Fan 1848*4a1a9510SRong-En Fan <div class="SECT3"> 1849*4a1a9510SRong-En Fan <hr> 1850*4a1a9510SRong-En Fan 1851*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="WSCANWMVWSCANW" id= 1852*4a1a9510SRong-En Fan "WSCANWMVWSCANW">7.2.2. wscanw() and mvwscanw()</a></h4> 1853*4a1a9510SRong-En Fan 1854*4a1a9510SRong-En Fan <p>These are similar to above two functions except that 1855*4a1a9510SRong-En Fan they read from a window, which is supplied as one of the 1856*4a1a9510SRong-En Fan arguments to these functions.</p> 1857*4a1a9510SRong-En Fan </div> 1858*4a1a9510SRong-En Fan 1859*4a1a9510SRong-En Fan <div class="SECT3"> 1860*4a1a9510SRong-En Fan <hr> 1861*4a1a9510SRong-En Fan 1862*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="VWSCANW" id="VWSCANW">7.2.3. 1863*4a1a9510SRong-En Fan vw_scanw()</a></h4> 1864*4a1a9510SRong-En Fan 1865*4a1a9510SRong-En Fan <p>This function is similar to <tt class= 1866*4a1a9510SRong-En Fan "LITERAL">vscanf()</tt>. This can be used when a variable 1867*4a1a9510SRong-En Fan number of arguments are to be scanned.</p> 1868*4a1a9510SRong-En Fan </div> 1869*4a1a9510SRong-En Fan </div> 1870*4a1a9510SRong-En Fan 1871*4a1a9510SRong-En Fan <div class="SECT2"> 1872*4a1a9510SRong-En Fan <hr> 1873*4a1a9510SRong-En Fan 1874*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="GETSTRCLASS" id= 1875*4a1a9510SRong-En Fan "GETSTRCLASS">7.3. getstr() class of functions</a></h3> 1876*4a1a9510SRong-En Fan 1877*4a1a9510SRong-En Fan <p>These functions are used to get strings from the 1878*4a1a9510SRong-En Fan terminal. In essence, this function performs the same task 1879*4a1a9510SRong-En Fan as would be achieved by a series of calls to <tt class= 1880*4a1a9510SRong-En Fan "LITERAL">getch()</tt> until a newline, carriage return, or 1881*4a1a9510SRong-En Fan end-of-file is received. The resulting string of characters 1882*4a1a9510SRong-En Fan are pointed to by <tt class="LITERAL">str</tt>, which is a 1883*4a1a9510SRong-En Fan character pointer provided by the user.</p> 1884*4a1a9510SRong-En Fan </div> 1885*4a1a9510SRong-En Fan 1886*4a1a9510SRong-En Fan <div class="SECT2"> 1887*4a1a9510SRong-En Fan <hr> 1888*4a1a9510SRong-En Fan 1889*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="GETSTREX" id="GETSTREX">7.4. 1890*4a1a9510SRong-En Fan Some examples</a></h3> 1891*4a1a9510SRong-En Fan 1892*4a1a9510SRong-En Fan <div class="EXAMPLE"> 1893*4a1a9510SRong-En Fan <a name="BSCEX" id="BSCEX"></a> 1894*4a1a9510SRong-En Fan 1895*4a1a9510SRong-En Fan <p><b>Example 4. A Simple scanw example</b></p> 1896*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1897*4a1a9510SRong-En Fan<span class= 1898*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">#include <ncurses.h> /* ncurses.h includes stdio.h */ 1899*4a1a9510SRong-En Fan#include <string.h> 1900*4a1a9510SRong-En Fan 1901*4a1a9510SRong-En Fanint main() 1902*4a1a9510SRong-En Fan{ 1903*4a1a9510SRong-En Fan char mesg[]="Enter a string: "; /* message to be appeared on the screen */ 1904*4a1a9510SRong-En Fan char str[80]; 1905*4a1a9510SRong-En Fan int row,col; /* to store the number of rows and * 1906*4a1a9510SRong-En Fan * the number of colums of the screen */ 1907*4a1a9510SRong-En Fan initscr(); /* start the curses mode */ 1908*4a1a9510SRong-En Fan getmaxyx(stdscr,row,col); /* get the number of rows and columns */ 1909*4a1a9510SRong-En Fan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); 1910*4a1a9510SRong-En Fan /* print the message at the center of the screen */ 1911*4a1a9510SRong-En Fan getstr(str); 1912*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "You Entered: %s", str); 1913*4a1a9510SRong-En Fan getch(); 1914*4a1a9510SRong-En Fan endwin(); 1915*4a1a9510SRong-En Fan 1916*4a1a9510SRong-En Fan return 0; 1917*4a1a9510SRong-En Fan}</span> 1918*4a1a9510SRong-En Fan</pre> 1919*4a1a9510SRong-En Fan </div> 1920*4a1a9510SRong-En Fan </div> 1921*4a1a9510SRong-En Fan </div> 1922*4a1a9510SRong-En Fan 1923*4a1a9510SRong-En Fan <div class="SECT1"> 1924*4a1a9510SRong-En Fan <hr> 1925*4a1a9510SRong-En Fan 1926*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="ATTRIB" id="ATTRIB">8. 1927*4a1a9510SRong-En Fan Attributes</a></h2> 1928*4a1a9510SRong-En Fan 1929*4a1a9510SRong-En Fan <p>We have seen an example of how attributes can be used to 1930*4a1a9510SRong-En Fan print characters with some special effects. Attributes, when 1931*4a1a9510SRong-En Fan set prudently, can present information in an easy, 1932*4a1a9510SRong-En Fan understandable manner. The following program takes a C file 1933*4a1a9510SRong-En Fan as input and prints the file with comments in bold. Scan 1934*4a1a9510SRong-En Fan through the code.</p> 1935*4a1a9510SRong-En Fan 1936*4a1a9510SRong-En Fan <div class="EXAMPLE"> 1937*4a1a9510SRong-En Fan <a name="BSIAT" id="BSIAT"></a> 1938*4a1a9510SRong-En Fan 1939*4a1a9510SRong-En Fan <p><b>Example 5. A Simple Attributes example</b></p> 1940*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 1941*4a1a9510SRong-En Fan<span class= 1942*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">/* pager functionality by Joseph Spainhour" <[email protected]> */ 1943*4a1a9510SRong-En Fan#include <ncurses.h> 1944*4a1a9510SRong-En Fan#include <stdlib.h> 1945*4a1a9510SRong-En Fan 1946*4a1a9510SRong-En Fanint main(int argc, char *argv[]) 1947*4a1a9510SRong-En Fan{ 1948*4a1a9510SRong-En Fan int ch, prev, row, col; 1949*4a1a9510SRong-En Fan prev = EOF; 1950*4a1a9510SRong-En Fan FILE *fp; 1951*4a1a9510SRong-En Fan int y, x; 1952*4a1a9510SRong-En Fan 1953*4a1a9510SRong-En Fan if(argc != 2) 1954*4a1a9510SRong-En Fan { 1955*4a1a9510SRong-En Fan printf("Usage: %s <a c file name>\n", argv[0]); 1956*4a1a9510SRong-En Fan exit(1); 1957*4a1a9510SRong-En Fan } 1958*4a1a9510SRong-En Fan fp = fopen(argv[1], "r"); 1959*4a1a9510SRong-En Fan if(fp == NULL) 1960*4a1a9510SRong-En Fan { 1961*4a1a9510SRong-En Fan perror("Cannot open input file"); 1962*4a1a9510SRong-En Fan exit(1); 1963*4a1a9510SRong-En Fan } 1964*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 1965*4a1a9510SRong-En Fan getmaxyx(stdscr, row, col); /* find the boundaries of the screeen */ 1966*4a1a9510SRong-En Fan while((ch = fgetc(fp)) != EOF) /* read the file till we reach the end */ 1967*4a1a9510SRong-En Fan { 1968*4a1a9510SRong-En Fan getyx(stdscr, y, x); /* get the current curser position */ 1969*4a1a9510SRong-En Fan if(y == (row - 1)) /* are we are at the end of the screen */ 1970*4a1a9510SRong-En Fan { 1971*4a1a9510SRong-En Fan printw("<-Press Any Key->"); /* tell the user to press a key */ 1972*4a1a9510SRong-En Fan getch(); 1973*4a1a9510SRong-En Fan clear(); /* clear the screen */ 1974*4a1a9510SRong-En Fan move(0, 0); /* start at the beginning of the screen */ 1975*4a1a9510SRong-En Fan } 1976*4a1a9510SRong-En Fan if(prev == '/' && ch == '*') /* If it is / and * then only 1977*4a1a9510SRong-En Fan * switch bold on */ 1978*4a1a9510SRong-En Fan { 1979*4a1a9510SRong-En Fan attron(A_BOLD); /* cut bold on */ 1980*4a1a9510SRong-En Fan getyx(stdscr, y, x); /* get the current curser position */ 1981*4a1a9510SRong-En Fan move(y, x - 1); /* back up one space */ 1982*4a1a9510SRong-En Fan printw("%c%c", '/', ch); /* The actual printing is done here */ 1983*4a1a9510SRong-En Fan } 1984*4a1a9510SRong-En Fan else 1985*4a1a9510SRong-En Fan printw("%c", ch); 1986*4a1a9510SRong-En Fan refresh(); 1987*4a1a9510SRong-En Fan if(prev == '*' && ch == '/') 1988*4a1a9510SRong-En Fan attroff(A_BOLD); /* Switch it off once we got * 1989*4a1a9510SRong-En Fan * and then / */ 1990*4a1a9510SRong-En Fan prev = ch; 1991*4a1a9510SRong-En Fan } 1992*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 1993*4a1a9510SRong-En Fan fclose(fp); 1994*4a1a9510SRong-En Fan return 0; 1995*4a1a9510SRong-En Fan}</span> 1996*4a1a9510SRong-En Fan</pre> 1997*4a1a9510SRong-En Fan </div> 1998*4a1a9510SRong-En Fan 1999*4a1a9510SRong-En Fan <p>Don't worry about all those initialization and other crap. 2000*4a1a9510SRong-En Fan Concentrate on the while loop. It reads each character in the 2001*4a1a9510SRong-En Fan file and searches for the pattern /*. Once it spots the 2002*4a1a9510SRong-En Fan pattern, it switches the BOLD attribute on with <tt class= 2003*4a1a9510SRong-En Fan "LITERAL">attron()</tt> . When we get the pattern */ it is 2004*4a1a9510SRong-En Fan switched off by <tt class="LITERAL">attroff()</tt> .</p> 2005*4a1a9510SRong-En Fan 2006*4a1a9510SRong-En Fan <p>The above program also introduces us to two useful 2007*4a1a9510SRong-En Fan functions <tt class="LITERAL">getyx()</tt> and <tt class= 2008*4a1a9510SRong-En Fan "LITERAL">move()</tt>. The first function gets the 2009*4a1a9510SRong-En Fan co-ordinates of the present cursor into the variables y, x. 2010*4a1a9510SRong-En Fan Since getyx() is a macro we don't have to pass pointers to 2011*4a1a9510SRong-En Fan variables. The function <tt class="LITERAL">move()</tt> moves 2012*4a1a9510SRong-En Fan the cursor to the co-ordinates given to it.</p> 2013*4a1a9510SRong-En Fan 2014*4a1a9510SRong-En Fan <p>The above program is really a simple one which doesn't do 2015*4a1a9510SRong-En Fan much. On these lines one could write a more useful program 2016*4a1a9510SRong-En Fan which reads a C file, parses it and prints it in different 2017*4a1a9510SRong-En Fan colors. One could even extend it to other languages as 2018*4a1a9510SRong-En Fan well.</p> 2019*4a1a9510SRong-En Fan 2020*4a1a9510SRong-En Fan <div class="SECT2"> 2021*4a1a9510SRong-En Fan <hr> 2022*4a1a9510SRong-En Fan 2023*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ATTRIBDETAILS" id= 2024*4a1a9510SRong-En Fan "ATTRIBDETAILS">8.1. The details</a></h3> 2025*4a1a9510SRong-En Fan 2026*4a1a9510SRong-En Fan <p>Let's get into more details of attributes. The functions 2027*4a1a9510SRong-En Fan <tt class="LITERAL">attron(), attroff(), attrset()</tt> , 2028*4a1a9510SRong-En Fan and their sister functions <tt class= 2029*4a1a9510SRong-En Fan "LITERAL">attr_get()</tt> etc.. can be used to switch 2030*4a1a9510SRong-En Fan attributes on/off , get attributes and produce a colorful 2031*4a1a9510SRong-En Fan display.</p> 2032*4a1a9510SRong-En Fan 2033*4a1a9510SRong-En Fan <p>The functions attron and attroff take a bit-mask of 2034*4a1a9510SRong-En Fan attributes and switch them on or off, respectively. The 2035*4a1a9510SRong-En Fan following video attributes, which are defined in 2036*4a1a9510SRong-En Fan <curses.h> can be passed to these functions.</p> 2037*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2038*4a1a9510SRong-En Fan 2039*4a1a9510SRong-En Fan A_NORMAL Normal display (no highlight) 2040*4a1a9510SRong-En Fan A_STANDOUT Best highlighting mode of the terminal. 2041*4a1a9510SRong-En Fan A_UNDERLINE Underlining 2042*4a1a9510SRong-En Fan A_REVERSE Reverse video 2043*4a1a9510SRong-En Fan A_BLINK Blinking 2044*4a1a9510SRong-En Fan A_DIM Half bright 2045*4a1a9510SRong-En Fan A_BOLD Extra bright or bold 2046*4a1a9510SRong-En Fan A_PROTECT Protected mode 2047*4a1a9510SRong-En Fan A_INVIS Invisible or blank mode 2048*4a1a9510SRong-En Fan A_ALTCHARSET Alternate character set 2049*4a1a9510SRong-En Fan A_CHARTEXT Bit-mask to extract a character 2050*4a1a9510SRong-En Fan COLOR_PAIR(n) Color-pair number n 2051*4a1a9510SRong-En Fan 2052*4a1a9510SRong-En Fan</pre> 2053*4a1a9510SRong-En Fan 2054*4a1a9510SRong-En Fan <p>The last one is the most colorful one :-) Colors are 2055*4a1a9510SRong-En Fan explained in the <a href="#color" target="_top">next 2056*4a1a9510SRong-En Fan sections</a>.</p> 2057*4a1a9510SRong-En Fan 2058*4a1a9510SRong-En Fan <p>We can OR(|) any number of above attributes to get a 2059*4a1a9510SRong-En Fan combined effect. If you wanted reverse video with blinking 2060*4a1a9510SRong-En Fan characters you can use</p> 2061*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2062*4a1a9510SRong-En Fan attron(A_REVERSE | A_BLINK); 2063*4a1a9510SRong-En Fan</pre> 2064*4a1a9510SRong-En Fan </div> 2065*4a1a9510SRong-En Fan 2066*4a1a9510SRong-En Fan <div class="SECT2"> 2067*4a1a9510SRong-En Fan <hr> 2068*4a1a9510SRong-En Fan 2069*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ATTRONVSATTRSET" id= 2070*4a1a9510SRong-En Fan "ATTRONVSATTRSET">8.2. attron() vs attrset()</a></h3> 2071*4a1a9510SRong-En Fan 2072*4a1a9510SRong-En Fan <p>Then what is the difference between attron() and 2073*4a1a9510SRong-En Fan attrset()? attrset sets the attributes of window whereas 2074*4a1a9510SRong-En Fan attron just switches on the attribute given to it. So 2075*4a1a9510SRong-En Fan attrset() fully overrides whatever attributes the window 2076*4a1a9510SRong-En Fan previously had and sets it to the new attribute(s). 2077*4a1a9510SRong-En Fan Similarly attroff() just switches off the attribute(s) 2078*4a1a9510SRong-En Fan given to it as an argument. This gives us the flexibility 2079*4a1a9510SRong-En Fan of managing attributes easily.But if you use them 2080*4a1a9510SRong-En Fan carelessly you may loose track of what attributes the 2081*4a1a9510SRong-En Fan window has and garble the display. This is especially true 2082*4a1a9510SRong-En Fan while managing menus with colors and highlighting. So 2083*4a1a9510SRong-En Fan decide on a consistent policy and stick to it. You can 2084*4a1a9510SRong-En Fan always use <tt class="LITERAL">standend()</tt> which is 2085*4a1a9510SRong-En Fan equivalent to <tt class="LITERAL">attrset(A_NORMAL)</tt> 2086*4a1a9510SRong-En Fan which turns off all attributes and brings you to normal 2087*4a1a9510SRong-En Fan mode.</p> 2088*4a1a9510SRong-En Fan </div> 2089*4a1a9510SRong-En Fan 2090*4a1a9510SRong-En Fan <div class="SECT2"> 2091*4a1a9510SRong-En Fan <hr> 2092*4a1a9510SRong-En Fan 2093*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ATTRGET" id="ATTRGET">8.3. 2094*4a1a9510SRong-En Fan attr_get()</a></h3> 2095*4a1a9510SRong-En Fan 2096*4a1a9510SRong-En Fan <p>The function attr_get() gets the current attributes and 2097*4a1a9510SRong-En Fan color pair of the window. Though we might not use this as 2098*4a1a9510SRong-En Fan often as the above functions, this is useful in scanning 2099*4a1a9510SRong-En Fan areas of screen. Say we wanted to do some complex update on 2100*4a1a9510SRong-En Fan screen and we are not sure what attribute each character is 2101*4a1a9510SRong-En Fan associated with. Then this function can be used with either 2102*4a1a9510SRong-En Fan attrset or attron to produce the desired effect.</p> 2103*4a1a9510SRong-En Fan </div> 2104*4a1a9510SRong-En Fan 2105*4a1a9510SRong-En Fan <div class="SECT2"> 2106*4a1a9510SRong-En Fan <hr> 2107*4a1a9510SRong-En Fan 2108*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ATTRFUNCS" id="ATTRFUNCS">8.4. 2109*4a1a9510SRong-En Fan attr_ functions</a></h3> 2110*4a1a9510SRong-En Fan 2111*4a1a9510SRong-En Fan <p>There are series of functions like attr_set(), attr_on 2112*4a1a9510SRong-En Fan etc.. These are similar to above functions except that they 2113*4a1a9510SRong-En Fan take parameters of type <tt class= 2114*4a1a9510SRong-En Fan "LITERAL">attr_t</tt>.</p> 2115*4a1a9510SRong-En Fan </div> 2116*4a1a9510SRong-En Fan 2117*4a1a9510SRong-En Fan <div class="SECT2"> 2118*4a1a9510SRong-En Fan <hr> 2119*4a1a9510SRong-En Fan 2120*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WATTRFUNCS" id="WATTRFUNCS">8.5. 2121*4a1a9510SRong-En Fan wattr functions</a></h3> 2122*4a1a9510SRong-En Fan 2123*4a1a9510SRong-En Fan <p>For each of the above functions we have a corresponding 2124*4a1a9510SRong-En Fan function with 'w' which operates on a particular window. 2125*4a1a9510SRong-En Fan The above functions operate on stdscr.</p> 2126*4a1a9510SRong-En Fan </div> 2127*4a1a9510SRong-En Fan 2128*4a1a9510SRong-En Fan <div class="SECT2"> 2129*4a1a9510SRong-En Fan <hr> 2130*4a1a9510SRong-En Fan 2131*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="CHGAT" id="CHGAT">8.6. chgat() 2132*4a1a9510SRong-En Fan functions</a></h3> 2133*4a1a9510SRong-En Fan 2134*4a1a9510SRong-En Fan <p>The function chgat() is listed in the end of the man 2135*4a1a9510SRong-En Fan page curs_attr. It actually is a useful one. This function 2136*4a1a9510SRong-En Fan can be used to set attributes for a group of characters 2137*4a1a9510SRong-En Fan without moving. I mean it !!! without moving the cursor :-) 2138*4a1a9510SRong-En Fan It changes the attributes of a given number of characters 2139*4a1a9510SRong-En Fan starting at the current cursor location.</p> 2140*4a1a9510SRong-En Fan 2141*4a1a9510SRong-En Fan <p>We can give -1 as the character count to update till end 2142*4a1a9510SRong-En Fan of line. If you want to change attributes of characters 2143*4a1a9510SRong-En Fan from current position to end of line, just use this.</p> 2144*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2145*4a1a9510SRong-En Fan chgat(-1, A_REVERSE, 0, NULL); 2146*4a1a9510SRong-En Fan</pre> 2147*4a1a9510SRong-En Fan 2148*4a1a9510SRong-En Fan <p>This function is useful when changing attributes for 2149*4a1a9510SRong-En Fan characters that are already on the screen. Move to the 2150*4a1a9510SRong-En Fan character from which you want to change and change the 2151*4a1a9510SRong-En Fan attribute.</p> 2152*4a1a9510SRong-En Fan 2153*4a1a9510SRong-En Fan <p>Other functions wchgat(), mvchgat(), wchgat() behave 2154*4a1a9510SRong-En Fan similarly except that the w functions operate on the 2155*4a1a9510SRong-En Fan particular window. The mv functions first move the cursor 2156*4a1a9510SRong-En Fan then perform the work given to them. Actually chgat is a 2157*4a1a9510SRong-En Fan macro which is replaced by a wchgat() with stdscr as the 2158*4a1a9510SRong-En Fan window. Most of the "w-less" functions are macros.</p> 2159*4a1a9510SRong-En Fan 2160*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2161*4a1a9510SRong-En Fan <a name="BWICH" id="BWICH"></a> 2162*4a1a9510SRong-En Fan 2163*4a1a9510SRong-En Fan <p><b>Example 6. Chgat() Usage example</b></p> 2164*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2165*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 2166*4a1a9510SRong-En Fan 2167*4a1a9510SRong-En Fanint main(int argc, char *argv[]) 2168*4a1a9510SRong-En Fan{ initscr(); /* Start curses mode */ 2169*4a1a9510SRong-En Fan start_color(); /* Start color functionality */ 2170*4a1a9510SRong-En Fan 2171*4a1a9510SRong-En Fan init_pair(1, COLOR_CYAN, COLOR_BLACK); 2172*4a1a9510SRong-En Fan printw("A Big string which i didn't care to type fully "); 2173*4a1a9510SRong-En Fan mvchgat(0, 0, -1, A_BLINK, 1, NULL); 2174*4a1a9510SRong-En Fan /* 2175*4a1a9510SRong-En Fan * First two parameters specify the position at which to start 2176*4a1a9510SRong-En Fan * Third parameter number of characters to update. -1 means till 2177*4a1a9510SRong-En Fan * end of line 2178*4a1a9510SRong-En Fan * Forth parameter is the normal attribute you wanted to give 2179*4a1a9510SRong-En Fan * to the charcter 2180*4a1a9510SRong-En Fan * Fifth is the color index. It is the index given during init_pair() 2181*4a1a9510SRong-En Fan * use 0 if you didn't want color 2182*4a1a9510SRong-En Fan * Sixth one is always NULL 2183*4a1a9510SRong-En Fan */ 2184*4a1a9510SRong-En Fan refresh(); 2185*4a1a9510SRong-En Fan getch(); 2186*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 2187*4a1a9510SRong-En Fan return 0; 2188*4a1a9510SRong-En Fan}</span> 2189*4a1a9510SRong-En Fan</pre> 2190*4a1a9510SRong-En Fan </div> 2191*4a1a9510SRong-En Fan 2192*4a1a9510SRong-En Fan <p>This example also introduces us to the color world of 2193*4a1a9510SRong-En Fan curses. Colors will be explained in detail later. Use 0 for 2194*4a1a9510SRong-En Fan no color.</p> 2195*4a1a9510SRong-En Fan </div> 2196*4a1a9510SRong-En Fan </div> 2197*4a1a9510SRong-En Fan 2198*4a1a9510SRong-En Fan <div class="SECT1"> 2199*4a1a9510SRong-En Fan <hr> 2200*4a1a9510SRong-En Fan 2201*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="WINDOWS" id="WINDOWS">9. 2202*4a1a9510SRong-En Fan Windows</a></h2> 2203*4a1a9510SRong-En Fan 2204*4a1a9510SRong-En Fan <p>Windows form the most important concept in curses. You 2205*4a1a9510SRong-En Fan have seen the standard window stdscr above where all the 2206*4a1a9510SRong-En Fan functions implicitly operated on this window. Now to make 2207*4a1a9510SRong-En Fan design even a simplest GUI, you need to resort to windows. 2208*4a1a9510SRong-En Fan The main reason you may want to use windows is to manipulate 2209*4a1a9510SRong-En Fan parts of the screen separately, for better efficiency, by 2210*4a1a9510SRong-En Fan updating only the windows that need to be changed and for a 2211*4a1a9510SRong-En Fan better design. I would say the last reason is the most 2212*4a1a9510SRong-En Fan important in going for windows. You should always strive for 2213*4a1a9510SRong-En Fan a better and easy-to-manage design in your programs. If you 2214*4a1a9510SRong-En Fan are writing big, complex GUIs this is of pivotal importance 2215*4a1a9510SRong-En Fan before you start doing anything.</p> 2216*4a1a9510SRong-En Fan 2217*4a1a9510SRong-En Fan <div class="SECT2"> 2218*4a1a9510SRong-En Fan <hr> 2219*4a1a9510SRong-En Fan 2220*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WINDOWBASICS" id= 2221*4a1a9510SRong-En Fan "WINDOWBASICS">9.1. The basics</a></h3> 2222*4a1a9510SRong-En Fan 2223*4a1a9510SRong-En Fan <p>A Window can be created by calling the function 2224*4a1a9510SRong-En Fan <tt class="LITERAL">newwin()</tt>. It doesn't create any 2225*4a1a9510SRong-En Fan thing on the screen actually. It allocates memory for a 2226*4a1a9510SRong-En Fan structure to manipulate the window and updates the 2227*4a1a9510SRong-En Fan structure with data regarding the window like it's size, 2228*4a1a9510SRong-En Fan beginy, beginx etc.. Hence in curses, a window is just an 2229*4a1a9510SRong-En Fan abstraction of an imaginary window, which can be 2230*4a1a9510SRong-En Fan manipulated independent of other parts of screen. The 2231*4a1a9510SRong-En Fan function newwin() returns a pointer to structure WINDOW, 2232*4a1a9510SRong-En Fan which can be passed to window related functions like 2233*4a1a9510SRong-En Fan wprintw() etc.. Finally the window can be destroyed with 2234*4a1a9510SRong-En Fan delwin(). It will deallocate the memory associated with the 2235*4a1a9510SRong-En Fan window structure.</p> 2236*4a1a9510SRong-En Fan </div> 2237*4a1a9510SRong-En Fan 2238*4a1a9510SRong-En Fan <div class="SECT2"> 2239*4a1a9510SRong-En Fan <hr> 2240*4a1a9510SRong-En Fan 2241*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="LETBEWINDOW" id= 2242*4a1a9510SRong-En Fan "LETBEWINDOW">9.2. Let there be a Window !!!</a></h3> 2243*4a1a9510SRong-En Fan 2244*4a1a9510SRong-En Fan <p>What fun is it, if a window is created and we can't see 2245*4a1a9510SRong-En Fan it. So the fun part begins by displaying the window. The 2246*4a1a9510SRong-En Fan function <tt class="LITERAL">box()</tt> can be used to draw 2247*4a1a9510SRong-En Fan a border around the window. Let's explore these functions 2248*4a1a9510SRong-En Fan in more detail in this example.</p> 2249*4a1a9510SRong-En Fan 2250*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2251*4a1a9510SRong-En Fan <a name="BWIBO" id="BWIBO"></a> 2252*4a1a9510SRong-En Fan 2253*4a1a9510SRong-En Fan <p><b>Example 7. Window Border example</b></p> 2254*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2255*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 2256*4a1a9510SRong-En Fan 2257*4a1a9510SRong-En Fan 2258*4a1a9510SRong-En FanWINDOW *create_newwin(int height, int width, int starty, int startx); 2259*4a1a9510SRong-En Fanvoid destroy_win(WINDOW *local_win); 2260*4a1a9510SRong-En Fan 2261*4a1a9510SRong-En Fanint main(int argc, char *argv[]) 2262*4a1a9510SRong-En Fan{ WINDOW *my_win; 2263*4a1a9510SRong-En Fan int startx, starty, width, height; 2264*4a1a9510SRong-En Fan int ch; 2265*4a1a9510SRong-En Fan 2266*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 2267*4a1a9510SRong-En Fan cbreak(); /* Line buffering disabled, Pass on 2268*4a1a9510SRong-En Fan * everty thing to me */ 2269*4a1a9510SRong-En Fan keypad(stdscr, TRUE); /* I need that nifty F1 */ 2270*4a1a9510SRong-En Fan 2271*4a1a9510SRong-En Fan height = 3; 2272*4a1a9510SRong-En Fan width = 10; 2273*4a1a9510SRong-En Fan starty = (LINES - height) / 2; /* Calculating for a center placement */ 2274*4a1a9510SRong-En Fan startx = (COLS - width) / 2; /* of the window */ 2275*4a1a9510SRong-En Fan printw("Press F1 to exit"); 2276*4a1a9510SRong-En Fan refresh(); 2277*4a1a9510SRong-En Fan my_win = create_newwin(height, width, starty, startx); 2278*4a1a9510SRong-En Fan 2279*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 2280*4a1a9510SRong-En Fan { switch(ch) 2281*4a1a9510SRong-En Fan { case KEY_LEFT: 2282*4a1a9510SRong-En Fan destroy_win(my_win); 2283*4a1a9510SRong-En Fan my_win = create_newwin(height, width, starty,--startx); 2284*4a1a9510SRong-En Fan break; 2285*4a1a9510SRong-En Fan case KEY_RIGHT: 2286*4a1a9510SRong-En Fan destroy_win(my_win); 2287*4a1a9510SRong-En Fan my_win = create_newwin(height, width, starty,++startx); 2288*4a1a9510SRong-En Fan break; 2289*4a1a9510SRong-En Fan case KEY_UP: 2290*4a1a9510SRong-En Fan destroy_win(my_win); 2291*4a1a9510SRong-En Fan my_win = create_newwin(height, width, --starty,startx); 2292*4a1a9510SRong-En Fan break; 2293*4a1a9510SRong-En Fan case KEY_DOWN: 2294*4a1a9510SRong-En Fan destroy_win(my_win); 2295*4a1a9510SRong-En Fan my_win = create_newwin(height, width, ++starty,startx); 2296*4a1a9510SRong-En Fan break; 2297*4a1a9510SRong-En Fan } 2298*4a1a9510SRong-En Fan } 2299*4a1a9510SRong-En Fan 2300*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 2301*4a1a9510SRong-En Fan return 0; 2302*4a1a9510SRong-En Fan} 2303*4a1a9510SRong-En Fan 2304*4a1a9510SRong-En FanWINDOW *create_newwin(int height, int width, int starty, int startx) 2305*4a1a9510SRong-En Fan{ WINDOW *local_win; 2306*4a1a9510SRong-En Fan 2307*4a1a9510SRong-En Fan local_win = newwin(height, width, starty, startx); 2308*4a1a9510SRong-En Fan box(local_win, 0 , 0); /* 0, 0 gives default characters 2309*4a1a9510SRong-En Fan * for the vertical and horizontal 2310*4a1a9510SRong-En Fan * lines */ 2311*4a1a9510SRong-En Fan wrefresh(local_win); /* Show that box */ 2312*4a1a9510SRong-En Fan 2313*4a1a9510SRong-En Fan return local_win; 2314*4a1a9510SRong-En Fan} 2315*4a1a9510SRong-En Fan 2316*4a1a9510SRong-En Fanvoid destroy_win(WINDOW *local_win) 2317*4a1a9510SRong-En Fan{ 2318*4a1a9510SRong-En Fan /* box(local_win, ' ', ' '); : This won't produce the desired 2319*4a1a9510SRong-En Fan * result of erasing the window. It will leave it's four corners 2320*4a1a9510SRong-En Fan * and so an ugly remnant of window. 2321*4a1a9510SRong-En Fan */ 2322*4a1a9510SRong-En Fan wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' '); 2323*4a1a9510SRong-En Fan /* The parameters taken are 2324*4a1a9510SRong-En Fan * 1. win: the window on which to operate 2325*4a1a9510SRong-En Fan * 2. ls: character to be used for the left side of the window 2326*4a1a9510SRong-En Fan * 3. rs: character to be used for the right side of the window 2327*4a1a9510SRong-En Fan * 4. ts: character to be used for the top side of the window 2328*4a1a9510SRong-En Fan * 5. bs: character to be used for the bottom side of the window 2329*4a1a9510SRong-En Fan * 6. tl: character to be used for the top left corner of the window 2330*4a1a9510SRong-En Fan * 7. tr: character to be used for the top right corner of the window 2331*4a1a9510SRong-En Fan * 8. bl: character to be used for the bottom left corner of the window 2332*4a1a9510SRong-En Fan * 9. br: character to be used for the bottom right corner of the window 2333*4a1a9510SRong-En Fan */ 2334*4a1a9510SRong-En Fan wrefresh(local_win); 2335*4a1a9510SRong-En Fan delwin(local_win); 2336*4a1a9510SRong-En Fan}</span> 2337*4a1a9510SRong-En Fan</pre> 2338*4a1a9510SRong-En Fan </div> 2339*4a1a9510SRong-En Fan </div> 2340*4a1a9510SRong-En Fan 2341*4a1a9510SRong-En Fan <div class="SECT2"> 2342*4a1a9510SRong-En Fan <hr> 2343*4a1a9510SRong-En Fan 2344*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="BORDEREXEXPL" id= 2345*4a1a9510SRong-En Fan "BORDEREXEXPL">9.3. Explanation</a></h3> 2346*4a1a9510SRong-En Fan 2347*4a1a9510SRong-En Fan <p>Don't scream. I know it's a big example. But I have to 2348*4a1a9510SRong-En Fan explain some important things here :-). This program 2349*4a1a9510SRong-En Fan creates a rectangular window that can be moved with left, 2350*4a1a9510SRong-En Fan right, up, down arrow keys. It repeatedly creates and 2351*4a1a9510SRong-En Fan destroys windows as user press a key. Don't go beyond the 2352*4a1a9510SRong-En Fan screen limits. Checking for those limits is left as an 2353*4a1a9510SRong-En Fan exercise for the reader. Let's dissect it by line by 2354*4a1a9510SRong-En Fan line.</p> 2355*4a1a9510SRong-En Fan 2356*4a1a9510SRong-En Fan <p>The <tt class="LITERAL">create_newwin()</tt> function 2357*4a1a9510SRong-En Fan creates a window with <tt class="LITERAL">newwin()</tt> and 2358*4a1a9510SRong-En Fan displays a border around it with box. The function 2359*4a1a9510SRong-En Fan <tt class="LITERAL">destroy_win()</tt> first erases the 2360*4a1a9510SRong-En Fan window from screen by painting a border with ' ' character 2361*4a1a9510SRong-En Fan and then calling <tt class="LITERAL">delwin()</tt> to 2362*4a1a9510SRong-En Fan deallocate memory related to it. Depending on the key the 2363*4a1a9510SRong-En Fan user presses, starty or startx is changed and a new window 2364*4a1a9510SRong-En Fan is created.</p> 2365*4a1a9510SRong-En Fan 2366*4a1a9510SRong-En Fan <p>In the destroy_win, as you can see, I used wborder 2367*4a1a9510SRong-En Fan instead of box. The reason is written in the comments (You 2368*4a1a9510SRong-En Fan missed it. I know. Read the code :-)). wborder draws a 2369*4a1a9510SRong-En Fan border around the window with the characters given to it as 2370*4a1a9510SRong-En Fan the 4 corner points and the 4 lines. To put it clearly, if 2371*4a1a9510SRong-En Fan you have called wborder as below:</p> 2372*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2373*4a1a9510SRong-En Fan wborder(win, '|', '|', '-', '-', '+', '+', '+', '+'); 2374*4a1a9510SRong-En Fan</pre> 2375*4a1a9510SRong-En Fan 2376*4a1a9510SRong-En Fan <p>it produces some thing like</p> 2377*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2378*4a1a9510SRong-En Fan +------------+ 2379*4a1a9510SRong-En Fan | | 2380*4a1a9510SRong-En Fan | | 2381*4a1a9510SRong-En Fan | | 2382*4a1a9510SRong-En Fan | | 2383*4a1a9510SRong-En Fan | | 2384*4a1a9510SRong-En Fan | | 2385*4a1a9510SRong-En Fan +------------+ 2386*4a1a9510SRong-En Fan</pre> 2387*4a1a9510SRong-En Fan </div> 2388*4a1a9510SRong-En Fan 2389*4a1a9510SRong-En Fan <div class="SECT2"> 2390*4a1a9510SRong-En Fan <hr> 2391*4a1a9510SRong-En Fan 2392*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="OTHERSTUFF" id="OTHERSTUFF">9.4. 2393*4a1a9510SRong-En Fan The other stuff in the example</a></h3> 2394*4a1a9510SRong-En Fan 2395*4a1a9510SRong-En Fan <p>You can also see in the above examples, that I have used 2396*4a1a9510SRong-En Fan the variables COLS, LINES which are initialized to the 2397*4a1a9510SRong-En Fan screen sizes after initscr(). They can be useful in finding 2398*4a1a9510SRong-En Fan screen dimensions and finding the center co-ordinate of the 2399*4a1a9510SRong-En Fan screen as above. The function <tt class= 2400*4a1a9510SRong-En Fan "LITERAL">getch()</tt> as usual gets the key from keyboard 2401*4a1a9510SRong-En Fan and according to the key it does the corresponding work. 2402*4a1a9510SRong-En Fan This type of switch- case is very common in any GUI based 2403*4a1a9510SRong-En Fan programs.</p> 2404*4a1a9510SRong-En Fan </div> 2405*4a1a9510SRong-En Fan 2406*4a1a9510SRong-En Fan <div class="SECT2"> 2407*4a1a9510SRong-En Fan <hr> 2408*4a1a9510SRong-En Fan 2409*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="OTHERBORDERFUNCS" id= 2410*4a1a9510SRong-En Fan "OTHERBORDERFUNCS">9.5. Other Border functions</a></h3> 2411*4a1a9510SRong-En Fan 2412*4a1a9510SRong-En Fan <p>Above program is grossly inefficient in that with each 2413*4a1a9510SRong-En Fan press of a key, a window is destroyed and another is 2414*4a1a9510SRong-En Fan created. So let's write a more efficient program which uses 2415*4a1a9510SRong-En Fan other border related functions.</p> 2416*4a1a9510SRong-En Fan 2417*4a1a9510SRong-En Fan <p>The following program uses <tt class= 2418*4a1a9510SRong-En Fan "LITERAL">mvhline()</tt> and <tt class= 2419*4a1a9510SRong-En Fan "LITERAL">mvvline()</tt> to achieve similar effect. These 2420*4a1a9510SRong-En Fan two functions are simple. They create a horizontal or 2421*4a1a9510SRong-En Fan vertical line of the specified length at the specified 2422*4a1a9510SRong-En Fan position.</p> 2423*4a1a9510SRong-En Fan 2424*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2425*4a1a9510SRong-En Fan <a name="BOTBO" id="BOTBO"></a> 2426*4a1a9510SRong-En Fan 2427*4a1a9510SRong-En Fan <p><b>Example 8. More border functions</b></p> 2428*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2429*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 2430*4a1a9510SRong-En Fan 2431*4a1a9510SRong-En Fantypedef struct _win_border_struct { 2432*4a1a9510SRong-En Fan chtype ls, rs, ts, bs, 2433*4a1a9510SRong-En Fan tl, tr, bl, br; 2434*4a1a9510SRong-En Fan}WIN_BORDER; 2435*4a1a9510SRong-En Fan 2436*4a1a9510SRong-En Fantypedef struct _WIN_struct { 2437*4a1a9510SRong-En Fan 2438*4a1a9510SRong-En Fan int startx, starty; 2439*4a1a9510SRong-En Fan int height, width; 2440*4a1a9510SRong-En Fan WIN_BORDER border; 2441*4a1a9510SRong-En Fan}WIN; 2442*4a1a9510SRong-En Fan 2443*4a1a9510SRong-En Fanvoid init_win_params(WIN *p_win); 2444*4a1a9510SRong-En Fanvoid print_win_params(WIN *p_win); 2445*4a1a9510SRong-En Fanvoid create_box(WIN *win, bool flag); 2446*4a1a9510SRong-En Fan 2447*4a1a9510SRong-En Fanint main(int argc, char *argv[]) 2448*4a1a9510SRong-En Fan{ WIN win; 2449*4a1a9510SRong-En Fan int ch; 2450*4a1a9510SRong-En Fan 2451*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 2452*4a1a9510SRong-En Fan start_color(); /* Start the color functionality */ 2453*4a1a9510SRong-En Fan cbreak(); /* Line buffering disabled, Pass on 2454*4a1a9510SRong-En Fan * everty thing to me */ 2455*4a1a9510SRong-En Fan keypad(stdscr, TRUE); /* I need that nifty F1 */ 2456*4a1a9510SRong-En Fan noecho(); 2457*4a1a9510SRong-En Fan init_pair(1, COLOR_CYAN, COLOR_BLACK); 2458*4a1a9510SRong-En Fan 2459*4a1a9510SRong-En Fan /* Initialize the window parameters */ 2460*4a1a9510SRong-En Fan init_win_params(&win); 2461*4a1a9510SRong-En Fan print_win_params(&win); 2462*4a1a9510SRong-En Fan 2463*4a1a9510SRong-En Fan attron(COLOR_PAIR(1)); 2464*4a1a9510SRong-En Fan printw("Press F1 to exit"); 2465*4a1a9510SRong-En Fan refresh(); 2466*4a1a9510SRong-En Fan attroff(COLOR_PAIR(1)); 2467*4a1a9510SRong-En Fan 2468*4a1a9510SRong-En Fan create_box(&win, TRUE); 2469*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 2470*4a1a9510SRong-En Fan { switch(ch) 2471*4a1a9510SRong-En Fan { case KEY_LEFT: 2472*4a1a9510SRong-En Fan create_box(&win, FALSE); 2473*4a1a9510SRong-En Fan --win.startx; 2474*4a1a9510SRong-En Fan create_box(&win, TRUE); 2475*4a1a9510SRong-En Fan break; 2476*4a1a9510SRong-En Fan case KEY_RIGHT: 2477*4a1a9510SRong-En Fan create_box(&win, FALSE); 2478*4a1a9510SRong-En Fan ++win.startx; 2479*4a1a9510SRong-En Fan create_box(&win, TRUE); 2480*4a1a9510SRong-En Fan break; 2481*4a1a9510SRong-En Fan case KEY_UP: 2482*4a1a9510SRong-En Fan create_box(&win, FALSE); 2483*4a1a9510SRong-En Fan --win.starty; 2484*4a1a9510SRong-En Fan create_box(&win, TRUE); 2485*4a1a9510SRong-En Fan break; 2486*4a1a9510SRong-En Fan case KEY_DOWN: 2487*4a1a9510SRong-En Fan create_box(&win, FALSE); 2488*4a1a9510SRong-En Fan ++win.starty; 2489*4a1a9510SRong-En Fan create_box(&win, TRUE); 2490*4a1a9510SRong-En Fan break; 2491*4a1a9510SRong-En Fan } 2492*4a1a9510SRong-En Fan } 2493*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 2494*4a1a9510SRong-En Fan return 0; 2495*4a1a9510SRong-En Fan} 2496*4a1a9510SRong-En Fanvoid init_win_params(WIN *p_win) 2497*4a1a9510SRong-En Fan{ 2498*4a1a9510SRong-En Fan p_win->height = 3; 2499*4a1a9510SRong-En Fan p_win->width = 10; 2500*4a1a9510SRong-En Fan p_win->starty = (LINES - p_win->height)/2; 2501*4a1a9510SRong-En Fan p_win->startx = (COLS - p_win->width)/2; 2502*4a1a9510SRong-En Fan 2503*4a1a9510SRong-En Fan p_win->border.ls = '|'; 2504*4a1a9510SRong-En Fan p_win->border.rs = '|'; 2505*4a1a9510SRong-En Fan p_win->border.ts = '-'; 2506*4a1a9510SRong-En Fan p_win->border.bs = '-'; 2507*4a1a9510SRong-En Fan p_win->border.tl = '+'; 2508*4a1a9510SRong-En Fan p_win->border.tr = '+'; 2509*4a1a9510SRong-En Fan p_win->border.bl = '+'; 2510*4a1a9510SRong-En Fan p_win->border.br = '+'; 2511*4a1a9510SRong-En Fan 2512*4a1a9510SRong-En Fan} 2513*4a1a9510SRong-En Fanvoid print_win_params(WIN *p_win) 2514*4a1a9510SRong-En Fan{ 2515*4a1a9510SRong-En Fan#ifdef _DEBUG 2516*4a1a9510SRong-En Fan mvprintw(25, 0, "%d %d %d %d", p_win->startx, p_win->starty, 2517*4a1a9510SRong-En Fan p_win->width, p_win->height); 2518*4a1a9510SRong-En Fan refresh(); 2519*4a1a9510SRong-En Fan#endif 2520*4a1a9510SRong-En Fan} 2521*4a1a9510SRong-En Fanvoid create_box(WIN *p_win, bool flag) 2522*4a1a9510SRong-En Fan{ int i, j; 2523*4a1a9510SRong-En Fan int x, y, w, h; 2524*4a1a9510SRong-En Fan 2525*4a1a9510SRong-En Fan x = p_win->startx; 2526*4a1a9510SRong-En Fan y = p_win->starty; 2527*4a1a9510SRong-En Fan w = p_win->width; 2528*4a1a9510SRong-En Fan h = p_win->height; 2529*4a1a9510SRong-En Fan 2530*4a1a9510SRong-En Fan if(flag == TRUE) 2531*4a1a9510SRong-En Fan { mvaddch(y, x, p_win->border.tl); 2532*4a1a9510SRong-En Fan mvaddch(y, x + w, p_win->border.tr); 2533*4a1a9510SRong-En Fan mvaddch(y + h, x, p_win->border.bl); 2534*4a1a9510SRong-En Fan mvaddch(y + h, x + w, p_win->border.br); 2535*4a1a9510SRong-En Fan mvhline(y, x + 1, p_win->border.ts, w - 1); 2536*4a1a9510SRong-En Fan mvhline(y + h, x + 1, p_win->border.bs, w - 1); 2537*4a1a9510SRong-En Fan mvvline(y + 1, x, p_win->border.ls, h - 1); 2538*4a1a9510SRong-En Fan mvvline(y + 1, x + w, p_win->border.rs, h - 1); 2539*4a1a9510SRong-En Fan 2540*4a1a9510SRong-En Fan } 2541*4a1a9510SRong-En Fan else 2542*4a1a9510SRong-En Fan for(j = y; j <= y + h; ++j) 2543*4a1a9510SRong-En Fan for(i = x; i <= x + w; ++i) 2544*4a1a9510SRong-En Fan mvaddch(j, i, ' '); 2545*4a1a9510SRong-En Fan 2546*4a1a9510SRong-En Fan refresh(); 2547*4a1a9510SRong-En Fan 2548*4a1a9510SRong-En Fan}</span> 2549*4a1a9510SRong-En Fan</pre> 2550*4a1a9510SRong-En Fan </div> 2551*4a1a9510SRong-En Fan </div> 2552*4a1a9510SRong-En Fan </div> 2553*4a1a9510SRong-En Fan 2554*4a1a9510SRong-En Fan <div class="SECT1"> 2555*4a1a9510SRong-En Fan <hr> 2556*4a1a9510SRong-En Fan 2557*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="COLOR" id="COLOR">10. 2558*4a1a9510SRong-En Fan Colors</a></h2> 2559*4a1a9510SRong-En Fan 2560*4a1a9510SRong-En Fan <div class="SECT2"> 2561*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COLORBASICS" id= 2562*4a1a9510SRong-En Fan "COLORBASICS">10.1. The basics</a></h3> 2563*4a1a9510SRong-En Fan 2564*4a1a9510SRong-En Fan <p>Life seems dull with no colors. Curses has a nice 2565*4a1a9510SRong-En Fan mechanism to handle colors. Let's get into the thick of the 2566*4a1a9510SRong-En Fan things with a small program.</p> 2567*4a1a9510SRong-En Fan 2568*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2569*4a1a9510SRong-En Fan <a name="BSICO" id="BSICO"></a> 2570*4a1a9510SRong-En Fan 2571*4a1a9510SRong-En Fan <p><b>Example 9. A Simple Color example</b></p> 2572*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2573*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 2574*4a1a9510SRong-En Fan 2575*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string); 2576*4a1a9510SRong-En Fanint main(int argc, char *argv[]) 2577*4a1a9510SRong-En Fan{ initscr(); /* Start curses mode */ 2578*4a1a9510SRong-En Fan if(has_colors() == FALSE) 2579*4a1a9510SRong-En Fan { endwin(); 2580*4a1a9510SRong-En Fan printf("Your terminal does not support color\n"); 2581*4a1a9510SRong-En Fan exit(1); 2582*4a1a9510SRong-En Fan } 2583*4a1a9510SRong-En Fan start_color(); /* Start color */ 2584*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 2585*4a1a9510SRong-En Fan 2586*4a1a9510SRong-En Fan attron(COLOR_PAIR(1)); 2587*4a1a9510SRong-En Fan print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ..."); 2588*4a1a9510SRong-En Fan attroff(COLOR_PAIR(1)); 2589*4a1a9510SRong-En Fan getch(); 2590*4a1a9510SRong-En Fan endwin(); 2591*4a1a9510SRong-En Fan} 2592*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string) 2593*4a1a9510SRong-En Fan{ int length, x, y; 2594*4a1a9510SRong-En Fan float temp; 2595*4a1a9510SRong-En Fan 2596*4a1a9510SRong-En Fan if(win == NULL) 2597*4a1a9510SRong-En Fan win = stdscr; 2598*4a1a9510SRong-En Fan getyx(win, y, x); 2599*4a1a9510SRong-En Fan if(startx != 0) 2600*4a1a9510SRong-En Fan x = startx; 2601*4a1a9510SRong-En Fan if(starty != 0) 2602*4a1a9510SRong-En Fan y = starty; 2603*4a1a9510SRong-En Fan if(width == 0) 2604*4a1a9510SRong-En Fan width = 80; 2605*4a1a9510SRong-En Fan 2606*4a1a9510SRong-En Fan length = strlen(string); 2607*4a1a9510SRong-En Fan temp = (width - length)/ 2; 2608*4a1a9510SRong-En Fan x = startx + (int)temp; 2609*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 2610*4a1a9510SRong-En Fan refresh(); 2611*4a1a9510SRong-En Fan} 2612*4a1a9510SRong-En Fan</span> 2613*4a1a9510SRong-En Fan</pre> 2614*4a1a9510SRong-En Fan </div> 2615*4a1a9510SRong-En Fan 2616*4a1a9510SRong-En Fan <p>As you can see, to start using color, you should first 2617*4a1a9510SRong-En Fan call the function <tt class="LITERAL">start_color()</tt>. 2618*4a1a9510SRong-En Fan After that, you can use color capabilities of your 2619*4a1a9510SRong-En Fan terminals using various functions. To find out whether a 2620*4a1a9510SRong-En Fan terminal has color capabilities or not, you can use 2621*4a1a9510SRong-En Fan <tt class="LITERAL">has_colors()</tt> function, which 2622*4a1a9510SRong-En Fan returns FALSE if the terminal does not support color.</p> 2623*4a1a9510SRong-En Fan 2624*4a1a9510SRong-En Fan <p>Curses initializes all the colors supported by terminal 2625*4a1a9510SRong-En Fan when start_color() is called. These can be accessed by the 2626*4a1a9510SRong-En Fan define constants like <tt class="LITERAL">COLOR_BLACK</tt> 2627*4a1a9510SRong-En Fan etc. Now to actually start using colors, you have to define 2628*4a1a9510SRong-En Fan pairs. Colors are always used in pairs. That means you have 2629*4a1a9510SRong-En Fan to use the function <tt class="LITERAL">init_pair()</tt> to 2630*4a1a9510SRong-En Fan define the foreground and background for the pair number 2631*4a1a9510SRong-En Fan you give. After that that pair number can be used as a 2632*4a1a9510SRong-En Fan normal attribute with <tt class= 2633*4a1a9510SRong-En Fan "LITERAL">COLOR_PAIR()</tt>function. This may seem to be 2634*4a1a9510SRong-En Fan cumbersome at first. But this elegant solution allows us to 2635*4a1a9510SRong-En Fan manage color pairs very easily. To appreciate it, you have 2636*4a1a9510SRong-En Fan to look into the the source code of "dialog", a utility for 2637*4a1a9510SRong-En Fan displaying dialog boxes from shell scripts. The developers 2638*4a1a9510SRong-En Fan have defined foreground and background combinations for all 2639*4a1a9510SRong-En Fan the colors they might need and initialized at the 2640*4a1a9510SRong-En Fan beginning. This makes it very easy to set attributes just 2641*4a1a9510SRong-En Fan by accessing a pair which we already have defined as a 2642*4a1a9510SRong-En Fan constant.</p> 2643*4a1a9510SRong-En Fan 2644*4a1a9510SRong-En Fan <p>The following colors are defined in <tt class= 2645*4a1a9510SRong-En Fan "LITERAL">curses.h</tt>. You can use these as parameters 2646*4a1a9510SRong-En Fan for various color functions.</p> 2647*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2648*4a1a9510SRong-En Fan COLOR_BLACK 0 2649*4a1a9510SRong-En Fan COLOR_RED 1 2650*4a1a9510SRong-En Fan COLOR_GREEN 2 2651*4a1a9510SRong-En Fan COLOR_YELLOW 3 2652*4a1a9510SRong-En Fan COLOR_BLUE 4 2653*4a1a9510SRong-En Fan COLOR_MAGENTA 5 2654*4a1a9510SRong-En Fan COLOR_CYAN 6 2655*4a1a9510SRong-En Fan COLOR_WHITE 7 2656*4a1a9510SRong-En Fan</pre> 2657*4a1a9510SRong-En Fan </div> 2658*4a1a9510SRong-En Fan 2659*4a1a9510SRong-En Fan <div class="SECT2"> 2660*4a1a9510SRong-En Fan <hr> 2661*4a1a9510SRong-En Fan 2662*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="CHANGECOLORDEFS" id= 2663*4a1a9510SRong-En Fan "CHANGECOLORDEFS">10.2. Changing Color Definitions</a></h3> 2664*4a1a9510SRong-En Fan 2665*4a1a9510SRong-En Fan <p>The function <tt class="LITERAL">init_color()</tt>can be 2666*4a1a9510SRong-En Fan used to change the rgb values for the colors defined by 2667*4a1a9510SRong-En Fan curses initially. Say you wanted to lighten the intensity 2668*4a1a9510SRong-En Fan of red color by a minuscule. Then you can use this function 2669*4a1a9510SRong-En Fan as</p> 2670*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2671*4a1a9510SRong-En Fan init_color(COLOR_RED, 700, 0, 0); 2672*4a1a9510SRong-En Fan /* param 1 : color name 2673*4a1a9510SRong-En Fan * param 2, 3, 4 : rgb content min = 0, max = 1000 */ 2674*4a1a9510SRong-En Fan</pre> 2675*4a1a9510SRong-En Fan 2676*4a1a9510SRong-En Fan <p>If your terminal cannot change the color definitions, 2677*4a1a9510SRong-En Fan the function returns ERR. The function <tt class= 2678*4a1a9510SRong-En Fan "LITERAL">can_change_color()</tt> can be used to find out 2679*4a1a9510SRong-En Fan whether the terminal has the capability of changing color 2680*4a1a9510SRong-En Fan content or not. The rgb content is scaled from 0 to 1000. 2681*4a1a9510SRong-En Fan Initially RED color is defined with content 1000(r), 0(g), 2682*4a1a9510SRong-En Fan 0(b).</p> 2683*4a1a9510SRong-En Fan </div> 2684*4a1a9510SRong-En Fan 2685*4a1a9510SRong-En Fan <div class="SECT2"> 2686*4a1a9510SRong-En Fan <hr> 2687*4a1a9510SRong-En Fan 2688*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COLORCONTENT" id= 2689*4a1a9510SRong-En Fan "COLORCONTENT">10.3. Color Content</a></h3> 2690*4a1a9510SRong-En Fan 2691*4a1a9510SRong-En Fan <p>The functions <tt class="LITERAL">color_content()</tt> 2692*4a1a9510SRong-En Fan and <tt class="LITERAL">pair_content()</tt> can be used to 2693*4a1a9510SRong-En Fan find the color content and foreground, background 2694*4a1a9510SRong-En Fan combination for the pair.</p> 2695*4a1a9510SRong-En Fan </div> 2696*4a1a9510SRong-En Fan </div> 2697*4a1a9510SRong-En Fan 2698*4a1a9510SRong-En Fan <div class="SECT1"> 2699*4a1a9510SRong-En Fan <hr> 2700*4a1a9510SRong-En Fan 2701*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="KEYS" id="KEYS">11. Interfacing 2702*4a1a9510SRong-En Fan with the key board</a></h2> 2703*4a1a9510SRong-En Fan 2704*4a1a9510SRong-En Fan <div class="SECT2"> 2705*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="KEYSBASICS" id= 2706*4a1a9510SRong-En Fan "KEYSBASICS">11.1. The Basics</a></h3> 2707*4a1a9510SRong-En Fan 2708*4a1a9510SRong-En Fan <p>No GUI is complete without a strong user interface and 2709*4a1a9510SRong-En Fan to interact with the user, a curses program should be 2710*4a1a9510SRong-En Fan sensitive to key presses or the mouse actions done by the 2711*4a1a9510SRong-En Fan user. Let's deal with the keys first.</p> 2712*4a1a9510SRong-En Fan 2713*4a1a9510SRong-En Fan <p>As you have seen in almost all of the above examples, 2714*4a1a9510SRong-En Fan it's very easy to get key input from the user. A simple way 2715*4a1a9510SRong-En Fan of getting key presses is to use <tt class= 2716*4a1a9510SRong-En Fan "LITERAL">getch()</tt> function. The cbreak mode should be 2717*4a1a9510SRong-En Fan enabled to read keys when you are interested in reading 2718*4a1a9510SRong-En Fan individual key hits rather than complete lines of text 2719*4a1a9510SRong-En Fan (which usually end with a carriage return). keypad should 2720*4a1a9510SRong-En Fan be enabled to get the Functions keys, arrow keys etc. See 2721*4a1a9510SRong-En Fan the initialization section for details.</p> 2722*4a1a9510SRong-En Fan 2723*4a1a9510SRong-En Fan <p><tt class="LITERAL">getch()</tt> returns an integer 2724*4a1a9510SRong-En Fan corresponding to the key pressed. If it is a normal 2725*4a1a9510SRong-En Fan character, the integer value will be equivalent to the 2726*4a1a9510SRong-En Fan character. Otherwise it returns a number which can be 2727*4a1a9510SRong-En Fan matched with the constants defined in <tt class= 2728*4a1a9510SRong-En Fan "LITERAL">curses.h</tt>. For example if the user presses 2729*4a1a9510SRong-En Fan F1, the integer returned is 265. This can be checked using 2730*4a1a9510SRong-En Fan the macro KEY_F() defined in curses.h. This makes reading 2731*4a1a9510SRong-En Fan keys portable and easy to manage.</p> 2732*4a1a9510SRong-En Fan 2733*4a1a9510SRong-En Fan <p>For example, if you call getch() like this</p> 2734*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2735*4a1a9510SRong-En Fan int ch; 2736*4a1a9510SRong-En Fan 2737*4a1a9510SRong-En Fan ch = getch(); 2738*4a1a9510SRong-En Fan</pre> 2739*4a1a9510SRong-En Fan 2740*4a1a9510SRong-En Fan <p>getch() will wait for the user to press a key, (unless 2741*4a1a9510SRong-En Fan you specified a timeout) and when user presses a key, the 2742*4a1a9510SRong-En Fan corresponding integer is returned. Then you can check the 2743*4a1a9510SRong-En Fan value returned with the constants defined in curses.h to 2744*4a1a9510SRong-En Fan match against the keys you want.</p> 2745*4a1a9510SRong-En Fan 2746*4a1a9510SRong-En Fan <p>The following code piece will do that job.</p> 2747*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2748*4a1a9510SRong-En Fan if(ch == KEY_LEFT) 2749*4a1a9510SRong-En Fan printw("Left arrow is pressed\n"); 2750*4a1a9510SRong-En Fan</pre> 2751*4a1a9510SRong-En Fan 2752*4a1a9510SRong-En Fan <p>Let's write a small program which creates a menu which 2753*4a1a9510SRong-En Fan can be navigated by up and down arrows.</p> 2754*4a1a9510SRong-En Fan </div> 2755*4a1a9510SRong-En Fan 2756*4a1a9510SRong-En Fan <div class="SECT2"> 2757*4a1a9510SRong-En Fan <hr> 2758*4a1a9510SRong-En Fan 2759*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="SIMPLEKEYEX" id= 2760*4a1a9510SRong-En Fan "SIMPLEKEYEX">11.2. A Simple Key Usage example</a></h3> 2761*4a1a9510SRong-En Fan 2762*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2763*4a1a9510SRong-En Fan <a name="BSIKE" id="BSIKE"></a> 2764*4a1a9510SRong-En Fan 2765*4a1a9510SRong-En Fan <p><b>Example 10. A Simple Key Usage example</b></p> 2766*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2767*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <stdio.h> 2768*4a1a9510SRong-En Fan#include <ncurses.h> 2769*4a1a9510SRong-En Fan 2770*4a1a9510SRong-En Fan#define WIDTH 30 2771*4a1a9510SRong-En Fan#define HEIGHT 10 2772*4a1a9510SRong-En Fan 2773*4a1a9510SRong-En Fanint startx = 0; 2774*4a1a9510SRong-En Fanint starty = 0; 2775*4a1a9510SRong-En Fan 2776*4a1a9510SRong-En Fanchar *choices[] = { 2777*4a1a9510SRong-En Fan "Choice 1", 2778*4a1a9510SRong-En Fan "Choice 2", 2779*4a1a9510SRong-En Fan "Choice 3", 2780*4a1a9510SRong-En Fan "Choice 4", 2781*4a1a9510SRong-En Fan "Exit", 2782*4a1a9510SRong-En Fan }; 2783*4a1a9510SRong-En Fanint n_choices = sizeof(choices) / sizeof(char *); 2784*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight); 2785*4a1a9510SRong-En Fan 2786*4a1a9510SRong-En Fanint main() 2787*4a1a9510SRong-En Fan{ WINDOW *menu_win; 2788*4a1a9510SRong-En Fan int highlight = 1; 2789*4a1a9510SRong-En Fan int choice = 0; 2790*4a1a9510SRong-En Fan int c; 2791*4a1a9510SRong-En Fan 2792*4a1a9510SRong-En Fan initscr(); 2793*4a1a9510SRong-En Fan clear(); 2794*4a1a9510SRong-En Fan noecho(); 2795*4a1a9510SRong-En Fan cbreak(); /* Line buffering disabled. pass on everything */ 2796*4a1a9510SRong-En Fan startx = (80 - WIDTH) / 2; 2797*4a1a9510SRong-En Fan starty = (24 - HEIGHT) / 2; 2798*4a1a9510SRong-En Fan 2799*4a1a9510SRong-En Fan menu_win = newwin(HEIGHT, WIDTH, starty, startx); 2800*4a1a9510SRong-En Fan keypad(menu_win, TRUE); 2801*4a1a9510SRong-En Fan mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice"); 2802*4a1a9510SRong-En Fan refresh(); 2803*4a1a9510SRong-En Fan print_menu(menu_win, highlight); 2804*4a1a9510SRong-En Fan while(1) 2805*4a1a9510SRong-En Fan { c = wgetch(menu_win); 2806*4a1a9510SRong-En Fan switch(c) 2807*4a1a9510SRong-En Fan { case KEY_UP: 2808*4a1a9510SRong-En Fan if(highlight == 1) 2809*4a1a9510SRong-En Fan highlight = n_choices; 2810*4a1a9510SRong-En Fan else 2811*4a1a9510SRong-En Fan --highlight; 2812*4a1a9510SRong-En Fan break; 2813*4a1a9510SRong-En Fan case KEY_DOWN: 2814*4a1a9510SRong-En Fan if(highlight == n_choices) 2815*4a1a9510SRong-En Fan highlight = 1; 2816*4a1a9510SRong-En Fan else 2817*4a1a9510SRong-En Fan ++highlight; 2818*4a1a9510SRong-En Fan break; 2819*4a1a9510SRong-En Fan case 10: 2820*4a1a9510SRong-En Fan choice = highlight; 2821*4a1a9510SRong-En Fan break; 2822*4a1a9510SRong-En Fan default: 2823*4a1a9510SRong-En Fan mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c); 2824*4a1a9510SRong-En Fan refresh(); 2825*4a1a9510SRong-En Fan break; 2826*4a1a9510SRong-En Fan } 2827*4a1a9510SRong-En Fan print_menu(menu_win, highlight); 2828*4a1a9510SRong-En Fan if(choice != 0) /* User did a choice come out of the infinite loop */ 2829*4a1a9510SRong-En Fan break; 2830*4a1a9510SRong-En Fan } 2831*4a1a9510SRong-En Fan mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]); 2832*4a1a9510SRong-En Fan clrtoeol(); 2833*4a1a9510SRong-En Fan refresh(); 2834*4a1a9510SRong-En Fan endwin(); 2835*4a1a9510SRong-En Fan return 0; 2836*4a1a9510SRong-En Fan} 2837*4a1a9510SRong-En Fan 2838*4a1a9510SRong-En Fan 2839*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight) 2840*4a1a9510SRong-En Fan{ 2841*4a1a9510SRong-En Fan int x, y, i; 2842*4a1a9510SRong-En Fan 2843*4a1a9510SRong-En Fan x = 2; 2844*4a1a9510SRong-En Fan y = 2; 2845*4a1a9510SRong-En Fan box(menu_win, 0, 0); 2846*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 2847*4a1a9510SRong-En Fan { if(highlight == i + 1) /* High light the present choice */ 2848*4a1a9510SRong-En Fan { wattron(menu_win, A_REVERSE); 2849*4a1a9510SRong-En Fan mvwprintw(menu_win, y, x, "%s", choices[i]); 2850*4a1a9510SRong-En Fan wattroff(menu_win, A_REVERSE); 2851*4a1a9510SRong-En Fan } 2852*4a1a9510SRong-En Fan else 2853*4a1a9510SRong-En Fan mvwprintw(menu_win, y, x, "%s", choices[i]); 2854*4a1a9510SRong-En Fan ++y; 2855*4a1a9510SRong-En Fan } 2856*4a1a9510SRong-En Fan wrefresh(menu_win); 2857*4a1a9510SRong-En Fan} 2858*4a1a9510SRong-En Fan</span> 2859*4a1a9510SRong-En Fan</pre> 2860*4a1a9510SRong-En Fan </div> 2861*4a1a9510SRong-En Fan </div> 2862*4a1a9510SRong-En Fan </div> 2863*4a1a9510SRong-En Fan 2864*4a1a9510SRong-En Fan <div class="SECT1"> 2865*4a1a9510SRong-En Fan <hr> 2866*4a1a9510SRong-En Fan 2867*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="MOUSE" id="MOUSE">12. Interfacing 2868*4a1a9510SRong-En Fan with the mouse</a></h2> 2869*4a1a9510SRong-En Fan 2870*4a1a9510SRong-En Fan <p>Now that you have seen how to get keys, lets do the same 2871*4a1a9510SRong-En Fan thing from mouse. Usually each UI allows the user to interact 2872*4a1a9510SRong-En Fan with both keyboard and mouse.</p> 2873*4a1a9510SRong-En Fan 2874*4a1a9510SRong-En Fan <div class="SECT2"> 2875*4a1a9510SRong-En Fan <hr> 2876*4a1a9510SRong-En Fan 2877*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MOUSEBASICS" id= 2878*4a1a9510SRong-En Fan "MOUSEBASICS">12.1. The Basics</a></h3> 2879*4a1a9510SRong-En Fan 2880*4a1a9510SRong-En Fan <p>Before you do any thing else, the events you want to 2881*4a1a9510SRong-En Fan receive have to be enabled with <tt class= 2882*4a1a9510SRong-En Fan "LITERAL">mousemask()</tt>.</p> 2883*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2884*4a1a9510SRong-En Fan mousemask( mmask_t newmask, /* The events you want to listen to */ 2885*4a1a9510SRong-En Fan mmask_t *oldmask) /* The old events mask */ 2886*4a1a9510SRong-En Fan</pre> 2887*4a1a9510SRong-En Fan 2888*4a1a9510SRong-En Fan <p>The first parameter to above function is a bit mask of 2889*4a1a9510SRong-En Fan events you would like to listen. By default, all the events 2890*4a1a9510SRong-En Fan are turned off. The bit mask <tt class= 2891*4a1a9510SRong-En Fan "LITERAL">ALL_MOUSE_EVENTS</tt> can be used to get all the 2892*4a1a9510SRong-En Fan events.</p> 2893*4a1a9510SRong-En Fan 2894*4a1a9510SRong-En Fan <p>The following are all the event masks:</p> 2895*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2896*4a1a9510SRong-En Fan Name Description 2897*4a1a9510SRong-En Fan --------------------------------------------------------------------- 2898*4a1a9510SRong-En Fan BUTTON1_PRESSED mouse button 1 down 2899*4a1a9510SRong-En Fan BUTTON1_RELEASED mouse button 1 up 2900*4a1a9510SRong-En Fan BUTTON1_CLICKED mouse button 1 clicked 2901*4a1a9510SRong-En Fan BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked 2902*4a1a9510SRong-En Fan BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked 2903*4a1a9510SRong-En Fan BUTTON2_PRESSED mouse button 2 down 2904*4a1a9510SRong-En Fan BUTTON2_RELEASED mouse button 2 up 2905*4a1a9510SRong-En Fan BUTTON2_CLICKED mouse button 2 clicked 2906*4a1a9510SRong-En Fan BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked 2907*4a1a9510SRong-En Fan BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked 2908*4a1a9510SRong-En Fan BUTTON3_PRESSED mouse button 3 down 2909*4a1a9510SRong-En Fan BUTTON3_RELEASED mouse button 3 up 2910*4a1a9510SRong-En Fan BUTTON3_CLICKED mouse button 3 clicked 2911*4a1a9510SRong-En Fan BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked 2912*4a1a9510SRong-En Fan BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked 2913*4a1a9510SRong-En Fan BUTTON4_PRESSED mouse button 4 down 2914*4a1a9510SRong-En Fan BUTTON4_RELEASED mouse button 4 up 2915*4a1a9510SRong-En Fan BUTTON4_CLICKED mouse button 4 clicked 2916*4a1a9510SRong-En Fan BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked 2917*4a1a9510SRong-En Fan BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked 2918*4a1a9510SRong-En Fan BUTTON_SHIFT shift was down during button state change 2919*4a1a9510SRong-En Fan BUTTON_CTRL control was down during button state change 2920*4a1a9510SRong-En Fan BUTTON_ALT alt was down during button state change 2921*4a1a9510SRong-En Fan ALL_MOUSE_EVENTS report all button state changes 2922*4a1a9510SRong-En Fan REPORT_MOUSE_POSITION report mouse movement 2923*4a1a9510SRong-En Fan</pre> 2924*4a1a9510SRong-En Fan </div> 2925*4a1a9510SRong-En Fan 2926*4a1a9510SRong-En Fan <div class="SECT2"> 2927*4a1a9510SRong-En Fan <hr> 2928*4a1a9510SRong-En Fan 2929*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="GETTINGEVENTS" id= 2930*4a1a9510SRong-En Fan "GETTINGEVENTS">12.2. Getting the events</a></h3> 2931*4a1a9510SRong-En Fan 2932*4a1a9510SRong-En Fan <p>Once a class of mouse events have been enabled, getch() 2933*4a1a9510SRong-En Fan class of functions return KEY_MOUSE every time some mouse 2934*4a1a9510SRong-En Fan event happens. Then the mouse event can be retrieved with 2935*4a1a9510SRong-En Fan <tt class="LITERAL">getmouse()</tt>.</p> 2936*4a1a9510SRong-En Fan 2937*4a1a9510SRong-En Fan <p>The code approximately looks like this:</p> 2938*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2939*4a1a9510SRong-En Fan MEVENT event; 2940*4a1a9510SRong-En Fan 2941*4a1a9510SRong-En Fan ch = getch(); 2942*4a1a9510SRong-En Fan if(ch == KEY_MOUSE) 2943*4a1a9510SRong-En Fan if(getmouse(&event) == OK) 2944*4a1a9510SRong-En Fan . /* Do some thing with the event */ 2945*4a1a9510SRong-En Fan . 2946*4a1a9510SRong-En Fan . 2947*4a1a9510SRong-En Fan</pre> 2948*4a1a9510SRong-En Fan 2949*4a1a9510SRong-En Fan <p>getmouse() returns the event into the pointer given to 2950*4a1a9510SRong-En Fan it. It's a structure which contains</p> 2951*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2952*4a1a9510SRong-En Fan typedef struct 2953*4a1a9510SRong-En Fan { 2954*4a1a9510SRong-En Fan short id; /* ID to distinguish multiple devices */ 2955*4a1a9510SRong-En Fan int x, y, z; /* event coordinates */ 2956*4a1a9510SRong-En Fan mmask_t bstate; /* button state bits */ 2957*4a1a9510SRong-En Fan } 2958*4a1a9510SRong-En Fan</pre> 2959*4a1a9510SRong-En Fan 2960*4a1a9510SRong-En Fan <p>The <tt class="LITERAL">bstate</tt> is the main variable 2961*4a1a9510SRong-En Fan we are interested in. It tells the button state of the 2962*4a1a9510SRong-En Fan mouse.</p> 2963*4a1a9510SRong-En Fan 2964*4a1a9510SRong-En Fan <p>Then with a code snippet like the following, we can find 2965*4a1a9510SRong-En Fan out what happened.</p> 2966*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2967*4a1a9510SRong-En Fan if(event.bstate & BUTTON1_PRESSED) 2968*4a1a9510SRong-En Fan printw("Left Button Pressed"); 2969*4a1a9510SRong-En Fan</pre> 2970*4a1a9510SRong-En Fan </div> 2971*4a1a9510SRong-En Fan 2972*4a1a9510SRong-En Fan <div class="SECT2"> 2973*4a1a9510SRong-En Fan <hr> 2974*4a1a9510SRong-En Fan 2975*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MOUSETOGETHER" id= 2976*4a1a9510SRong-En Fan "MOUSETOGETHER">12.3. Putting it all Together</a></h3> 2977*4a1a9510SRong-En Fan 2978*4a1a9510SRong-En Fan <p>That's pretty much interfacing with mouse. Let's create 2979*4a1a9510SRong-En Fan the same menu and enable mouse interaction. To make things 2980*4a1a9510SRong-En Fan simpler, key handling is removed.</p> 2981*4a1a9510SRong-En Fan 2982*4a1a9510SRong-En Fan <div class="EXAMPLE"> 2983*4a1a9510SRong-En Fan <a name="BMOME" id="BMOME"></a> 2984*4a1a9510SRong-En Fan 2985*4a1a9510SRong-En Fan <p><b>Example 11. Access the menu with mouse !!!</b></p> 2986*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 2987*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 2988*4a1a9510SRong-En Fan 2989*4a1a9510SRong-En Fan#define WIDTH 30 2990*4a1a9510SRong-En Fan#define HEIGHT 10 2991*4a1a9510SRong-En Fan 2992*4a1a9510SRong-En Fanint startx = 0; 2993*4a1a9510SRong-En Fanint starty = 0; 2994*4a1a9510SRong-En Fan 2995*4a1a9510SRong-En Fanchar *choices[] = { "Choice 1", 2996*4a1a9510SRong-En Fan "Choice 2", 2997*4a1a9510SRong-En Fan "Choice 3", 2998*4a1a9510SRong-En Fan "Choice 4", 2999*4a1a9510SRong-En Fan "Exit", 3000*4a1a9510SRong-En Fan }; 3001*4a1a9510SRong-En Fan 3002*4a1a9510SRong-En Fanint n_choices = sizeof(choices) / sizeof(char *); 3003*4a1a9510SRong-En Fan 3004*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight); 3005*4a1a9510SRong-En Fanvoid report_choice(int mouse_x, int mouse_y, int *p_choice); 3006*4a1a9510SRong-En Fan 3007*4a1a9510SRong-En Fanint main() 3008*4a1a9510SRong-En Fan{ int c, choice = 0; 3009*4a1a9510SRong-En Fan WINDOW *menu_win; 3010*4a1a9510SRong-En Fan MEVENT event; 3011*4a1a9510SRong-En Fan 3012*4a1a9510SRong-En Fan /* Initialize curses */ 3013*4a1a9510SRong-En Fan initscr(); 3014*4a1a9510SRong-En Fan clear(); 3015*4a1a9510SRong-En Fan noecho(); 3016*4a1a9510SRong-En Fan cbreak(); //Line buffering disabled. pass on everything 3017*4a1a9510SRong-En Fan 3018*4a1a9510SRong-En Fan /* Try to put the window in the middle of screen */ 3019*4a1a9510SRong-En Fan startx = (80 - WIDTH) / 2; 3020*4a1a9510SRong-En Fan starty = (24 - HEIGHT) / 2; 3021*4a1a9510SRong-En Fan 3022*4a1a9510SRong-En Fan attron(A_REVERSE); 3023*4a1a9510SRong-En Fan mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)"); 3024*4a1a9510SRong-En Fan refresh(); 3025*4a1a9510SRong-En Fan attroff(A_REVERSE); 3026*4a1a9510SRong-En Fan 3027*4a1a9510SRong-En Fan /* Print the menu for the first time */ 3028*4a1a9510SRong-En Fan menu_win = newwin(HEIGHT, WIDTH, starty, startx); 3029*4a1a9510SRong-En Fan print_menu(menu_win, 1); 3030*4a1a9510SRong-En Fan /* Get all the mouse events */ 3031*4a1a9510SRong-En Fan mousemask(ALL_MOUSE_EVENTS, NULL); 3032*4a1a9510SRong-En Fan 3033*4a1a9510SRong-En Fan while(1) 3034*4a1a9510SRong-En Fan { c = wgetch(menu_win); 3035*4a1a9510SRong-En Fan switch(c) 3036*4a1a9510SRong-En Fan { case KEY_MOUSE: 3037*4a1a9510SRong-En Fan if(getmouse(&event) == OK) 3038*4a1a9510SRong-En Fan { /* When the user clicks left mouse button */ 3039*4a1a9510SRong-En Fan if(event.bstate & BUTTON1_PRESSED) 3040*4a1a9510SRong-En Fan { report_choice(event.x + 1, event.y + 1, &choice); 3041*4a1a9510SRong-En Fan if(choice == -1) //Exit chosen 3042*4a1a9510SRong-En Fan goto end; 3043*4a1a9510SRong-En Fan mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]); 3044*4a1a9510SRong-En Fan refresh(); 3045*4a1a9510SRong-En Fan } 3046*4a1a9510SRong-En Fan } 3047*4a1a9510SRong-En Fan print_menu(menu_win, choice); 3048*4a1a9510SRong-En Fan break; 3049*4a1a9510SRong-En Fan } 3050*4a1a9510SRong-En Fan } 3051*4a1a9510SRong-En Fanend: 3052*4a1a9510SRong-En Fan endwin(); 3053*4a1a9510SRong-En Fan return 0; 3054*4a1a9510SRong-En Fan} 3055*4a1a9510SRong-En Fan 3056*4a1a9510SRong-En Fan 3057*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight) 3058*4a1a9510SRong-En Fan{ 3059*4a1a9510SRong-En Fan int x, y, i; 3060*4a1a9510SRong-En Fan 3061*4a1a9510SRong-En Fan x = 2; 3062*4a1a9510SRong-En Fan y = 2; 3063*4a1a9510SRong-En Fan box(menu_win, 0, 0); 3064*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 3065*4a1a9510SRong-En Fan { if(highlight == i + 1) 3066*4a1a9510SRong-En Fan { wattron(menu_win, A_REVERSE); 3067*4a1a9510SRong-En Fan mvwprintw(menu_win, y, x, "%s", choices[i]); 3068*4a1a9510SRong-En Fan wattroff(menu_win, A_REVERSE); 3069*4a1a9510SRong-En Fan } 3070*4a1a9510SRong-En Fan else 3071*4a1a9510SRong-En Fan mvwprintw(menu_win, y, x, "%s", choices[i]); 3072*4a1a9510SRong-En Fan ++y; 3073*4a1a9510SRong-En Fan } 3074*4a1a9510SRong-En Fan wrefresh(menu_win); 3075*4a1a9510SRong-En Fan} 3076*4a1a9510SRong-En Fan 3077*4a1a9510SRong-En Fan/* Report the choice according to mouse position */ 3078*4a1a9510SRong-En Fanvoid report_choice(int mouse_x, int mouse_y, int *p_choice) 3079*4a1a9510SRong-En Fan{ int i,j, choice; 3080*4a1a9510SRong-En Fan 3081*4a1a9510SRong-En Fan i = startx + 2; 3082*4a1a9510SRong-En Fan j = starty + 3; 3083*4a1a9510SRong-En Fan 3084*4a1a9510SRong-En Fan for(choice = 0; choice < n_choices; ++choice) 3085*4a1a9510SRong-En Fan if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice])) 3086*4a1a9510SRong-En Fan { if(choice == n_choices - 1) 3087*4a1a9510SRong-En Fan *p_choice = -1; 3088*4a1a9510SRong-En Fan else 3089*4a1a9510SRong-En Fan *p_choice = choice + 1; 3090*4a1a9510SRong-En Fan break; 3091*4a1a9510SRong-En Fan } 3092*4a1a9510SRong-En Fan}</span> 3093*4a1a9510SRong-En Fan</pre> 3094*4a1a9510SRong-En Fan </div> 3095*4a1a9510SRong-En Fan </div> 3096*4a1a9510SRong-En Fan 3097*4a1a9510SRong-En Fan <div class="SECT2"> 3098*4a1a9510SRong-En Fan <hr> 3099*4a1a9510SRong-En Fan 3100*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MISCMOUSEFUNCS" id= 3101*4a1a9510SRong-En Fan "MISCMOUSEFUNCS">12.4. Miscellaneous Functions</a></h3> 3102*4a1a9510SRong-En Fan 3103*4a1a9510SRong-En Fan <p>The functions mouse_trafo() and wmouse_trafo() can be 3104*4a1a9510SRong-En Fan used to convert to mouse co-ordinates to screen relative 3105*4a1a9510SRong-En Fan co-ordinates. See curs_mouse(3X) man page for details.</p> 3106*4a1a9510SRong-En Fan 3107*4a1a9510SRong-En Fan <p>The mouseinterval function sets the maximum time (in 3108*4a1a9510SRong-En Fan thousands of a second) that can elapse between press and 3109*4a1a9510SRong-En Fan release events in order for them to be recognized as a 3110*4a1a9510SRong-En Fan click. This function returns the previous interval value. 3111*4a1a9510SRong-En Fan The default is one fifth of a second.</p> 3112*4a1a9510SRong-En Fan </div> 3113*4a1a9510SRong-En Fan </div> 3114*4a1a9510SRong-En Fan 3115*4a1a9510SRong-En Fan <div class="SECT1"> 3116*4a1a9510SRong-En Fan <hr> 3117*4a1a9510SRong-En Fan 3118*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="SCREEN" id="SCREEN">13. Screen 3119*4a1a9510SRong-En Fan Manipulation</a></h2> 3120*4a1a9510SRong-En Fan 3121*4a1a9510SRong-En Fan <p>In this section, we will look into some functions, which 3122*4a1a9510SRong-En Fan allow us to manage the screen efficiently and to write some 3123*4a1a9510SRong-En Fan fancy programs. This is especially important in writing 3124*4a1a9510SRong-En Fan games.</p> 3125*4a1a9510SRong-En Fan 3126*4a1a9510SRong-En Fan <div class="SECT2"> 3127*4a1a9510SRong-En Fan <hr> 3128*4a1a9510SRong-En Fan 3129*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="GETYX" id="GETYX">13.1. getyx() 3130*4a1a9510SRong-En Fan functions</a></h3> 3131*4a1a9510SRong-En Fan 3132*4a1a9510SRong-En Fan <p>The function <tt class="LITERAL">getyx()</tt> can be 3133*4a1a9510SRong-En Fan used to find out the present cursor co-ordinates. It will 3134*4a1a9510SRong-En Fan fill the values of x and y co-ordinates in the arguments 3135*4a1a9510SRong-En Fan given to it. Since getyx() is a macro you don't have to 3136*4a1a9510SRong-En Fan pass the address of the variables. It can be called as</p> 3137*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3138*4a1a9510SRong-En Fan getyx(win, y, x); 3139*4a1a9510SRong-En Fan /* win: window pointer 3140*4a1a9510SRong-En Fan * y, x: y, x co-ordinates will be put into this variables 3141*4a1a9510SRong-En Fan */ 3142*4a1a9510SRong-En Fan</pre> 3143*4a1a9510SRong-En Fan 3144*4a1a9510SRong-En Fan <p>The function getparyx() gets the beginning co-ordinates 3145*4a1a9510SRong-En Fan of the sub window relative to the main window. This is some 3146*4a1a9510SRong-En Fan times useful to update a sub window. When designing fancy 3147*4a1a9510SRong-En Fan stuff like writing multiple menus, it becomes difficult to 3148*4a1a9510SRong-En Fan store the menu positions, their first option co-ordinates 3149*4a1a9510SRong-En Fan etc. A simple solution to this problem, is to create menus 3150*4a1a9510SRong-En Fan in sub windows and later find the starting co-ordinates of 3151*4a1a9510SRong-En Fan the menus by using getparyx().</p> 3152*4a1a9510SRong-En Fan 3153*4a1a9510SRong-En Fan <p>The functions getbegyx() and getmaxyx() store current 3154*4a1a9510SRong-En Fan window's beginning and maximum co-ordinates. These 3155*4a1a9510SRong-En Fan functions are useful in the same way as above in managing 3156*4a1a9510SRong-En Fan the windows and sub windows effectively.</p> 3157*4a1a9510SRong-En Fan </div> 3158*4a1a9510SRong-En Fan 3159*4a1a9510SRong-En Fan <div class="SECT2"> 3160*4a1a9510SRong-En Fan <hr> 3161*4a1a9510SRong-En Fan 3162*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="SCREENDUMP" id= 3163*4a1a9510SRong-En Fan "SCREENDUMP">13.2. Screen Dumping</a></h3> 3164*4a1a9510SRong-En Fan 3165*4a1a9510SRong-En Fan <p>While writing games, some times it becomes necessary to 3166*4a1a9510SRong-En Fan store the state of the screen and restore it back to the 3167*4a1a9510SRong-En Fan same state. The function scr_dump() can be used to dump the 3168*4a1a9510SRong-En Fan screen contents to a file given as an argument. Later it 3169*4a1a9510SRong-En Fan can be restored by scr_restore function. These two simple 3170*4a1a9510SRong-En Fan functions can be used effectively to maintain a fast moving 3171*4a1a9510SRong-En Fan game with changing scenarios.</p> 3172*4a1a9510SRong-En Fan </div> 3173*4a1a9510SRong-En Fan 3174*4a1a9510SRong-En Fan <div class="SECT2"> 3175*4a1a9510SRong-En Fan <hr> 3176*4a1a9510SRong-En Fan 3177*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="WINDOWDUMP" id= 3178*4a1a9510SRong-En Fan "WINDOWDUMP">13.3. Window Dumping</a></h3> 3179*4a1a9510SRong-En Fan 3180*4a1a9510SRong-En Fan <p>To store and restore windows, the functions <tt class= 3181*4a1a9510SRong-En Fan "LITERAL">putwin()</tt> and <tt class= 3182*4a1a9510SRong-En Fan "LITERAL">getwin()</tt> can be used. <tt class= 3183*4a1a9510SRong-En Fan "LITERAL">putwin()</tt> puts the present window state into 3184*4a1a9510SRong-En Fan a file, which can be later restored by <tt class= 3185*4a1a9510SRong-En Fan "LITERAL">getwin()</tt>.</p> 3186*4a1a9510SRong-En Fan 3187*4a1a9510SRong-En Fan <p>The function <tt class="LITERAL">copywin()</tt> can be 3188*4a1a9510SRong-En Fan used to copy a window completely onto another window. It 3189*4a1a9510SRong-En Fan takes the source and destination windows as parameters and 3190*4a1a9510SRong-En Fan according to the rectangle specified, it copies the 3191*4a1a9510SRong-En Fan rectangular region from source to destination window. It's 3192*4a1a9510SRong-En Fan last parameter specifies whether to overwrite or just 3193*4a1a9510SRong-En Fan overlay the contents on to the destination window. If this 3194*4a1a9510SRong-En Fan argument is true, then the copying is non-destructive.</p> 3195*4a1a9510SRong-En Fan </div> 3196*4a1a9510SRong-En Fan </div> 3197*4a1a9510SRong-En Fan 3198*4a1a9510SRong-En Fan <div class="SECT1"> 3199*4a1a9510SRong-En Fan <hr> 3200*4a1a9510SRong-En Fan 3201*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="MISC" id="MISC">14. Miscellaneous 3202*4a1a9510SRong-En Fan features</a></h2> 3203*4a1a9510SRong-En Fan 3204*4a1a9510SRong-En Fan <p>Now you know enough features to write a good curses 3205*4a1a9510SRong-En Fan program, with all bells and whistles. There are some 3206*4a1a9510SRong-En Fan miscellaneous functions which are useful in various cases. 3207*4a1a9510SRong-En Fan Let's go headlong into some of those.</p> 3208*4a1a9510SRong-En Fan 3209*4a1a9510SRong-En Fan <div class="SECT2"> 3210*4a1a9510SRong-En Fan <hr> 3211*4a1a9510SRong-En Fan 3212*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="CURSSET" id="CURSSET">14.1. 3213*4a1a9510SRong-En Fan curs_set()</a></h3> 3214*4a1a9510SRong-En Fan 3215*4a1a9510SRong-En Fan <p>This function can be used to make the cursor invisible. 3216*4a1a9510SRong-En Fan The parameter to this function should be</p> 3217*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3218*4a1a9510SRong-En Fan 0 : invisible or 3219*4a1a9510SRong-En Fan 1 : normal or 3220*4a1a9510SRong-En Fan 2 : very visible. 3221*4a1a9510SRong-En Fan</pre> 3222*4a1a9510SRong-En Fan </div> 3223*4a1a9510SRong-En Fan 3224*4a1a9510SRong-En Fan <div class="SECT2"> 3225*4a1a9510SRong-En Fan <hr> 3226*4a1a9510SRong-En Fan 3227*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="TEMPLEAVE" id="TEMPLEAVE">14.2. 3228*4a1a9510SRong-En Fan Temporarily Leaving Curses mode</a></h3> 3229*4a1a9510SRong-En Fan 3230*4a1a9510SRong-En Fan <p>Some times you may want to get back to cooked mode 3231*4a1a9510SRong-En Fan (normal line buffering mode) temporarily. In such a case 3232*4a1a9510SRong-En Fan you will first need to save the tty modes with a call to 3233*4a1a9510SRong-En Fan <tt class="LITERAL">def_prog_mode()</tt> and then call 3234*4a1a9510SRong-En Fan <tt class="LITERAL">endwin()</tt> to end the curses mode. 3235*4a1a9510SRong-En Fan This will leave you in the original tty mode. To get back 3236*4a1a9510SRong-En Fan to curses once you are done, call <tt class= 3237*4a1a9510SRong-En Fan "LITERAL">reset_prog_mode()</tt> . This function returns 3238*4a1a9510SRong-En Fan the tty to the state stored by <tt class= 3239*4a1a9510SRong-En Fan "LITERAL">def_prog_mode()</tt>. Then do refresh(), and you 3240*4a1a9510SRong-En Fan are back to the curses mode. Here is an example showing the 3241*4a1a9510SRong-En Fan sequence of things to be done.</p> 3242*4a1a9510SRong-En Fan 3243*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3244*4a1a9510SRong-En Fan <a name="BTELE" id="BTELE"></a> 3245*4a1a9510SRong-En Fan 3246*4a1a9510SRong-En Fan <p><b>Example 12. Temporarily Leaving Curses Mode</b></p> 3247*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3248*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 3249*4a1a9510SRong-En Fan 3250*4a1a9510SRong-En Fanint main() 3251*4a1a9510SRong-En Fan{ 3252*4a1a9510SRong-En Fan initscr(); /* Start curses mode */ 3253*4a1a9510SRong-En Fan printw("Hello World !!!\n"); /* Print Hello World */ 3254*4a1a9510SRong-En Fan refresh(); /* Print it on to the real screen */ 3255*4a1a9510SRong-En Fan def_prog_mode(); /* Save the tty modes */ 3256*4a1a9510SRong-En Fan endwin(); /* End curses mode temporarily */ 3257*4a1a9510SRong-En Fan system("/bin/sh"); /* Do whatever you like in cooked mode */ 3258*4a1a9510SRong-En Fan reset_prog_mode(); /* Return to the previous tty mode*/ 3259*4a1a9510SRong-En Fan /* stored by def_prog_mode() */ 3260*4a1a9510SRong-En Fan refresh(); /* Do refresh() to restore the */ 3261*4a1a9510SRong-En Fan /* Screen contents */ 3262*4a1a9510SRong-En Fan printw("Another String\n"); /* Back to curses use the full */ 3263*4a1a9510SRong-En Fan refresh(); /* capabilities of curses */ 3264*4a1a9510SRong-En Fan endwin(); /* End curses mode */ 3265*4a1a9510SRong-En Fan 3266*4a1a9510SRong-En Fan return 0; 3267*4a1a9510SRong-En Fan}</span> 3268*4a1a9510SRong-En Fan</pre> 3269*4a1a9510SRong-En Fan </div> 3270*4a1a9510SRong-En Fan </div> 3271*4a1a9510SRong-En Fan 3272*4a1a9510SRong-En Fan <div class="SECT2"> 3273*4a1a9510SRong-En Fan <hr> 3274*4a1a9510SRong-En Fan 3275*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="ACSVARS" id="ACSVARS">14.3. ACS_ 3276*4a1a9510SRong-En Fan variables</a></h3> 3277*4a1a9510SRong-En Fan 3278*4a1a9510SRong-En Fan <p>If you have ever programmed in DOS, you know about those 3279*4a1a9510SRong-En Fan nifty characters in extended character set. They are 3280*4a1a9510SRong-En Fan printable only on some terminals. NCURSES functions like 3281*4a1a9510SRong-En Fan <tt class="LITERAL">box()</tt> use these characters. All 3282*4a1a9510SRong-En Fan these variables start with ACS meaning alternative 3283*4a1a9510SRong-En Fan character set. You might have noticed me using these 3284*4a1a9510SRong-En Fan characters in some of the programs above. Here's an example 3285*4a1a9510SRong-En Fan showing all the characters.</p> 3286*4a1a9510SRong-En Fan 3287*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3288*4a1a9510SRong-En Fan <a name="BACSVARS" id="BACSVARS"></a> 3289*4a1a9510SRong-En Fan 3290*4a1a9510SRong-En Fan <p><b>Example 13. ACS Variables Example</b></p> 3291*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3292*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <ncurses.h> 3293*4a1a9510SRong-En Fan 3294*4a1a9510SRong-En Fanint main() 3295*4a1a9510SRong-En Fan{ 3296*4a1a9510SRong-En Fan initscr(); 3297*4a1a9510SRong-En Fan 3298*4a1a9510SRong-En Fan printw("Upper left corner "); addch(ACS_ULCORNER); printw("\n"); 3299*4a1a9510SRong-En Fan printw("Lower left corner "); addch(ACS_LLCORNER); printw("\n"); 3300*4a1a9510SRong-En Fan printw("Lower right corner "); addch(ACS_LRCORNER); printw("\n"); 3301*4a1a9510SRong-En Fan printw("Tee pointing right "); addch(ACS_LTEE); printw("\n"); 3302*4a1a9510SRong-En Fan printw("Tee pointing left "); addch(ACS_RTEE); printw("\n"); 3303*4a1a9510SRong-En Fan printw("Tee pointing up "); addch(ACS_BTEE); printw("\n"); 3304*4a1a9510SRong-En Fan printw("Tee pointing down "); addch(ACS_TTEE); printw("\n"); 3305*4a1a9510SRong-En Fan printw("Horizontal line "); addch(ACS_HLINE); printw("\n"); 3306*4a1a9510SRong-En Fan printw("Vertical line "); addch(ACS_VLINE); printw("\n"); 3307*4a1a9510SRong-En Fan printw("Large Plus or cross over "); addch(ACS_PLUS); printw("\n"); 3308*4a1a9510SRong-En Fan printw("Scan Line 1 "); addch(ACS_S1); printw("\n"); 3309*4a1a9510SRong-En Fan printw("Scan Line 3 "); addch(ACS_S3); printw("\n"); 3310*4a1a9510SRong-En Fan printw("Scan Line 7 "); addch(ACS_S7); printw("\n"); 3311*4a1a9510SRong-En Fan printw("Scan Line 9 "); addch(ACS_S9); printw("\n"); 3312*4a1a9510SRong-En Fan printw("Diamond "); addch(ACS_DIAMOND); printw("\n"); 3313*4a1a9510SRong-En Fan printw("Checker board (stipple) "); addch(ACS_CKBOARD); printw("\n"); 3314*4a1a9510SRong-En Fan printw("Degree Symbol "); addch(ACS_DEGREE); printw("\n"); 3315*4a1a9510SRong-En Fan printw("Plus/Minus Symbol "); addch(ACS_PLMINUS); printw("\n"); 3316*4a1a9510SRong-En Fan printw("Bullet "); addch(ACS_BULLET); printw("\n"); 3317*4a1a9510SRong-En Fan printw("Arrow Pointing Left "); addch(ACS_LARROW); printw("\n"); 3318*4a1a9510SRong-En Fan printw("Arrow Pointing Right "); addch(ACS_RARROW); printw("\n"); 3319*4a1a9510SRong-En Fan printw("Arrow Pointing Down "); addch(ACS_DARROW); printw("\n"); 3320*4a1a9510SRong-En Fan printw("Arrow Pointing Up "); addch(ACS_UARROW); printw("\n"); 3321*4a1a9510SRong-En Fan printw("Board of squares "); addch(ACS_BOARD); printw("\n"); 3322*4a1a9510SRong-En Fan printw("Lantern Symbol "); addch(ACS_LANTERN); printw("\n"); 3323*4a1a9510SRong-En Fan printw("Solid Square Block "); addch(ACS_BLOCK); printw("\n"); 3324*4a1a9510SRong-En Fan printw("Less/Equal sign "); addch(ACS_LEQUAL); printw("\n"); 3325*4a1a9510SRong-En Fan printw("Greater/Equal sign "); addch(ACS_GEQUAL); printw("\n"); 3326*4a1a9510SRong-En Fan printw("Pi "); addch(ACS_PI); printw("\n"); 3327*4a1a9510SRong-En Fan printw("Not equal "); addch(ACS_NEQUAL); printw("\n"); 3328*4a1a9510SRong-En Fan printw("UK pound sign "); addch(ACS_STERLING); printw("\n"); 3329*4a1a9510SRong-En Fan 3330*4a1a9510SRong-En Fan refresh(); 3331*4a1a9510SRong-En Fan getch(); 3332*4a1a9510SRong-En Fan endwin(); 3333*4a1a9510SRong-En Fan 3334*4a1a9510SRong-En Fan return 0; 3335*4a1a9510SRong-En Fan}</span> 3336*4a1a9510SRong-En Fan</pre> 3337*4a1a9510SRong-En Fan </div> 3338*4a1a9510SRong-En Fan </div> 3339*4a1a9510SRong-En Fan </div> 3340*4a1a9510SRong-En Fan 3341*4a1a9510SRong-En Fan <div class="SECT1"> 3342*4a1a9510SRong-En Fan <hr> 3343*4a1a9510SRong-En Fan 3344*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="OTHERLIB" id="OTHERLIB">15. Other 3345*4a1a9510SRong-En Fan libraries</a></h2> 3346*4a1a9510SRong-En Fan 3347*4a1a9510SRong-En Fan <p>Apart from the curses library, there are few text mode 3348*4a1a9510SRong-En Fan libraries, which provide more functionality and a lot of 3349*4a1a9510SRong-En Fan features. The following sections explain three standard 3350*4a1a9510SRong-En Fan libraries which are usually distributed along with 3351*4a1a9510SRong-En Fan curses.</p> 3352*4a1a9510SRong-En Fan </div> 3353*4a1a9510SRong-En Fan 3354*4a1a9510SRong-En Fan <div class="SECT1"> 3355*4a1a9510SRong-En Fan <hr> 3356*4a1a9510SRong-En Fan 3357*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="PANELS" id="PANELS">16. Panel 3358*4a1a9510SRong-En Fan Library</a></h2> 3359*4a1a9510SRong-En Fan 3360*4a1a9510SRong-En Fan <p>Now that you are proficient in curses, you wanted to do 3361*4a1a9510SRong-En Fan some thing big. You created a lot of overlapping windows to 3362*4a1a9510SRong-En Fan give a professional windows-type look. Unfortunately, it soon 3363*4a1a9510SRong-En Fan becomes difficult to manage these. The multiple refreshes, 3364*4a1a9510SRong-En Fan updates plunge you into a nightmare. The overlapping windows 3365*4a1a9510SRong-En Fan create blotches, whenever you forget to refresh the windows 3366*4a1a9510SRong-En Fan in the proper order.</p> 3367*4a1a9510SRong-En Fan 3368*4a1a9510SRong-En Fan <p>Don't despair. There's an elegant solution provided in 3369*4a1a9510SRong-En Fan panels library. In the words of developers of ncurses</p> 3370*4a1a9510SRong-En Fan 3371*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">When your 3372*4a1a9510SRong-En Fan interface design is such that windows may dive deeper into 3373*4a1a9510SRong-En Fan the visibility stack or pop to the top at runtime, the 3374*4a1a9510SRong-En Fan resulting book-keeping can be tedious and difficult to get 3375*4a1a9510SRong-En Fan right. Hence the panels library.</i></span></p> 3376*4a1a9510SRong-En Fan 3377*4a1a9510SRong-En Fan <p>If you have lot of overlapping windows, then panels 3378*4a1a9510SRong-En Fan library is the way to go. It obviates the need of doing 3379*4a1a9510SRong-En Fan series of wnoutrefresh(), doupdate() and relieves the burden 3380*4a1a9510SRong-En Fan of doing it correctly(bottom up). The library maintains 3381*4a1a9510SRong-En Fan information about the order of windows, their overlapping and 3382*4a1a9510SRong-En Fan update the screen properly. So why wait? Let's take a close 3383*4a1a9510SRong-En Fan peek into panels.</p> 3384*4a1a9510SRong-En Fan 3385*4a1a9510SRong-En Fan <div class="SECT2"> 3386*4a1a9510SRong-En Fan <hr> 3387*4a1a9510SRong-En Fan 3388*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PANELBASICS" id= 3389*4a1a9510SRong-En Fan "PANELBASICS">16.1. The Basics</a></h3> 3390*4a1a9510SRong-En Fan 3391*4a1a9510SRong-En Fan <p>Panel object is a window that is implicitly treated as 3392*4a1a9510SRong-En Fan part of a deck including all other panel objects. The deck 3393*4a1a9510SRong-En Fan is treated as a stack with the top panel being completely 3394*4a1a9510SRong-En Fan visible and the other panels may or may not be obscured 3395*4a1a9510SRong-En Fan according to their positions. So the basic idea is to 3396*4a1a9510SRong-En Fan create a stack of overlapping panels and use panels library 3397*4a1a9510SRong-En Fan to display them correctly. There is a function similar to 3398*4a1a9510SRong-En Fan refresh() which, when called , displays panels in the 3399*4a1a9510SRong-En Fan correct order. Functions are provided to hide or show 3400*4a1a9510SRong-En Fan panels, move panels, change its size etc.. The overlapping 3401*4a1a9510SRong-En Fan problem is managed by the panels library during all the 3402*4a1a9510SRong-En Fan calls to these functions.</p> 3403*4a1a9510SRong-En Fan 3404*4a1a9510SRong-En Fan <p>The general flow of a panel program goes like this:</p> 3405*4a1a9510SRong-En Fan 3406*4a1a9510SRong-En Fan <ol type="1"> 3407*4a1a9510SRong-En Fan <li> 3408*4a1a9510SRong-En Fan <p>Create the windows (with newwin()) to be attached to 3409*4a1a9510SRong-En Fan the panels.</p> 3410*4a1a9510SRong-En Fan </li> 3411*4a1a9510SRong-En Fan 3412*4a1a9510SRong-En Fan <li> 3413*4a1a9510SRong-En Fan <p>Create panels with the chosen visibility order. 3414*4a1a9510SRong-En Fan Stack them up according to the desired visibility. The 3415*4a1a9510SRong-En Fan function new_panel() is used to created panels.</p> 3416*4a1a9510SRong-En Fan </li> 3417*4a1a9510SRong-En Fan 3418*4a1a9510SRong-En Fan <li> 3419*4a1a9510SRong-En Fan <p>Call update_panels() to write the panels to the 3420*4a1a9510SRong-En Fan virtual screen in correct visibility order. Do a 3421*4a1a9510SRong-En Fan doupdate() to show it on the screen.</p> 3422*4a1a9510SRong-En Fan </li> 3423*4a1a9510SRong-En Fan 3424*4a1a9510SRong-En Fan <li> 3425*4a1a9510SRong-En Fan <p>Mainpulate the panels with show_panel(), 3426*4a1a9510SRong-En Fan hide_panel(), move_panel() etc. Make use of helper 3427*4a1a9510SRong-En Fan functions like panel_hidden() and panel_window(). Make 3428*4a1a9510SRong-En Fan use of user pointer to store custom data for a panel. 3429*4a1a9510SRong-En Fan Use the functions set_panel_userptr() and 3430*4a1a9510SRong-En Fan panel_userptr() to set and get the user pointer for a 3431*4a1a9510SRong-En Fan panel.</p> 3432*4a1a9510SRong-En Fan </li> 3433*4a1a9510SRong-En Fan 3434*4a1a9510SRong-En Fan <li> 3435*4a1a9510SRong-En Fan <p>When you are done with the panel use del_panel() to 3436*4a1a9510SRong-En Fan delete the panel.</p> 3437*4a1a9510SRong-En Fan </li> 3438*4a1a9510SRong-En Fan </ol> 3439*4a1a9510SRong-En Fan 3440*4a1a9510SRong-En Fan <p>Let's make the concepts clear, with some programs. The 3441*4a1a9510SRong-En Fan following is a simple program which creates 3 overlapping 3442*4a1a9510SRong-En Fan panels and shows them on the screen.</p> 3443*4a1a9510SRong-En Fan </div> 3444*4a1a9510SRong-En Fan 3445*4a1a9510SRong-En Fan <div class="SECT2"> 3446*4a1a9510SRong-En Fan <hr> 3447*4a1a9510SRong-En Fan 3448*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COMPILEPANELS" id= 3449*4a1a9510SRong-En Fan "COMPILEPANELS">16.2. Compiling With the Panels 3450*4a1a9510SRong-En Fan Library</a></h3> 3451*4a1a9510SRong-En Fan 3452*4a1a9510SRong-En Fan <p>To use panels library functions, you have to include 3453*4a1a9510SRong-En Fan panel.h and to link the program with panels library the 3454*4a1a9510SRong-En Fan flag -lpanel should be added along with -lncurses in that 3455*4a1a9510SRong-En Fan order.</p> 3456*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3457*4a1a9510SRong-En Fan #include <panel.h> 3458*4a1a9510SRong-En Fan . 3459*4a1a9510SRong-En Fan . 3460*4a1a9510SRong-En Fan . 3461*4a1a9510SRong-En Fan 3462*4a1a9510SRong-En Fan compile and link: gcc <program file> -lpanel -lncurses 3463*4a1a9510SRong-En Fan</pre> 3464*4a1a9510SRong-En Fan 3465*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3466*4a1a9510SRong-En Fan <a name="PPASI" id="PPASI"></a> 3467*4a1a9510SRong-En Fan 3468*4a1a9510SRong-En Fan <p><b>Example 14. Panel basics</b></p> 3469*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3470*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <panel.h> 3471*4a1a9510SRong-En Fan 3472*4a1a9510SRong-En Fanint main() 3473*4a1a9510SRong-En Fan{ WINDOW *my_wins[3]; 3474*4a1a9510SRong-En Fan PANEL *my_panels[3]; 3475*4a1a9510SRong-En Fan int lines = 10, cols = 40, y = 2, x = 4, i; 3476*4a1a9510SRong-En Fan 3477*4a1a9510SRong-En Fan initscr(); 3478*4a1a9510SRong-En Fan cbreak(); 3479*4a1a9510SRong-En Fan noecho(); 3480*4a1a9510SRong-En Fan 3481*4a1a9510SRong-En Fan /* Create windows for the panels */ 3482*4a1a9510SRong-En Fan my_wins[0] = newwin(lines, cols, y, x); 3483*4a1a9510SRong-En Fan my_wins[1] = newwin(lines, cols, y + 1, x + 5); 3484*4a1a9510SRong-En Fan my_wins[2] = newwin(lines, cols, y + 2, x + 10); 3485*4a1a9510SRong-En Fan 3486*4a1a9510SRong-En Fan /* 3487*4a1a9510SRong-En Fan * Create borders around the windows so that you can see the effect 3488*4a1a9510SRong-En Fan * of panels 3489*4a1a9510SRong-En Fan */ 3490*4a1a9510SRong-En Fan for(i = 0; i < 3; ++i) 3491*4a1a9510SRong-En Fan box(my_wins[i], 0, 0); 3492*4a1a9510SRong-En Fan 3493*4a1a9510SRong-En Fan /* Attach a panel to each window */ /* Order is bottom up */ 3494*4a1a9510SRong-En Fan my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 3495*4a1a9510SRong-En Fan my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 3496*4a1a9510SRong-En Fan my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 3497*4a1a9510SRong-En Fan 3498*4a1a9510SRong-En Fan /* Update the stacking order. 2nd panel will be on top */ 3499*4a1a9510SRong-En Fan update_panels(); 3500*4a1a9510SRong-En Fan 3501*4a1a9510SRong-En Fan /* Show it on the screen */ 3502*4a1a9510SRong-En Fan doupdate(); 3503*4a1a9510SRong-En Fan 3504*4a1a9510SRong-En Fan getch(); 3505*4a1a9510SRong-En Fan endwin(); 3506*4a1a9510SRong-En Fan} 3507*4a1a9510SRong-En Fan</span> 3508*4a1a9510SRong-En Fan</pre> 3509*4a1a9510SRong-En Fan </div> 3510*4a1a9510SRong-En Fan 3511*4a1a9510SRong-En Fan <p>As you can see, above program follows a simple flow as 3512*4a1a9510SRong-En Fan explained. The windows are created with newwin() and then 3513*4a1a9510SRong-En Fan they are attached to panels with new_panel(). As we attach 3514*4a1a9510SRong-En Fan one panel after another, the stack of panels gets updated. 3515*4a1a9510SRong-En Fan To put them on screen update_panels() and doupdate() are 3516*4a1a9510SRong-En Fan called.</p> 3517*4a1a9510SRong-En Fan </div> 3518*4a1a9510SRong-En Fan 3519*4a1a9510SRong-En Fan <div class="SECT2"> 3520*4a1a9510SRong-En Fan <hr> 3521*4a1a9510SRong-En Fan 3522*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PANELBROWSING" id= 3523*4a1a9510SRong-En Fan "PANELBROWSING">16.3. Panel Window Browsing</a></h3> 3524*4a1a9510SRong-En Fan 3525*4a1a9510SRong-En Fan <p>A slightly complicated example is given below. This 3526*4a1a9510SRong-En Fan program creates 3 windows which can be cycled through using 3527*4a1a9510SRong-En Fan tab. Have a look at the code.</p> 3528*4a1a9510SRong-En Fan 3529*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3530*4a1a9510SRong-En Fan <a name="PPABR" id="PPABR"></a> 3531*4a1a9510SRong-En Fan 3532*4a1a9510SRong-En Fan <p><b>Example 15. Panel Window Browsing Example</b></p> 3533*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3534*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <panel.h> 3535*4a1a9510SRong-En Fan 3536*4a1a9510SRong-En Fan#define NLINES 10 3537*4a1a9510SRong-En Fan#define NCOLS 40 3538*4a1a9510SRong-En Fan 3539*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n); 3540*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color); 3541*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 3542*4a1a9510SRong-En Fan 3543*4a1a9510SRong-En Fanint main() 3544*4a1a9510SRong-En Fan{ WINDOW *my_wins[3]; 3545*4a1a9510SRong-En Fan PANEL *my_panels[3]; 3546*4a1a9510SRong-En Fan PANEL *top; 3547*4a1a9510SRong-En Fan int ch; 3548*4a1a9510SRong-En Fan 3549*4a1a9510SRong-En Fan /* Initialize curses */ 3550*4a1a9510SRong-En Fan initscr(); 3551*4a1a9510SRong-En Fan start_color(); 3552*4a1a9510SRong-En Fan cbreak(); 3553*4a1a9510SRong-En Fan noecho(); 3554*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 3555*4a1a9510SRong-En Fan 3556*4a1a9510SRong-En Fan /* Initialize all the colors */ 3557*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 3558*4a1a9510SRong-En Fan init_pair(2, COLOR_GREEN, COLOR_BLACK); 3559*4a1a9510SRong-En Fan init_pair(3, COLOR_BLUE, COLOR_BLACK); 3560*4a1a9510SRong-En Fan init_pair(4, COLOR_CYAN, COLOR_BLACK); 3561*4a1a9510SRong-En Fan 3562*4a1a9510SRong-En Fan init_wins(my_wins, 3); 3563*4a1a9510SRong-En Fan 3564*4a1a9510SRong-En Fan /* Attach a panel to each window */ /* Order is bottom up */ 3565*4a1a9510SRong-En Fan my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 3566*4a1a9510SRong-En Fan my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 3567*4a1a9510SRong-En Fan my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 3568*4a1a9510SRong-En Fan 3569*4a1a9510SRong-En Fan /* Set up the user pointers to the next panel */ 3570*4a1a9510SRong-En Fan set_panel_userptr(my_panels[0], my_panels[1]); 3571*4a1a9510SRong-En Fan set_panel_userptr(my_panels[1], my_panels[2]); 3572*4a1a9510SRong-En Fan set_panel_userptr(my_panels[2], my_panels[0]); 3573*4a1a9510SRong-En Fan 3574*4a1a9510SRong-En Fan /* Update the stacking order. 2nd panel will be on top */ 3575*4a1a9510SRong-En Fan update_panels(); 3576*4a1a9510SRong-En Fan 3577*4a1a9510SRong-En Fan /* Show it on the screen */ 3578*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 3579*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 3580*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 3581*4a1a9510SRong-En Fan doupdate(); 3582*4a1a9510SRong-En Fan 3583*4a1a9510SRong-En Fan top = my_panels[2]; 3584*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 3585*4a1a9510SRong-En Fan { switch(ch) 3586*4a1a9510SRong-En Fan { case 9: 3587*4a1a9510SRong-En Fan top = (PANEL *)panel_userptr(top); 3588*4a1a9510SRong-En Fan top_panel(top); 3589*4a1a9510SRong-En Fan break; 3590*4a1a9510SRong-En Fan } 3591*4a1a9510SRong-En Fan update_panels(); 3592*4a1a9510SRong-En Fan doupdate(); 3593*4a1a9510SRong-En Fan } 3594*4a1a9510SRong-En Fan endwin(); 3595*4a1a9510SRong-En Fan return 0; 3596*4a1a9510SRong-En Fan} 3597*4a1a9510SRong-En Fan 3598*4a1a9510SRong-En Fan/* Put all the windows */ 3599*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n) 3600*4a1a9510SRong-En Fan{ int x, y, i; 3601*4a1a9510SRong-En Fan char label[80]; 3602*4a1a9510SRong-En Fan 3603*4a1a9510SRong-En Fan y = 2; 3604*4a1a9510SRong-En Fan x = 10; 3605*4a1a9510SRong-En Fan for(i = 0; i < n; ++i) 3606*4a1a9510SRong-En Fan { wins[i] = newwin(NLINES, NCOLS, y, x); 3607*4a1a9510SRong-En Fan sprintf(label, "Window Number %d", i + 1); 3608*4a1a9510SRong-En Fan win_show(wins[i], label, i + 1); 3609*4a1a9510SRong-En Fan y += 3; 3610*4a1a9510SRong-En Fan x += 7; 3611*4a1a9510SRong-En Fan } 3612*4a1a9510SRong-En Fan} 3613*4a1a9510SRong-En Fan 3614*4a1a9510SRong-En Fan/* Show the window with a border and a label */ 3615*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color) 3616*4a1a9510SRong-En Fan{ int startx, starty, height, width; 3617*4a1a9510SRong-En Fan 3618*4a1a9510SRong-En Fan getbegyx(win, starty, startx); 3619*4a1a9510SRong-En Fan getmaxyx(win, height, width); 3620*4a1a9510SRong-En Fan 3621*4a1a9510SRong-En Fan box(win, 0, 0); 3622*4a1a9510SRong-En Fan mvwaddch(win, 2, 0, ACS_LTEE); 3623*4a1a9510SRong-En Fan mvwhline(win, 2, 1, ACS_HLINE, width - 2); 3624*4a1a9510SRong-En Fan mvwaddch(win, 2, width - 1, ACS_RTEE); 3625*4a1a9510SRong-En Fan 3626*4a1a9510SRong-En Fan print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 3627*4a1a9510SRong-En Fan} 3628*4a1a9510SRong-En Fan 3629*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 3630*4a1a9510SRong-En Fan{ int length, x, y; 3631*4a1a9510SRong-En Fan float temp; 3632*4a1a9510SRong-En Fan 3633*4a1a9510SRong-En Fan if(win == NULL) 3634*4a1a9510SRong-En Fan win = stdscr; 3635*4a1a9510SRong-En Fan getyx(win, y, x); 3636*4a1a9510SRong-En Fan if(startx != 0) 3637*4a1a9510SRong-En Fan x = startx; 3638*4a1a9510SRong-En Fan if(starty != 0) 3639*4a1a9510SRong-En Fan y = starty; 3640*4a1a9510SRong-En Fan if(width == 0) 3641*4a1a9510SRong-En Fan width = 80; 3642*4a1a9510SRong-En Fan 3643*4a1a9510SRong-En Fan length = strlen(string); 3644*4a1a9510SRong-En Fan temp = (width - length)/ 2; 3645*4a1a9510SRong-En Fan x = startx + (int)temp; 3646*4a1a9510SRong-En Fan wattron(win, color); 3647*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 3648*4a1a9510SRong-En Fan wattroff(win, color); 3649*4a1a9510SRong-En Fan refresh(); 3650*4a1a9510SRong-En Fan}</span> 3651*4a1a9510SRong-En Fan</pre> 3652*4a1a9510SRong-En Fan </div> 3653*4a1a9510SRong-En Fan </div> 3654*4a1a9510SRong-En Fan 3655*4a1a9510SRong-En Fan <div class="SECT2"> 3656*4a1a9510SRong-En Fan <hr> 3657*4a1a9510SRong-En Fan 3658*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="USERPTRUSING" id= 3659*4a1a9510SRong-En Fan "USERPTRUSING">16.4. Using User Pointers</a></h3> 3660*4a1a9510SRong-En Fan 3661*4a1a9510SRong-En Fan <p>In the above example I used user pointers to find out 3662*4a1a9510SRong-En Fan the next window in the cycle. We can attach custom 3663*4a1a9510SRong-En Fan information to the panel by specifying a user pointer, 3664*4a1a9510SRong-En Fan which can point to any information you want to store. In 3665*4a1a9510SRong-En Fan this case I stored the pointer to the next panel in the 3666*4a1a9510SRong-En Fan cycle. User pointer for a panel can be set with the 3667*4a1a9510SRong-En Fan function <tt class="LITERAL">set_panel_userptr()</tt>. It 3668*4a1a9510SRong-En Fan can be accessed using the function <tt class= 3669*4a1a9510SRong-En Fan "LITERAL">panel_userptr()</tt> which will return the user 3670*4a1a9510SRong-En Fan pointer for the panel given as argument. After finding the 3671*4a1a9510SRong-En Fan next panel in the cycle It's brought to the top by the 3672*4a1a9510SRong-En Fan function top_panel(). This function brings the panel given 3673*4a1a9510SRong-En Fan as argument to the top of the panel stack.</p> 3674*4a1a9510SRong-En Fan </div> 3675*4a1a9510SRong-En Fan 3676*4a1a9510SRong-En Fan <div class="SECT2"> 3677*4a1a9510SRong-En Fan <hr> 3678*4a1a9510SRong-En Fan 3679*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PANELMOVERESIZE" id= 3680*4a1a9510SRong-En Fan "PANELMOVERESIZE">16.5. Moving and Resizing Panels</a></h3> 3681*4a1a9510SRong-En Fan 3682*4a1a9510SRong-En Fan <p>The function <tt class="LITERAL">move_panel()</tt> can 3683*4a1a9510SRong-En Fan be used to move a panel to the desired location. It does 3684*4a1a9510SRong-En Fan not change the position of the panel in the stack. Make 3685*4a1a9510SRong-En Fan sure that you use move_panel() instead mvwin() on the 3686*4a1a9510SRong-En Fan window associated with the panel.</p> 3687*4a1a9510SRong-En Fan 3688*4a1a9510SRong-En Fan <p>Resizing a panel is slightly complex. There is no 3689*4a1a9510SRong-En Fan straight forward function just to resize the window 3690*4a1a9510SRong-En Fan associated with a panel. A solution to resize a panel is to 3691*4a1a9510SRong-En Fan create a new window with the desired sizes, change the 3692*4a1a9510SRong-En Fan window associated with the panel using replace_panel(). 3693*4a1a9510SRong-En Fan Don't forget to delete the old window. The window 3694*4a1a9510SRong-En Fan associated with a panel can be found by using the function 3695*4a1a9510SRong-En Fan panel_window().</p> 3696*4a1a9510SRong-En Fan 3697*4a1a9510SRong-En Fan <p>The following program shows these concepts, in 3698*4a1a9510SRong-En Fan supposedly simple program. You can cycle through the window 3699*4a1a9510SRong-En Fan with <TAB> as usual. To resize or move the active 3700*4a1a9510SRong-En Fan panel press 'r' for resize 'm' for moving. Then use arrow 3701*4a1a9510SRong-En Fan keys to resize or move it to the desired way and press 3702*4a1a9510SRong-En Fan enter to end your resizing or moving. This example makes 3703*4a1a9510SRong-En Fan use of user data to get the required data to do the 3704*4a1a9510SRong-En Fan operations.</p> 3705*4a1a9510SRong-En Fan 3706*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3707*4a1a9510SRong-En Fan <a name="PPARE" id="PPARE"></a> 3708*4a1a9510SRong-En Fan 3709*4a1a9510SRong-En Fan <p><b>Example 16. Panel Moving and Resizing 3710*4a1a9510SRong-En Fan example</b></p> 3711*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 3712*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <panel.h> 3713*4a1a9510SRong-En Fan 3714*4a1a9510SRong-En Fantypedef struct _PANEL_DATA { 3715*4a1a9510SRong-En Fan int x, y, w, h; 3716*4a1a9510SRong-En Fan char label[80]; 3717*4a1a9510SRong-En Fan int label_color; 3718*4a1a9510SRong-En Fan PANEL *next; 3719*4a1a9510SRong-En Fan}PANEL_DATA; 3720*4a1a9510SRong-En Fan 3721*4a1a9510SRong-En Fan#define NLINES 10 3722*4a1a9510SRong-En Fan#define NCOLS 40 3723*4a1a9510SRong-En Fan 3724*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n); 3725*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color); 3726*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 3727*4a1a9510SRong-En Fanvoid set_user_ptrs(PANEL **panels, int n); 3728*4a1a9510SRong-En Fan 3729*4a1a9510SRong-En Fanint main() 3730*4a1a9510SRong-En Fan{ WINDOW *my_wins[3]; 3731*4a1a9510SRong-En Fan PANEL *my_panels[3]; 3732*4a1a9510SRong-En Fan PANEL_DATA *top; 3733*4a1a9510SRong-En Fan PANEL *stack_top; 3734*4a1a9510SRong-En Fan WINDOW *temp_win, *old_win; 3735*4a1a9510SRong-En Fan int ch; 3736*4a1a9510SRong-En Fan int newx, newy, neww, newh; 3737*4a1a9510SRong-En Fan int size = FALSE, move = FALSE; 3738*4a1a9510SRong-En Fan 3739*4a1a9510SRong-En Fan /* Initialize curses */ 3740*4a1a9510SRong-En Fan initscr(); 3741*4a1a9510SRong-En Fan start_color(); 3742*4a1a9510SRong-En Fan cbreak(); 3743*4a1a9510SRong-En Fan noecho(); 3744*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 3745*4a1a9510SRong-En Fan 3746*4a1a9510SRong-En Fan /* Initialize all the colors */ 3747*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 3748*4a1a9510SRong-En Fan init_pair(2, COLOR_GREEN, COLOR_BLACK); 3749*4a1a9510SRong-En Fan init_pair(3, COLOR_BLUE, COLOR_BLACK); 3750*4a1a9510SRong-En Fan init_pair(4, COLOR_CYAN, COLOR_BLACK); 3751*4a1a9510SRong-En Fan 3752*4a1a9510SRong-En Fan init_wins(my_wins, 3); 3753*4a1a9510SRong-En Fan 3754*4a1a9510SRong-En Fan /* Attach a panel to each window */ /* Order is bottom up */ 3755*4a1a9510SRong-En Fan my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 3756*4a1a9510SRong-En Fan my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 3757*4a1a9510SRong-En Fan my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 3758*4a1a9510SRong-En Fan 3759*4a1a9510SRong-En Fan set_user_ptrs(my_panels, 3); 3760*4a1a9510SRong-En Fan /* Update the stacking order. 2nd panel will be on top */ 3761*4a1a9510SRong-En Fan update_panels(); 3762*4a1a9510SRong-En Fan 3763*4a1a9510SRong-En Fan /* Show it on the screen */ 3764*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 3765*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing"); 3766*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 3767*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 3768*4a1a9510SRong-En Fan doupdate(); 3769*4a1a9510SRong-En Fan 3770*4a1a9510SRong-En Fan stack_top = my_panels[2]; 3771*4a1a9510SRong-En Fan top = (PANEL_DATA *)panel_userptr(stack_top); 3772*4a1a9510SRong-En Fan newx = top->x; 3773*4a1a9510SRong-En Fan newy = top->y; 3774*4a1a9510SRong-En Fan neww = top->w; 3775*4a1a9510SRong-En Fan newh = top->h; 3776*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 3777*4a1a9510SRong-En Fan { switch(ch) 3778*4a1a9510SRong-En Fan { case 9: /* Tab */ 3779*4a1a9510SRong-En Fan top = (PANEL_DATA *)panel_userptr(stack_top); 3780*4a1a9510SRong-En Fan top_panel(top->next); 3781*4a1a9510SRong-En Fan stack_top = top->next; 3782*4a1a9510SRong-En Fan top = (PANEL_DATA *)panel_userptr(stack_top); 3783*4a1a9510SRong-En Fan newx = top->x; 3784*4a1a9510SRong-En Fan newy = top->y; 3785*4a1a9510SRong-En Fan neww = top->w; 3786*4a1a9510SRong-En Fan newh = top->h; 3787*4a1a9510SRong-En Fan break; 3788*4a1a9510SRong-En Fan case 'r': /* Re-Size*/ 3789*4a1a9510SRong-En Fan size = TRUE; 3790*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 3791*4a1a9510SRong-En Fan mvprintw(LINES - 4, 0, "Entered Resizing :Use Arrow Keys to resize and press <ENTER> to end resizing"); 3792*4a1a9510SRong-En Fan refresh(); 3793*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 3794*4a1a9510SRong-En Fan break; 3795*4a1a9510SRong-En Fan case 'm': /* Move */ 3796*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 3797*4a1a9510SRong-En Fan mvprintw(LINES - 4, 0, "Entered Moving: Use Arrow Keys to Move and press <ENTER> to end moving"); 3798*4a1a9510SRong-En Fan refresh(); 3799*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 3800*4a1a9510SRong-En Fan move = TRUE; 3801*4a1a9510SRong-En Fan break; 3802*4a1a9510SRong-En Fan case KEY_LEFT: 3803*4a1a9510SRong-En Fan if(size == TRUE) 3804*4a1a9510SRong-En Fan { --newx; 3805*4a1a9510SRong-En Fan ++neww; 3806*4a1a9510SRong-En Fan } 3807*4a1a9510SRong-En Fan if(move == TRUE) 3808*4a1a9510SRong-En Fan --newx; 3809*4a1a9510SRong-En Fan break; 3810*4a1a9510SRong-En Fan case KEY_RIGHT: 3811*4a1a9510SRong-En Fan if(size == TRUE) 3812*4a1a9510SRong-En Fan { ++newx; 3813*4a1a9510SRong-En Fan --neww; 3814*4a1a9510SRong-En Fan } 3815*4a1a9510SRong-En Fan if(move == TRUE) 3816*4a1a9510SRong-En Fan ++newx; 3817*4a1a9510SRong-En Fan break; 3818*4a1a9510SRong-En Fan case KEY_UP: 3819*4a1a9510SRong-En Fan if(size == TRUE) 3820*4a1a9510SRong-En Fan { --newy; 3821*4a1a9510SRong-En Fan ++newh; 3822*4a1a9510SRong-En Fan } 3823*4a1a9510SRong-En Fan if(move == TRUE) 3824*4a1a9510SRong-En Fan --newy; 3825*4a1a9510SRong-En Fan break; 3826*4a1a9510SRong-En Fan case KEY_DOWN: 3827*4a1a9510SRong-En Fan if(size == TRUE) 3828*4a1a9510SRong-En Fan { ++newy; 3829*4a1a9510SRong-En Fan --newh; 3830*4a1a9510SRong-En Fan } 3831*4a1a9510SRong-En Fan if(move == TRUE) 3832*4a1a9510SRong-En Fan ++newy; 3833*4a1a9510SRong-En Fan break; 3834*4a1a9510SRong-En Fan case 10: /* Enter */ 3835*4a1a9510SRong-En Fan move(LINES - 4, 0); 3836*4a1a9510SRong-En Fan clrtoeol(); 3837*4a1a9510SRong-En Fan refresh(); 3838*4a1a9510SRong-En Fan if(size == TRUE) 3839*4a1a9510SRong-En Fan { old_win = panel_window(stack_top); 3840*4a1a9510SRong-En Fan temp_win = newwin(newh, neww, newy, newx); 3841*4a1a9510SRong-En Fan replace_panel(stack_top, temp_win); 3842*4a1a9510SRong-En Fan win_show(temp_win, top->label, top->label_color); 3843*4a1a9510SRong-En Fan delwin(old_win); 3844*4a1a9510SRong-En Fan size = FALSE; 3845*4a1a9510SRong-En Fan } 3846*4a1a9510SRong-En Fan if(move == TRUE) 3847*4a1a9510SRong-En Fan { move_panel(stack_top, newy, newx); 3848*4a1a9510SRong-En Fan move = FALSE; 3849*4a1a9510SRong-En Fan } 3850*4a1a9510SRong-En Fan break; 3851*4a1a9510SRong-En Fan 3852*4a1a9510SRong-En Fan } 3853*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 3854*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing"); 3855*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 3856*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 3857*4a1a9510SRong-En Fan refresh(); 3858*4a1a9510SRong-En Fan update_panels(); 3859*4a1a9510SRong-En Fan doupdate(); 3860*4a1a9510SRong-En Fan } 3861*4a1a9510SRong-En Fan endwin(); 3862*4a1a9510SRong-En Fan return 0; 3863*4a1a9510SRong-En Fan} 3864*4a1a9510SRong-En Fan 3865*4a1a9510SRong-En Fan/* Put all the windows */ 3866*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n) 3867*4a1a9510SRong-En Fan{ int x, y, i; 3868*4a1a9510SRong-En Fan char label[80]; 3869*4a1a9510SRong-En Fan 3870*4a1a9510SRong-En Fan y = 2; 3871*4a1a9510SRong-En Fan x = 10; 3872*4a1a9510SRong-En Fan for(i = 0; i < n; ++i) 3873*4a1a9510SRong-En Fan { wins[i] = newwin(NLINES, NCOLS, y, x); 3874*4a1a9510SRong-En Fan sprintf(label, "Window Number %d", i + 1); 3875*4a1a9510SRong-En Fan win_show(wins[i], label, i + 1); 3876*4a1a9510SRong-En Fan y += 3; 3877*4a1a9510SRong-En Fan x += 7; 3878*4a1a9510SRong-En Fan } 3879*4a1a9510SRong-En Fan} 3880*4a1a9510SRong-En Fan 3881*4a1a9510SRong-En Fan/* Set the PANEL_DATA structures for individual panels */ 3882*4a1a9510SRong-En Fanvoid set_user_ptrs(PANEL **panels, int n) 3883*4a1a9510SRong-En Fan{ PANEL_DATA *ptrs; 3884*4a1a9510SRong-En Fan WINDOW *win; 3885*4a1a9510SRong-En Fan int x, y, w, h, i; 3886*4a1a9510SRong-En Fan char temp[80]; 3887*4a1a9510SRong-En Fan 3888*4a1a9510SRong-En Fan ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA)); 3889*4a1a9510SRong-En Fan 3890*4a1a9510SRong-En Fan for(i = 0;i < n; ++i) 3891*4a1a9510SRong-En Fan { win = panel_window(panels[i]); 3892*4a1a9510SRong-En Fan getbegyx(win, y, x); 3893*4a1a9510SRong-En Fan getmaxyx(win, h, w); 3894*4a1a9510SRong-En Fan ptrs[i].x = x; 3895*4a1a9510SRong-En Fan ptrs[i].y = y; 3896*4a1a9510SRong-En Fan ptrs[i].w = w; 3897*4a1a9510SRong-En Fan ptrs[i].h = h; 3898*4a1a9510SRong-En Fan sprintf(temp, "Window Number %d", i + 1); 3899*4a1a9510SRong-En Fan strcpy(ptrs[i].label, temp); 3900*4a1a9510SRong-En Fan ptrs[i].label_color = i + 1; 3901*4a1a9510SRong-En Fan if(i + 1 == n) 3902*4a1a9510SRong-En Fan ptrs[i].next = panels[0]; 3903*4a1a9510SRong-En Fan else 3904*4a1a9510SRong-En Fan ptrs[i].next = panels[i + 1]; 3905*4a1a9510SRong-En Fan set_panel_userptr(panels[i], &ptrs[i]); 3906*4a1a9510SRong-En Fan } 3907*4a1a9510SRong-En Fan} 3908*4a1a9510SRong-En Fan 3909*4a1a9510SRong-En Fan/* Show the window with a border and a label */ 3910*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color) 3911*4a1a9510SRong-En Fan{ int startx, starty, height, width; 3912*4a1a9510SRong-En Fan 3913*4a1a9510SRong-En Fan getbegyx(win, starty, startx); 3914*4a1a9510SRong-En Fan getmaxyx(win, height, width); 3915*4a1a9510SRong-En Fan 3916*4a1a9510SRong-En Fan box(win, 0, 0); 3917*4a1a9510SRong-En Fan mvwaddch(win, 2, 0, ACS_LTEE); 3918*4a1a9510SRong-En Fan mvwhline(win, 2, 1, ACS_HLINE, width - 2); 3919*4a1a9510SRong-En Fan mvwaddch(win, 2, width - 1, ACS_RTEE); 3920*4a1a9510SRong-En Fan 3921*4a1a9510SRong-En Fan print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 3922*4a1a9510SRong-En Fan} 3923*4a1a9510SRong-En Fan 3924*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 3925*4a1a9510SRong-En Fan{ int length, x, y; 3926*4a1a9510SRong-En Fan float temp; 3927*4a1a9510SRong-En Fan 3928*4a1a9510SRong-En Fan if(win == NULL) 3929*4a1a9510SRong-En Fan win = stdscr; 3930*4a1a9510SRong-En Fan getyx(win, y, x); 3931*4a1a9510SRong-En Fan if(startx != 0) 3932*4a1a9510SRong-En Fan x = startx; 3933*4a1a9510SRong-En Fan if(starty != 0) 3934*4a1a9510SRong-En Fan y = starty; 3935*4a1a9510SRong-En Fan if(width == 0) 3936*4a1a9510SRong-En Fan width = 80; 3937*4a1a9510SRong-En Fan 3938*4a1a9510SRong-En Fan length = strlen(string); 3939*4a1a9510SRong-En Fan temp = (width - length)/ 2; 3940*4a1a9510SRong-En Fan x = startx + (int)temp; 3941*4a1a9510SRong-En Fan wattron(win, color); 3942*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 3943*4a1a9510SRong-En Fan wattroff(win, color); 3944*4a1a9510SRong-En Fan refresh(); 3945*4a1a9510SRong-En Fan}</span> 3946*4a1a9510SRong-En Fan</pre> 3947*4a1a9510SRong-En Fan </div> 3948*4a1a9510SRong-En Fan 3949*4a1a9510SRong-En Fan <p>Concentrate on the main while loop. Once it finds out 3950*4a1a9510SRong-En Fan the type of key pressed, it takes appropriate action. If 3951*4a1a9510SRong-En Fan 'r' is pressed resizing mode is started. After this the new 3952*4a1a9510SRong-En Fan sizes are updated as the user presses the arrow keys. When 3953*4a1a9510SRong-En Fan the user presses <ENTER> present selection ends and 3954*4a1a9510SRong-En Fan panel is resized by using the concept explained. While in 3955*4a1a9510SRong-En Fan resizing mode the program doesn't show how the window is 3956*4a1a9510SRong-En Fan getting resized. It's left as an exercise to the reader to 3957*4a1a9510SRong-En Fan print a dotted border while it gets resized to a new 3958*4a1a9510SRong-En Fan position.</p> 3959*4a1a9510SRong-En Fan 3960*4a1a9510SRong-En Fan <p>When the user presses 'm' the move mode starts. This is 3961*4a1a9510SRong-En Fan a bit simpler than resizing. As the arrow keys are pressed 3962*4a1a9510SRong-En Fan the new position is updated and pressing of <ENTER> 3963*4a1a9510SRong-En Fan causes the panel to be moved by calling the function 3964*4a1a9510SRong-En Fan move_panel().</p> 3965*4a1a9510SRong-En Fan 3966*4a1a9510SRong-En Fan <p>In this program the user data which is represented as 3967*4a1a9510SRong-En Fan PANEL_DATA, plays very important role in finding the 3968*4a1a9510SRong-En Fan associated information with a panel. As written in the 3969*4a1a9510SRong-En Fan comments, the PANEL_DATA stores the panel sizes, label, 3970*4a1a9510SRong-En Fan label color and a pointer to the next panel in the 3971*4a1a9510SRong-En Fan cycle.</p> 3972*4a1a9510SRong-En Fan </div> 3973*4a1a9510SRong-En Fan 3974*4a1a9510SRong-En Fan <div class="SECT2"> 3975*4a1a9510SRong-En Fan <hr> 3976*4a1a9510SRong-En Fan 3977*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PANELSHOWHIDE" id= 3978*4a1a9510SRong-En Fan "PANELSHOWHIDE">16.6. Hiding and Showing Panels</a></h3> 3979*4a1a9510SRong-En Fan 3980*4a1a9510SRong-En Fan <p>A Panel can be hidden by using the function 3981*4a1a9510SRong-En Fan hide_panel(). This function merely removes it form the 3982*4a1a9510SRong-En Fan stack of panels, thus hiding it on the screen once you do 3983*4a1a9510SRong-En Fan update_panels() and doupdate(). It doesn't destroy the 3984*4a1a9510SRong-En Fan PANEL structure associated with the hidden panel. It can be 3985*4a1a9510SRong-En Fan shown again by using the show_panel() function.</p> 3986*4a1a9510SRong-En Fan 3987*4a1a9510SRong-En Fan <p>The following program shows the hiding of panels. Press 3988*4a1a9510SRong-En Fan 'a' or 'b' or 'c' to show or hide first, second and third 3989*4a1a9510SRong-En Fan windows respectively. It uses a user data with a small 3990*4a1a9510SRong-En Fan variable hide, which keeps track of whether the window is 3991*4a1a9510SRong-En Fan hidden or not. For some reason the function <tt class= 3992*4a1a9510SRong-En Fan "LITERAL">panel_hidden()</tt> which tells whether a panel 3993*4a1a9510SRong-En Fan is hidden or not is not working. A bug report was also 3994*4a1a9510SRong-En Fan presented by Michael Andres <a href= 3995*4a1a9510SRong-En Fan "http://www.geocrawler.com/archives/3/344/1999/9/0/2643549/" 3996*4a1a9510SRong-En Fan target="_top">here</a></p> 3997*4a1a9510SRong-En Fan 3998*4a1a9510SRong-En Fan <div class="EXAMPLE"> 3999*4a1a9510SRong-En Fan <a name="PPAHI" id="PPAHI"></a> 4000*4a1a9510SRong-En Fan 4001*4a1a9510SRong-En Fan <p><b>Example 17. Panel Hiding and Showing 4002*4a1a9510SRong-En Fan example</b></p> 4003*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4004*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <panel.h> 4005*4a1a9510SRong-En Fan 4006*4a1a9510SRong-En Fantypedef struct _PANEL_DATA { 4007*4a1a9510SRong-En Fan int hide; /* TRUE if panel is hidden */ 4008*4a1a9510SRong-En Fan}PANEL_DATA; 4009*4a1a9510SRong-En Fan 4010*4a1a9510SRong-En Fan#define NLINES 10 4011*4a1a9510SRong-En Fan#define NCOLS 40 4012*4a1a9510SRong-En Fan 4013*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n); 4014*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color); 4015*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4016*4a1a9510SRong-En Fan 4017*4a1a9510SRong-En Fanint main() 4018*4a1a9510SRong-En Fan{ WINDOW *my_wins[3]; 4019*4a1a9510SRong-En Fan PANEL *my_panels[3]; 4020*4a1a9510SRong-En Fan PANEL_DATA panel_datas[3]; 4021*4a1a9510SRong-En Fan PANEL_DATA *temp; 4022*4a1a9510SRong-En Fan int ch; 4023*4a1a9510SRong-En Fan 4024*4a1a9510SRong-En Fan /* Initialize curses */ 4025*4a1a9510SRong-En Fan initscr(); 4026*4a1a9510SRong-En Fan start_color(); 4027*4a1a9510SRong-En Fan cbreak(); 4028*4a1a9510SRong-En Fan noecho(); 4029*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 4030*4a1a9510SRong-En Fan 4031*4a1a9510SRong-En Fan /* Initialize all the colors */ 4032*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 4033*4a1a9510SRong-En Fan init_pair(2, COLOR_GREEN, COLOR_BLACK); 4034*4a1a9510SRong-En Fan init_pair(3, COLOR_BLUE, COLOR_BLACK); 4035*4a1a9510SRong-En Fan init_pair(4, COLOR_CYAN, COLOR_BLACK); 4036*4a1a9510SRong-En Fan 4037*4a1a9510SRong-En Fan init_wins(my_wins, 3); 4038*4a1a9510SRong-En Fan 4039*4a1a9510SRong-En Fan /* Attach a panel to each window */ /* Order is bottom up */ 4040*4a1a9510SRong-En Fan my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 4041*4a1a9510SRong-En Fan my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 4042*4a1a9510SRong-En Fan my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 4043*4a1a9510SRong-En Fan 4044*4a1a9510SRong-En Fan /* Initialize panel datas saying that nothing is hidden */ 4045*4a1a9510SRong-En Fan panel_datas[0].hide = FALSE; 4046*4a1a9510SRong-En Fan panel_datas[1].hide = FALSE; 4047*4a1a9510SRong-En Fan panel_datas[2].hide = FALSE; 4048*4a1a9510SRong-En Fan 4049*4a1a9510SRong-En Fan set_panel_userptr(my_panels[0], &panel_datas[0]); 4050*4a1a9510SRong-En Fan set_panel_userptr(my_panels[1], &panel_datas[1]); 4051*4a1a9510SRong-En Fan set_panel_userptr(my_panels[2], &panel_datas[2]); 4052*4a1a9510SRong-En Fan 4053*4a1a9510SRong-En Fan /* Update the stacking order. 2nd panel will be on top */ 4054*4a1a9510SRong-En Fan update_panels(); 4055*4a1a9510SRong-En Fan 4056*4a1a9510SRong-En Fan /* Show it on the screen */ 4057*4a1a9510SRong-En Fan attron(COLOR_PAIR(4)); 4058*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Show or Hide a window with 'a'(first window) 'b'(Second Window) 'c'(Third Window)"); 4059*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "F1 to Exit"); 4060*4a1a9510SRong-En Fan 4061*4a1a9510SRong-En Fan attroff(COLOR_PAIR(4)); 4062*4a1a9510SRong-En Fan doupdate(); 4063*4a1a9510SRong-En Fan 4064*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 4065*4a1a9510SRong-En Fan { switch(ch) 4066*4a1a9510SRong-En Fan { case 'a': 4067*4a1a9510SRong-En Fan temp = (PANEL_DATA *)panel_userptr(my_panels[0]); 4068*4a1a9510SRong-En Fan if(temp->hide == FALSE) 4069*4a1a9510SRong-En Fan { hide_panel(my_panels[0]); 4070*4a1a9510SRong-En Fan temp->hide = TRUE; 4071*4a1a9510SRong-En Fan } 4072*4a1a9510SRong-En Fan else 4073*4a1a9510SRong-En Fan { show_panel(my_panels[0]); 4074*4a1a9510SRong-En Fan temp->hide = FALSE; 4075*4a1a9510SRong-En Fan } 4076*4a1a9510SRong-En Fan break; 4077*4a1a9510SRong-En Fan case 'b': 4078*4a1a9510SRong-En Fan temp = (PANEL_DATA *)panel_userptr(my_panels[1]); 4079*4a1a9510SRong-En Fan if(temp->hide == FALSE) 4080*4a1a9510SRong-En Fan { hide_panel(my_panels[1]); 4081*4a1a9510SRong-En Fan temp->hide = TRUE; 4082*4a1a9510SRong-En Fan } 4083*4a1a9510SRong-En Fan else 4084*4a1a9510SRong-En Fan { show_panel(my_panels[1]); 4085*4a1a9510SRong-En Fan temp->hide = FALSE; 4086*4a1a9510SRong-En Fan } 4087*4a1a9510SRong-En Fan break; 4088*4a1a9510SRong-En Fan case 'c': 4089*4a1a9510SRong-En Fan temp = (PANEL_DATA *)panel_userptr(my_panels[2]); 4090*4a1a9510SRong-En Fan if(temp->hide == FALSE) 4091*4a1a9510SRong-En Fan { hide_panel(my_panels[2]); 4092*4a1a9510SRong-En Fan temp->hide = TRUE; 4093*4a1a9510SRong-En Fan } 4094*4a1a9510SRong-En Fan else 4095*4a1a9510SRong-En Fan { show_panel(my_panels[2]); 4096*4a1a9510SRong-En Fan temp->hide = FALSE; 4097*4a1a9510SRong-En Fan } 4098*4a1a9510SRong-En Fan break; 4099*4a1a9510SRong-En Fan } 4100*4a1a9510SRong-En Fan update_panels(); 4101*4a1a9510SRong-En Fan doupdate(); 4102*4a1a9510SRong-En Fan } 4103*4a1a9510SRong-En Fan endwin(); 4104*4a1a9510SRong-En Fan return 0; 4105*4a1a9510SRong-En Fan} 4106*4a1a9510SRong-En Fan 4107*4a1a9510SRong-En Fan/* Put all the windows */ 4108*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n) 4109*4a1a9510SRong-En Fan{ int x, y, i; 4110*4a1a9510SRong-En Fan char label[80]; 4111*4a1a9510SRong-En Fan 4112*4a1a9510SRong-En Fan y = 2; 4113*4a1a9510SRong-En Fan x = 10; 4114*4a1a9510SRong-En Fan for(i = 0; i < n; ++i) 4115*4a1a9510SRong-En Fan { wins[i] = newwin(NLINES, NCOLS, y, x); 4116*4a1a9510SRong-En Fan sprintf(label, "Window Number %d", i + 1); 4117*4a1a9510SRong-En Fan win_show(wins[i], label, i + 1); 4118*4a1a9510SRong-En Fan y += 3; 4119*4a1a9510SRong-En Fan x += 7; 4120*4a1a9510SRong-En Fan } 4121*4a1a9510SRong-En Fan} 4122*4a1a9510SRong-En Fan 4123*4a1a9510SRong-En Fan/* Show the window with a border and a label */ 4124*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color) 4125*4a1a9510SRong-En Fan{ int startx, starty, height, width; 4126*4a1a9510SRong-En Fan 4127*4a1a9510SRong-En Fan getbegyx(win, starty, startx); 4128*4a1a9510SRong-En Fan getmaxyx(win, height, width); 4129*4a1a9510SRong-En Fan 4130*4a1a9510SRong-En Fan box(win, 0, 0); 4131*4a1a9510SRong-En Fan mvwaddch(win, 2, 0, ACS_LTEE); 4132*4a1a9510SRong-En Fan mvwhline(win, 2, 1, ACS_HLINE, width - 2); 4133*4a1a9510SRong-En Fan mvwaddch(win, 2, width - 1, ACS_RTEE); 4134*4a1a9510SRong-En Fan 4135*4a1a9510SRong-En Fan print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 4136*4a1a9510SRong-En Fan} 4137*4a1a9510SRong-En Fan 4138*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 4139*4a1a9510SRong-En Fan{ int length, x, y; 4140*4a1a9510SRong-En Fan float temp; 4141*4a1a9510SRong-En Fan 4142*4a1a9510SRong-En Fan if(win == NULL) 4143*4a1a9510SRong-En Fan win = stdscr; 4144*4a1a9510SRong-En Fan getyx(win, y, x); 4145*4a1a9510SRong-En Fan if(startx != 0) 4146*4a1a9510SRong-En Fan x = startx; 4147*4a1a9510SRong-En Fan if(starty != 0) 4148*4a1a9510SRong-En Fan y = starty; 4149*4a1a9510SRong-En Fan if(width == 0) 4150*4a1a9510SRong-En Fan width = 80; 4151*4a1a9510SRong-En Fan 4152*4a1a9510SRong-En Fan length = strlen(string); 4153*4a1a9510SRong-En Fan temp = (width - length)/ 2; 4154*4a1a9510SRong-En Fan x = startx + (int)temp; 4155*4a1a9510SRong-En Fan wattron(win, color); 4156*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 4157*4a1a9510SRong-En Fan wattroff(win, color); 4158*4a1a9510SRong-En Fan refresh(); 4159*4a1a9510SRong-En Fan}</span> 4160*4a1a9510SRong-En Fan</pre> 4161*4a1a9510SRong-En Fan </div> 4162*4a1a9510SRong-En Fan </div> 4163*4a1a9510SRong-En Fan 4164*4a1a9510SRong-En Fan <div class="SECT2"> 4165*4a1a9510SRong-En Fan <hr> 4166*4a1a9510SRong-En Fan 4167*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PANELABOVE" id= 4168*4a1a9510SRong-En Fan "PANELABOVE">16.7. panel_above() and panel_below() 4169*4a1a9510SRong-En Fan Functions</a></h3> 4170*4a1a9510SRong-En Fan 4171*4a1a9510SRong-En Fan <p>The functions <tt class="LITERAL">panel_above()</tt> and 4172*4a1a9510SRong-En Fan <tt class="LITERAL">panel_below()</tt> can be used to find 4173*4a1a9510SRong-En Fan out the panel above and below a panel. If the argument to 4174*4a1a9510SRong-En Fan these functions is NULL, then they return a pointer to 4175*4a1a9510SRong-En Fan bottom panel and top panel respectively.</p> 4176*4a1a9510SRong-En Fan </div> 4177*4a1a9510SRong-En Fan </div> 4178*4a1a9510SRong-En Fan 4179*4a1a9510SRong-En Fan <div class="SECT1"> 4180*4a1a9510SRong-En Fan <hr> 4181*4a1a9510SRong-En Fan 4182*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="MENUS" id="MENUS">17. Menus 4183*4a1a9510SRong-En Fan Library</a></h2> 4184*4a1a9510SRong-En Fan 4185*4a1a9510SRong-En Fan <p>The menus library provides a nice extension to basic 4186*4a1a9510SRong-En Fan curses, through which you can create menus. It provides a set 4187*4a1a9510SRong-En Fan of functions to create menus. But they have to be customized 4188*4a1a9510SRong-En Fan to give a nicer look, with colors etc. Let's get into the 4189*4a1a9510SRong-En Fan details.</p> 4190*4a1a9510SRong-En Fan 4191*4a1a9510SRong-En Fan <p>A menu is a screen display that assists the user to choose 4192*4a1a9510SRong-En Fan some subset of a given set of items. To put it simple, a menu 4193*4a1a9510SRong-En Fan is a collection of items from which one or more items can be 4194*4a1a9510SRong-En Fan chosen. Some readers might not be aware of multiple item 4195*4a1a9510SRong-En Fan selection capability. Menu library provides functionality to 4196*4a1a9510SRong-En Fan write menus from which the user can chose more than one item 4197*4a1a9510SRong-En Fan as the preferred choice. This is dealt with in a later 4198*4a1a9510SRong-En Fan section. Now it is time for some rudiments.</p> 4199*4a1a9510SRong-En Fan 4200*4a1a9510SRong-En Fan <div class="SECT2"> 4201*4a1a9510SRong-En Fan <hr> 4202*4a1a9510SRong-En Fan 4203*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MENUBASICS" id= 4204*4a1a9510SRong-En Fan "MENUBASICS">17.1. The Basics</a></h3> 4205*4a1a9510SRong-En Fan 4206*4a1a9510SRong-En Fan <p>To create menus, you first create items, and then post 4207*4a1a9510SRong-En Fan the menu to the display. After that, all the processing of 4208*4a1a9510SRong-En Fan user responses is done in an elegant function menu_driver() 4209*4a1a9510SRong-En Fan which is the work horse of any menu program.</p> 4210*4a1a9510SRong-En Fan 4211*4a1a9510SRong-En Fan <p>The general flow of control of a menu program looks like 4212*4a1a9510SRong-En Fan this.</p> 4213*4a1a9510SRong-En Fan 4214*4a1a9510SRong-En Fan <ol type="1"> 4215*4a1a9510SRong-En Fan <li> 4216*4a1a9510SRong-En Fan <p>Initialize curses</p> 4217*4a1a9510SRong-En Fan </li> 4218*4a1a9510SRong-En Fan 4219*4a1a9510SRong-En Fan <li> 4220*4a1a9510SRong-En Fan <p>Create items using new_item(). You can specify a 4221*4a1a9510SRong-En Fan name and description for the items.</p> 4222*4a1a9510SRong-En Fan </li> 4223*4a1a9510SRong-En Fan 4224*4a1a9510SRong-En Fan <li> 4225*4a1a9510SRong-En Fan <p>Create the menu with new_menu() by specifying the 4226*4a1a9510SRong-En Fan items to be attached with.</p> 4227*4a1a9510SRong-En Fan </li> 4228*4a1a9510SRong-En Fan 4229*4a1a9510SRong-En Fan <li> 4230*4a1a9510SRong-En Fan <p>Post the menu with menu_post() and refresh the 4231*4a1a9510SRong-En Fan screen.</p> 4232*4a1a9510SRong-En Fan </li> 4233*4a1a9510SRong-En Fan 4234*4a1a9510SRong-En Fan <li> 4235*4a1a9510SRong-En Fan <p>Process the user requests with a loop and do 4236*4a1a9510SRong-En Fan necessary updates to menu with menu_driver.</p> 4237*4a1a9510SRong-En Fan </li> 4238*4a1a9510SRong-En Fan 4239*4a1a9510SRong-En Fan <li> 4240*4a1a9510SRong-En Fan <p>Unpost the menu with menu_unpost()</p> 4241*4a1a9510SRong-En Fan </li> 4242*4a1a9510SRong-En Fan 4243*4a1a9510SRong-En Fan <li> 4244*4a1a9510SRong-En Fan <p>Free the memory allocated to menu by free_menu()</p> 4245*4a1a9510SRong-En Fan </li> 4246*4a1a9510SRong-En Fan 4247*4a1a9510SRong-En Fan <li> 4248*4a1a9510SRong-En Fan <p>Free the memory allocated to the items with 4249*4a1a9510SRong-En Fan free_item()</p> 4250*4a1a9510SRong-En Fan </li> 4251*4a1a9510SRong-En Fan 4252*4a1a9510SRong-En Fan <li> 4253*4a1a9510SRong-En Fan <p>End curses</p> 4254*4a1a9510SRong-En Fan </li> 4255*4a1a9510SRong-En Fan </ol> 4256*4a1a9510SRong-En Fan 4257*4a1a9510SRong-En Fan <p>Let's see a program which prints a simple menu and 4258*4a1a9510SRong-En Fan updates the current selection with up, down arrows.</p> 4259*4a1a9510SRong-En Fan </div> 4260*4a1a9510SRong-En Fan 4261*4a1a9510SRong-En Fan <div class="SECT2"> 4262*4a1a9510SRong-En Fan <hr> 4263*4a1a9510SRong-En Fan 4264*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COMPILEMENUS" id= 4265*4a1a9510SRong-En Fan "COMPILEMENUS">17.2. Compiling With the Menu 4266*4a1a9510SRong-En Fan Library</a></h3> 4267*4a1a9510SRong-En Fan 4268*4a1a9510SRong-En Fan <p>To use menu library functions, you have to include 4269*4a1a9510SRong-En Fan menu.h and to link the program with menu library the flag 4270*4a1a9510SRong-En Fan -lmenu should be added along with -lncurses in that 4271*4a1a9510SRong-En Fan order.</p> 4272*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4273*4a1a9510SRong-En Fan #include <menu.h> 4274*4a1a9510SRong-En Fan . 4275*4a1a9510SRong-En Fan . 4276*4a1a9510SRong-En Fan . 4277*4a1a9510SRong-En Fan 4278*4a1a9510SRong-En Fan compile and link: gcc <program file> -lmenu -lncurses 4279*4a1a9510SRong-En Fan</pre> 4280*4a1a9510SRong-En Fan 4281*4a1a9510SRong-En Fan <div class="EXAMPLE"> 4282*4a1a9510SRong-En Fan <a name="MMESI" id="MMESI"></a> 4283*4a1a9510SRong-En Fan 4284*4a1a9510SRong-En Fan <p><b>Example 18. Menu Basics</b></p> 4285*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4286*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <curses.h> 4287*4a1a9510SRong-En Fan#include <menu.h> 4288*4a1a9510SRong-En Fan 4289*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 4290*4a1a9510SRong-En Fan#define CTRLD 4 4291*4a1a9510SRong-En Fan 4292*4a1a9510SRong-En Fanchar *choices[] = { 4293*4a1a9510SRong-En Fan "Choice 1", 4294*4a1a9510SRong-En Fan "Choice 2", 4295*4a1a9510SRong-En Fan "Choice 3", 4296*4a1a9510SRong-En Fan "Choice 4", 4297*4a1a9510SRong-En Fan "Exit", 4298*4a1a9510SRong-En Fan }; 4299*4a1a9510SRong-En Fan 4300*4a1a9510SRong-En Fanint main() 4301*4a1a9510SRong-En Fan{ ITEM **my_items; 4302*4a1a9510SRong-En Fan int c; 4303*4a1a9510SRong-En Fan MENU *my_menu; 4304*4a1a9510SRong-En Fan int n_choices, i; 4305*4a1a9510SRong-En Fan ITEM *cur_item; 4306*4a1a9510SRong-En Fan 4307*4a1a9510SRong-En Fan 4308*4a1a9510SRong-En Fan initscr(); 4309*4a1a9510SRong-En Fan cbreak(); 4310*4a1a9510SRong-En Fan noecho(); 4311*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 4312*4a1a9510SRong-En Fan 4313*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 4314*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 4315*4a1a9510SRong-En Fan 4316*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4317*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 4318*4a1a9510SRong-En Fan my_items[n_choices] = (ITEM *)NULL; 4319*4a1a9510SRong-En Fan 4320*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 4321*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "F1 to Exit"); 4322*4a1a9510SRong-En Fan post_menu(my_menu); 4323*4a1a9510SRong-En Fan refresh(); 4324*4a1a9510SRong-En Fan 4325*4a1a9510SRong-En Fan while((c = getch()) != KEY_F(1)) 4326*4a1a9510SRong-En Fan { switch(c) 4327*4a1a9510SRong-En Fan { case KEY_DOWN: 4328*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 4329*4a1a9510SRong-En Fan break; 4330*4a1a9510SRong-En Fan case KEY_UP: 4331*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 4332*4a1a9510SRong-En Fan break; 4333*4a1a9510SRong-En Fan } 4334*4a1a9510SRong-En Fan } 4335*4a1a9510SRong-En Fan 4336*4a1a9510SRong-En Fan free_item(my_items[0]); 4337*4a1a9510SRong-En Fan free_item(my_items[1]); 4338*4a1a9510SRong-En Fan free_menu(my_menu); 4339*4a1a9510SRong-En Fan endwin(); 4340*4a1a9510SRong-En Fan} 4341*4a1a9510SRong-En Fan </span> 4342*4a1a9510SRong-En Fan</pre> 4343*4a1a9510SRong-En Fan </div> 4344*4a1a9510SRong-En Fan 4345*4a1a9510SRong-En Fan <p>This program demonstrates the basic concepts involved in 4346*4a1a9510SRong-En Fan creating a menu using menus library. First we create the 4347*4a1a9510SRong-En Fan items using new_item() and then attach them to the menu 4348*4a1a9510SRong-En Fan with new_menu() function. After posting the menu and 4349*4a1a9510SRong-En Fan refreshing the screen, the main processing loop starts. It 4350*4a1a9510SRong-En Fan reads user input and takes corresponding action. The 4351*4a1a9510SRong-En Fan function menu_driver() is the main work horse of the menu 4352*4a1a9510SRong-En Fan system. The second parameter to this function tells what's 4353*4a1a9510SRong-En Fan to be done with the menu. According to the parameter, 4354*4a1a9510SRong-En Fan menu_driver() does the corresponding task. The value can be 4355*4a1a9510SRong-En Fan either a menu navigational request, an ascii character, or 4356*4a1a9510SRong-En Fan a KEY_MOUSE special key associated with a mouse event.</p> 4357*4a1a9510SRong-En Fan 4358*4a1a9510SRong-En Fan <p>The menu_driver accepts following navigational 4359*4a1a9510SRong-En Fan requests.</p> 4360*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4361*4a1a9510SRong-En Fan REQ_LEFT_ITEM Move left to an item. 4362*4a1a9510SRong-En Fan REQ_RIGHT_ITEM Move right to an item. 4363*4a1a9510SRong-En Fan REQ_UP_ITEM Move up to an item. 4364*4a1a9510SRong-En Fan REQ_DOWN_ITEM Move down to an item. 4365*4a1a9510SRong-En Fan REQ_SCR_ULINE Scroll up a line. 4366*4a1a9510SRong-En Fan REQ_SCR_DLINE Scroll down a line. 4367*4a1a9510SRong-En Fan REQ_SCR_DPAGE Scroll down a page. 4368*4a1a9510SRong-En Fan REQ_SCR_UPAGE Scroll up a page. 4369*4a1a9510SRong-En Fan REQ_FIRST_ITEM Move to the first item. 4370*4a1a9510SRong-En Fan REQ_LAST_ITEM Move to the last item. 4371*4a1a9510SRong-En Fan REQ_NEXT_ITEM Move to the next item. 4372*4a1a9510SRong-En Fan REQ_PREV_ITEM Move to the previous item. 4373*4a1a9510SRong-En Fan REQ_TOGGLE_ITEM Select/deselect an item. 4374*4a1a9510SRong-En Fan REQ_CLEAR_PATTERN Clear the menu pattern buffer. 4375*4a1a9510SRong-En Fan REQ_BACK_PATTERN Delete the previous character from the pattern buffer. 4376*4a1a9510SRong-En Fan REQ_NEXT_MATCH Move to the next item matching the pattern match. 4377*4a1a9510SRong-En Fan REQ_PREV_MATCH Move to the previous item matching the pattern match. 4378*4a1a9510SRong-En Fan</pre> 4379*4a1a9510SRong-En Fan 4380*4a1a9510SRong-En Fan <p>Don't get overwhelmed by the number of options. We will 4381*4a1a9510SRong-En Fan see them slowly one after another. The options of interest 4382*4a1a9510SRong-En Fan in this example are REQ_UP_ITEM and REQ_DOWN_ITEM. These 4383*4a1a9510SRong-En Fan two options when passed to menu_driver, menu driver updates 4384*4a1a9510SRong-En Fan the current item to one item up or down respectively.</p> 4385*4a1a9510SRong-En Fan </div> 4386*4a1a9510SRong-En Fan 4387*4a1a9510SRong-En Fan <div class="SECT2"> 4388*4a1a9510SRong-En Fan <hr> 4389*4a1a9510SRong-En Fan 4390*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MENUDRIVER" id= 4391*4a1a9510SRong-En Fan "MENUDRIVER">17.3. Menu Driver: The work horse of the menu 4392*4a1a9510SRong-En Fan system</a></h3> 4393*4a1a9510SRong-En Fan 4394*4a1a9510SRong-En Fan <p>As you have seen in the above example, menu_driver plays 4395*4a1a9510SRong-En Fan an important role in updating the menu. It is very 4396*4a1a9510SRong-En Fan important to understand various options it takes and what 4397*4a1a9510SRong-En Fan they do. As explained above, the second parameter to 4398*4a1a9510SRong-En Fan menu_driver() can be either a navigational request, a 4399*4a1a9510SRong-En Fan printable character or a KEY_MOUSE key. Let's dissect the 4400*4a1a9510SRong-En Fan different navigational requests.</p> 4401*4a1a9510SRong-En Fan 4402*4a1a9510SRong-En Fan <ul> 4403*4a1a9510SRong-En Fan <li> 4404*4a1a9510SRong-En Fan <p><span class="emphasis"><i class= 4405*4a1a9510SRong-En Fan "EMPHASIS">REQ_LEFT_ITEM and 4406*4a1a9510SRong-En Fan REQ_RIGHT_ITEM</i></span></p> 4407*4a1a9510SRong-En Fan 4408*4a1a9510SRong-En Fan <p>A Menu can be displayed with multiple columns for 4409*4a1a9510SRong-En Fan more than one item. This can be done by using the 4410*4a1a9510SRong-En Fan <tt class="LITERAL">menu_format()</tt>function. When a 4411*4a1a9510SRong-En Fan multi columnar menu is displayed these requests cause 4412*4a1a9510SRong-En Fan the menu driver to move the current selection to left 4413*4a1a9510SRong-En Fan or right.</p> 4414*4a1a9510SRong-En Fan </li> 4415*4a1a9510SRong-En Fan 4416*4a1a9510SRong-En Fan <li> 4417*4a1a9510SRong-En Fan <p><span class="emphasis"><i class= 4418*4a1a9510SRong-En Fan "EMPHASIS">REQ_UP_ITEM and REQ_DOWN_ITEM</i></span></p> 4419*4a1a9510SRong-En Fan 4420*4a1a9510SRong-En Fan <p>These two options you have seen in the above 4421*4a1a9510SRong-En Fan example. These options when given, makes the 4422*4a1a9510SRong-En Fan menu_driver to move the current selection to an item up 4423*4a1a9510SRong-En Fan or down.</p> 4424*4a1a9510SRong-En Fan </li> 4425*4a1a9510SRong-En Fan 4426*4a1a9510SRong-En Fan <li> 4427*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">REQ_SCR_* 4428*4a1a9510SRong-En Fan options</i></span></p> 4429*4a1a9510SRong-En Fan 4430*4a1a9510SRong-En Fan <p>The four options REQ_SCR_ULINE, REQ_SCR_DLINE, 4431*4a1a9510SRong-En Fan REQ_SCR_DPAGE, REQ_SCR_UPAGE are related to scrolling. 4432*4a1a9510SRong-En Fan If all the items in the menu cannot be displayed in the 4433*4a1a9510SRong-En Fan menu sub window, then the menu is scrollable. These 4434*4a1a9510SRong-En Fan requests can be given to the menu_driver to do the 4435*4a1a9510SRong-En Fan scrolling either one line up, down or one page down or 4436*4a1a9510SRong-En Fan up respectively.</p> 4437*4a1a9510SRong-En Fan </li> 4438*4a1a9510SRong-En Fan 4439*4a1a9510SRong-En Fan <li> 4440*4a1a9510SRong-En Fan <p><span class="emphasis"><i class= 4441*4a1a9510SRong-En Fan "EMPHASIS">REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_NEXT_ITEM 4442*4a1a9510SRong-En Fan and REQ_PREV_ITEM</i></span></p> 4443*4a1a9510SRong-En Fan 4444*4a1a9510SRong-En Fan <p>These requests are self explanatory.</p> 4445*4a1a9510SRong-En Fan </li> 4446*4a1a9510SRong-En Fan 4447*4a1a9510SRong-En Fan <li> 4448*4a1a9510SRong-En Fan <p><span class="emphasis"><i class= 4449*4a1a9510SRong-En Fan "EMPHASIS">REQ_TOGGLE_ITEM</i></span></p> 4450*4a1a9510SRong-En Fan 4451*4a1a9510SRong-En Fan <p>This request when given, toggles the present 4452*4a1a9510SRong-En Fan selection. This option is to be used only in a multi 4453*4a1a9510SRong-En Fan valued menu. So to use this request the option 4454*4a1a9510SRong-En Fan O_ONEVALUE must be off. This option can be made off or 4455*4a1a9510SRong-En Fan on with set_menu_opts().</p> 4456*4a1a9510SRong-En Fan </li> 4457*4a1a9510SRong-En Fan 4458*4a1a9510SRong-En Fan <li> 4459*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">Pattern 4460*4a1a9510SRong-En Fan Requests</i></span></p> 4461*4a1a9510SRong-En Fan 4462*4a1a9510SRong-En Fan <p>Every menu has an associated pattern buffer, which 4463*4a1a9510SRong-En Fan is used to find the nearest match to the ascii 4464*4a1a9510SRong-En Fan characters entered by the user. Whenever ascii 4465*4a1a9510SRong-En Fan characters are given to menu_driver, it puts in to the 4466*4a1a9510SRong-En Fan pattern buffer. It also tries to find the nearest match 4467*4a1a9510SRong-En Fan to the pattern in the items list and moves current 4468*4a1a9510SRong-En Fan selection to that item. The request REQ_CLEAR_PATTERN 4469*4a1a9510SRong-En Fan clears the pattern buffer. The request REQ_BACK_PATTERN 4470*4a1a9510SRong-En Fan deletes the previous character in the pattern buffer. 4471*4a1a9510SRong-En Fan In case the pattern matches more than one item then the 4472*4a1a9510SRong-En Fan matched items can be cycled through REQ_NEXT_MATCH and 4473*4a1a9510SRong-En Fan REQ_PREV_MATCH which move the current selection to the 4474*4a1a9510SRong-En Fan next and previous matches respectively.</p> 4475*4a1a9510SRong-En Fan </li> 4476*4a1a9510SRong-En Fan 4477*4a1a9510SRong-En Fan <li> 4478*4a1a9510SRong-En Fan <p><span class="emphasis"><i class="EMPHASIS">Mouse 4479*4a1a9510SRong-En Fan Requests</i></span></p> 4480*4a1a9510SRong-En Fan 4481*4a1a9510SRong-En Fan <p>In case of KEY_MOUSE requests, according to the 4482*4a1a9510SRong-En Fan mouse position an action is taken accordingly. The 4483*4a1a9510SRong-En Fan action to be taken is explained in the man page as,</p> 4484*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4485*4a1a9510SRong-En Fan<span class="emphasis"><i class= 4486*4a1a9510SRong-En Fan"EMPHASIS"> If the second argument is the KEY_MOUSE special key, the 4487*4a1a9510SRong-En Fan associated mouse event is translated into one of the above 4488*4a1a9510SRong-En Fan pre-defined requests. Currently only clicks in the user 4489*4a1a9510SRong-En Fan window (e.g. inside the menu display area or the decora­ 4490*4a1a9510SRong-En Fan tion window) are handled. If you click above the display 4491*4a1a9510SRong-En Fan region of the menu, a REQ_SCR_ULINE is generated, if you 4492*4a1a9510SRong-En Fan doubleclick a REQ_SCR_UPAGE is generated and if you 4493*4a1a9510SRong-En Fan tripleclick a REQ_FIRST_ITEM is generated. If you click 4494*4a1a9510SRong-En Fan below the display region of the menu, a REQ_SCR_DLINE is 4495*4a1a9510SRong-En Fan generated, if you doubleclick a REQ_SCR_DPAGE is generated 4496*4a1a9510SRong-En Fan and if you tripleclick a REQ_LAST_ITEM is generated. If 4497*4a1a9510SRong-En Fan you click at an item inside the display area of the menu, 4498*4a1a9510SRong-En Fan the menu cursor is positioned to that item.</i></span> 4499*4a1a9510SRong-En Fan</pre> 4500*4a1a9510SRong-En Fan </li> 4501*4a1a9510SRong-En Fan </ul> 4502*4a1a9510SRong-En Fan 4503*4a1a9510SRong-En Fan <p>Each of the above requests will be explained in the 4504*4a1a9510SRong-En Fan following lines with several examples whenever 4505*4a1a9510SRong-En Fan appropriate.</p> 4506*4a1a9510SRong-En Fan </div> 4507*4a1a9510SRong-En Fan 4508*4a1a9510SRong-En Fan <div class="SECT2"> 4509*4a1a9510SRong-En Fan <hr> 4510*4a1a9510SRong-En Fan 4511*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MENUWINDOWS" id= 4512*4a1a9510SRong-En Fan "MENUWINDOWS">17.4. Menu Windows</a></h3> 4513*4a1a9510SRong-En Fan 4514*4a1a9510SRong-En Fan <p>Every menu created is associated with a window and a sub 4515*4a1a9510SRong-En Fan window. The menu window displays any title or border 4516*4a1a9510SRong-En Fan associated with the menu. The menu sub window displays the 4517*4a1a9510SRong-En Fan menu items currently available for selection. But we didn't 4518*4a1a9510SRong-En Fan specify any window or sub window in the simple example. 4519*4a1a9510SRong-En Fan When a window is not specified, stdscr is taken as the main 4520*4a1a9510SRong-En Fan window, and then menu system calculates the sub window size 4521*4a1a9510SRong-En Fan required for the display of items. Then items are displayed 4522*4a1a9510SRong-En Fan in the calculated sub window. So let's play with these 4523*4a1a9510SRong-En Fan windows and display a menu with a border and a title.</p> 4524*4a1a9510SRong-En Fan 4525*4a1a9510SRong-En Fan <div class="EXAMPLE"> 4526*4a1a9510SRong-En Fan <a name="MMEWI" id="MMEWI"></a> 4527*4a1a9510SRong-En Fan 4528*4a1a9510SRong-En Fan <p><b>Example 19. Menu Windows Usage example</b></p> 4529*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4530*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <menu.h> 4531*4a1a9510SRong-En Fan 4532*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 4533*4a1a9510SRong-En Fan#define CTRLD 4 4534*4a1a9510SRong-En Fan 4535*4a1a9510SRong-En Fanchar *choices[] = { 4536*4a1a9510SRong-En Fan "Choice 1", 4537*4a1a9510SRong-En Fan "Choice 2", 4538*4a1a9510SRong-En Fan "Choice 3", 4539*4a1a9510SRong-En Fan "Choice 4", 4540*4a1a9510SRong-En Fan "Exit", 4541*4a1a9510SRong-En Fan (char *)NULL, 4542*4a1a9510SRong-En Fan }; 4543*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4544*4a1a9510SRong-En Fan 4545*4a1a9510SRong-En Fanint main() 4546*4a1a9510SRong-En Fan{ ITEM **my_items; 4547*4a1a9510SRong-En Fan int c; 4548*4a1a9510SRong-En Fan MENU *my_menu; 4549*4a1a9510SRong-En Fan WINDOW *my_menu_win; 4550*4a1a9510SRong-En Fan int n_choices, i; 4551*4a1a9510SRong-En Fan 4552*4a1a9510SRong-En Fan /* Initialize curses */ 4553*4a1a9510SRong-En Fan initscr(); 4554*4a1a9510SRong-En Fan start_color(); 4555*4a1a9510SRong-En Fan cbreak(); 4556*4a1a9510SRong-En Fan noecho(); 4557*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 4558*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 4559*4a1a9510SRong-En Fan 4560*4a1a9510SRong-En Fan /* Create items */ 4561*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 4562*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 4563*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4564*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 4565*4a1a9510SRong-En Fan 4566*4a1a9510SRong-En Fan /* Crate menu */ 4567*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 4568*4a1a9510SRong-En Fan 4569*4a1a9510SRong-En Fan /* Create the window to be associated with the menu */ 4570*4a1a9510SRong-En Fan my_menu_win = newwin(10, 40, 4, 4); 4571*4a1a9510SRong-En Fan keypad(my_menu_win, TRUE); 4572*4a1a9510SRong-En Fan 4573*4a1a9510SRong-En Fan /* Set main window and sub window */ 4574*4a1a9510SRong-En Fan set_menu_win(my_menu, my_menu_win); 4575*4a1a9510SRong-En Fan set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1)); 4576*4a1a9510SRong-En Fan 4577*4a1a9510SRong-En Fan /* Set menu mark to the string " * " */ 4578*4a1a9510SRong-En Fan set_menu_mark(my_menu, " * "); 4579*4a1a9510SRong-En Fan 4580*4a1a9510SRong-En Fan /* Print a border around the main window and print a title */ 4581*4a1a9510SRong-En Fan box(my_menu_win, 0, 0); 4582*4a1a9510SRong-En Fan print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1)); 4583*4a1a9510SRong-En Fan mvwaddch(my_menu_win, 2, 0, ACS_LTEE); 4584*4a1a9510SRong-En Fan mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38); 4585*4a1a9510SRong-En Fan mvwaddch(my_menu_win, 2, 39, ACS_RTEE); 4586*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "F1 to exit"); 4587*4a1a9510SRong-En Fan refresh(); 4588*4a1a9510SRong-En Fan 4589*4a1a9510SRong-En Fan /* Post the menu */ 4590*4a1a9510SRong-En Fan post_menu(my_menu); 4591*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4592*4a1a9510SRong-En Fan 4593*4a1a9510SRong-En Fan while((c = wgetch(my_menu_win)) != KEY_F(1)) 4594*4a1a9510SRong-En Fan { switch(c) 4595*4a1a9510SRong-En Fan { case KEY_DOWN: 4596*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 4597*4a1a9510SRong-En Fan break; 4598*4a1a9510SRong-En Fan case KEY_UP: 4599*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 4600*4a1a9510SRong-En Fan break; 4601*4a1a9510SRong-En Fan } 4602*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4603*4a1a9510SRong-En Fan } 4604*4a1a9510SRong-En Fan 4605*4a1a9510SRong-En Fan /* Unpost and free all the memory taken up */ 4606*4a1a9510SRong-En Fan unpost_menu(my_menu); 4607*4a1a9510SRong-En Fan free_menu(my_menu); 4608*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4609*4a1a9510SRong-En Fan free_item(my_items[i]); 4610*4a1a9510SRong-En Fan endwin(); 4611*4a1a9510SRong-En Fan} 4612*4a1a9510SRong-En Fan 4613*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 4614*4a1a9510SRong-En Fan{ int length, x, y; 4615*4a1a9510SRong-En Fan float temp; 4616*4a1a9510SRong-En Fan 4617*4a1a9510SRong-En Fan if(win == NULL) 4618*4a1a9510SRong-En Fan win = stdscr; 4619*4a1a9510SRong-En Fan getyx(win, y, x); 4620*4a1a9510SRong-En Fan if(startx != 0) 4621*4a1a9510SRong-En Fan x = startx; 4622*4a1a9510SRong-En Fan if(starty != 0) 4623*4a1a9510SRong-En Fan y = starty; 4624*4a1a9510SRong-En Fan if(width == 0) 4625*4a1a9510SRong-En Fan width = 80; 4626*4a1a9510SRong-En Fan 4627*4a1a9510SRong-En Fan length = strlen(string); 4628*4a1a9510SRong-En Fan temp = (width - length)/ 2; 4629*4a1a9510SRong-En Fan x = startx + (int)temp; 4630*4a1a9510SRong-En Fan wattron(win, color); 4631*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 4632*4a1a9510SRong-En Fan wattroff(win, color); 4633*4a1a9510SRong-En Fan refresh(); 4634*4a1a9510SRong-En Fan}</span> 4635*4a1a9510SRong-En Fan</pre> 4636*4a1a9510SRong-En Fan </div> 4637*4a1a9510SRong-En Fan 4638*4a1a9510SRong-En Fan <p>This example creates a menu with a title, border, a 4639*4a1a9510SRong-En Fan fancy line separating title and the items. As you can see, 4640*4a1a9510SRong-En Fan in order to attach a window to a menu the function 4641*4a1a9510SRong-En Fan set_menu_win() has to be used. Then we attach the sub 4642*4a1a9510SRong-En Fan window also. This displays the items in the sub window. You 4643*4a1a9510SRong-En Fan can also set the mark string which gets displayed to the 4644*4a1a9510SRong-En Fan left of the selected item with set_menu_mark().</p> 4645*4a1a9510SRong-En Fan </div> 4646*4a1a9510SRong-En Fan 4647*4a1a9510SRong-En Fan <div class="SECT2"> 4648*4a1a9510SRong-En Fan <hr> 4649*4a1a9510SRong-En Fan 4650*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="SCROLLMENUS" id= 4651*4a1a9510SRong-En Fan "SCROLLMENUS">17.5. Scrolling Menus</a></h3> 4652*4a1a9510SRong-En Fan 4653*4a1a9510SRong-En Fan <p>If the sub window given for a window is not big enough 4654*4a1a9510SRong-En Fan to show all the items, then the menu will be scrollable. 4655*4a1a9510SRong-En Fan When you are on the last item in the present list, if you 4656*4a1a9510SRong-En Fan send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE 4657*4a1a9510SRong-En Fan and the menu scrolls by one item. You can manually give 4658*4a1a9510SRong-En Fan REQ_SCR_ operations to do scrolling. Let's see how it can 4659*4a1a9510SRong-En Fan be done.</p> 4660*4a1a9510SRong-En Fan 4661*4a1a9510SRong-En Fan <div class="EXAMPLE"> 4662*4a1a9510SRong-En Fan <a name="MMESC" id="MMESC"></a> 4663*4a1a9510SRong-En Fan 4664*4a1a9510SRong-En Fan <p><b>Example 20. Scrolling Menus example</b></p> 4665*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4666*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <curses.h> 4667*4a1a9510SRong-En Fan#include <menu.h> 4668*4a1a9510SRong-En Fan 4669*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 4670*4a1a9510SRong-En Fan#define CTRLD 4 4671*4a1a9510SRong-En Fan 4672*4a1a9510SRong-En Fanchar *choices[] = { 4673*4a1a9510SRong-En Fan "Choice 1", 4674*4a1a9510SRong-En Fan "Choice 2", 4675*4a1a9510SRong-En Fan "Choice 3", 4676*4a1a9510SRong-En Fan "Choice 4", 4677*4a1a9510SRong-En Fan "Choice 5", 4678*4a1a9510SRong-En Fan "Choice 6", 4679*4a1a9510SRong-En Fan "Choice 7", 4680*4a1a9510SRong-En Fan "Choice 8", 4681*4a1a9510SRong-En Fan "Choice 9", 4682*4a1a9510SRong-En Fan "Choice 10", 4683*4a1a9510SRong-En Fan "Exit", 4684*4a1a9510SRong-En Fan (char *)NULL, 4685*4a1a9510SRong-En Fan }; 4686*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4687*4a1a9510SRong-En Fan 4688*4a1a9510SRong-En Fanint main() 4689*4a1a9510SRong-En Fan{ ITEM **my_items; 4690*4a1a9510SRong-En Fan int c; 4691*4a1a9510SRong-En Fan MENU *my_menu; 4692*4a1a9510SRong-En Fan WINDOW *my_menu_win; 4693*4a1a9510SRong-En Fan int n_choices, i; 4694*4a1a9510SRong-En Fan 4695*4a1a9510SRong-En Fan /* Initialize curses */ 4696*4a1a9510SRong-En Fan initscr(); 4697*4a1a9510SRong-En Fan start_color(); 4698*4a1a9510SRong-En Fan cbreak(); 4699*4a1a9510SRong-En Fan noecho(); 4700*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 4701*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 4702*4a1a9510SRong-En Fan init_pair(2, COLOR_CYAN, COLOR_BLACK); 4703*4a1a9510SRong-En Fan 4704*4a1a9510SRong-En Fan /* Create items */ 4705*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 4706*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 4707*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4708*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 4709*4a1a9510SRong-En Fan 4710*4a1a9510SRong-En Fan /* Crate menu */ 4711*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 4712*4a1a9510SRong-En Fan 4713*4a1a9510SRong-En Fan /* Create the window to be associated with the menu */ 4714*4a1a9510SRong-En Fan my_menu_win = newwin(10, 40, 4, 4); 4715*4a1a9510SRong-En Fan keypad(my_menu_win, TRUE); 4716*4a1a9510SRong-En Fan 4717*4a1a9510SRong-En Fan /* Set main window and sub window */ 4718*4a1a9510SRong-En Fan set_menu_win(my_menu, my_menu_win); 4719*4a1a9510SRong-En Fan set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1)); 4720*4a1a9510SRong-En Fan set_menu_format(my_menu, 5, 1); 4721*4a1a9510SRong-En Fan 4722*4a1a9510SRong-En Fan /* Set menu mark to the string " * " */ 4723*4a1a9510SRong-En Fan set_menu_mark(my_menu, " * "); 4724*4a1a9510SRong-En Fan 4725*4a1a9510SRong-En Fan /* Print a border around the main window and print a title */ 4726*4a1a9510SRong-En Fan box(my_menu_win, 0, 0); 4727*4a1a9510SRong-En Fan print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1)); 4728*4a1a9510SRong-En Fan mvwaddch(my_menu_win, 2, 0, ACS_LTEE); 4729*4a1a9510SRong-En Fan mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38); 4730*4a1a9510SRong-En Fan mvwaddch(my_menu_win, 2, 39, ACS_RTEE); 4731*4a1a9510SRong-En Fan 4732*4a1a9510SRong-En Fan /* Post the menu */ 4733*4a1a9510SRong-En Fan post_menu(my_menu); 4734*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4735*4a1a9510SRong-En Fan 4736*4a1a9510SRong-En Fan attron(COLOR_PAIR(2)); 4737*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scoll down or up a page of items"); 4738*4a1a9510SRong-En Fan mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)"); 4739*4a1a9510SRong-En Fan attroff(COLOR_PAIR(2)); 4740*4a1a9510SRong-En Fan refresh(); 4741*4a1a9510SRong-En Fan 4742*4a1a9510SRong-En Fan while((c = wgetch(my_menu_win)) != KEY_F(1)) 4743*4a1a9510SRong-En Fan { switch(c) 4744*4a1a9510SRong-En Fan { case KEY_DOWN: 4745*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 4746*4a1a9510SRong-En Fan break; 4747*4a1a9510SRong-En Fan case KEY_UP: 4748*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 4749*4a1a9510SRong-En Fan break; 4750*4a1a9510SRong-En Fan case KEY_NPAGE: 4751*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_SCR_DPAGE); 4752*4a1a9510SRong-En Fan break; 4753*4a1a9510SRong-En Fan case KEY_PPAGE: 4754*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_SCR_UPAGE); 4755*4a1a9510SRong-En Fan break; 4756*4a1a9510SRong-En Fan } 4757*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4758*4a1a9510SRong-En Fan } 4759*4a1a9510SRong-En Fan 4760*4a1a9510SRong-En Fan /* Unpost and free all the memory taken up */ 4761*4a1a9510SRong-En Fan unpost_menu(my_menu); 4762*4a1a9510SRong-En Fan free_menu(my_menu); 4763*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4764*4a1a9510SRong-En Fan free_item(my_items[i]); 4765*4a1a9510SRong-En Fan endwin(); 4766*4a1a9510SRong-En Fan} 4767*4a1a9510SRong-En Fan 4768*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 4769*4a1a9510SRong-En Fan{ int length, x, y; 4770*4a1a9510SRong-En Fan float temp; 4771*4a1a9510SRong-En Fan 4772*4a1a9510SRong-En Fan if(win == NULL) 4773*4a1a9510SRong-En Fan win = stdscr; 4774*4a1a9510SRong-En Fan getyx(win, y, x); 4775*4a1a9510SRong-En Fan if(startx != 0) 4776*4a1a9510SRong-En Fan x = startx; 4777*4a1a9510SRong-En Fan if(starty != 0) 4778*4a1a9510SRong-En Fan y = starty; 4779*4a1a9510SRong-En Fan if(width == 0) 4780*4a1a9510SRong-En Fan width = 80; 4781*4a1a9510SRong-En Fan 4782*4a1a9510SRong-En Fan length = strlen(string); 4783*4a1a9510SRong-En Fan temp = (width - length)/ 2; 4784*4a1a9510SRong-En Fan x = startx + (int)temp; 4785*4a1a9510SRong-En Fan wattron(win, color); 4786*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 4787*4a1a9510SRong-En Fan wattroff(win, color); 4788*4a1a9510SRong-En Fan refresh(); 4789*4a1a9510SRong-En Fan}</span> 4790*4a1a9510SRong-En Fan</pre> 4791*4a1a9510SRong-En Fan </div> 4792*4a1a9510SRong-En Fan 4793*4a1a9510SRong-En Fan <p>This program is self-explanatory. In this example the 4794*4a1a9510SRong-En Fan number of choices has been increased to ten, which is 4795*4a1a9510SRong-En Fan larger than our sub window size which can hold 6 items. 4796*4a1a9510SRong-En Fan This message has to be explicitly conveyed to the menu 4797*4a1a9510SRong-En Fan system with the function set_menu_format(). In here we 4798*4a1a9510SRong-En Fan specify the number of rows and columns we want to be 4799*4a1a9510SRong-En Fan displayed for a single page. We can specify any number of 4800*4a1a9510SRong-En Fan items to be shown, in the rows variables, if it is less 4801*4a1a9510SRong-En Fan than the height of the sub window. If the key pressed by 4802*4a1a9510SRong-En Fan the user is a PAGE UP or PAGE DOWN, the menu is scrolled a 4803*4a1a9510SRong-En Fan page due to the requests (REQ_SCR_DPAGE and REQ_SCR_UPAGE) 4804*4a1a9510SRong-En Fan given to menu_driver().</p> 4805*4a1a9510SRong-En Fan </div> 4806*4a1a9510SRong-En Fan 4807*4a1a9510SRong-En Fan <div class="SECT2"> 4808*4a1a9510SRong-En Fan <hr> 4809*4a1a9510SRong-En Fan 4810*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MULTICOLUMN" id= 4811*4a1a9510SRong-En Fan "MULTICOLUMN">17.6. Multi Columnar Menus</a></h3> 4812*4a1a9510SRong-En Fan 4813*4a1a9510SRong-En Fan <p>In the above example you have seen how to use the 4814*4a1a9510SRong-En Fan function set_menu_format(). I didn't mention what the cols 4815*4a1a9510SRong-En Fan variable (third parameter) does. Well, If your sub window 4816*4a1a9510SRong-En Fan is wide enough, you can opt to display more than one item 4817*4a1a9510SRong-En Fan per row. This can be specified in the cols variable. To 4818*4a1a9510SRong-En Fan make things simpler, the following example doesn't show 4819*4a1a9510SRong-En Fan descriptions for the items.</p> 4820*4a1a9510SRong-En Fan 4821*4a1a9510SRong-En Fan <div class="EXAMPLE"> 4822*4a1a9510SRong-En Fan <a name="MMEMUCO" id="MMEMUCO"></a> 4823*4a1a9510SRong-En Fan 4824*4a1a9510SRong-En Fan <p><b>Example 21. Milt Columnar Menus Example</b></p> 4825*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4826*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <curses.h> 4827*4a1a9510SRong-En Fan#include <menu.h> 4828*4a1a9510SRong-En Fan 4829*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 4830*4a1a9510SRong-En Fan#define CTRLD 4 4831*4a1a9510SRong-En Fan 4832*4a1a9510SRong-En Fanchar *choices[] = { 4833*4a1a9510SRong-En Fan "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5", 4834*4a1a9510SRong-En Fan "Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10", 4835*4a1a9510SRong-En Fan "Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15", 4836*4a1a9510SRong-En Fan "Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20", 4837*4a1a9510SRong-En Fan "Exit", 4838*4a1a9510SRong-En Fan (char *)NULL, 4839*4a1a9510SRong-En Fan }; 4840*4a1a9510SRong-En Fan 4841*4a1a9510SRong-En Fanint main() 4842*4a1a9510SRong-En Fan{ ITEM **my_items; 4843*4a1a9510SRong-En Fan int c; 4844*4a1a9510SRong-En Fan MENU *my_menu; 4845*4a1a9510SRong-En Fan WINDOW *my_menu_win; 4846*4a1a9510SRong-En Fan int n_choices, i; 4847*4a1a9510SRong-En Fan 4848*4a1a9510SRong-En Fan /* Initialize curses */ 4849*4a1a9510SRong-En Fan initscr(); 4850*4a1a9510SRong-En Fan start_color(); 4851*4a1a9510SRong-En Fan cbreak(); 4852*4a1a9510SRong-En Fan noecho(); 4853*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 4854*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 4855*4a1a9510SRong-En Fan init_pair(2, COLOR_CYAN, COLOR_BLACK); 4856*4a1a9510SRong-En Fan 4857*4a1a9510SRong-En Fan /* Create items */ 4858*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 4859*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 4860*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4861*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 4862*4a1a9510SRong-En Fan 4863*4a1a9510SRong-En Fan /* Crate menu */ 4864*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 4865*4a1a9510SRong-En Fan 4866*4a1a9510SRong-En Fan /* Set menu option not to show the description */ 4867*4a1a9510SRong-En Fan menu_opts_off(my_menu, O_SHOWDESC); 4868*4a1a9510SRong-En Fan 4869*4a1a9510SRong-En Fan /* Create the window to be associated with the menu */ 4870*4a1a9510SRong-En Fan my_menu_win = newwin(10, 70, 4, 4); 4871*4a1a9510SRong-En Fan keypad(my_menu_win, TRUE); 4872*4a1a9510SRong-En Fan 4873*4a1a9510SRong-En Fan /* Set main window and sub window */ 4874*4a1a9510SRong-En Fan set_menu_win(my_menu, my_menu_win); 4875*4a1a9510SRong-En Fan set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1)); 4876*4a1a9510SRong-En Fan set_menu_format(my_menu, 5, 3); 4877*4a1a9510SRong-En Fan set_menu_mark(my_menu, " * "); 4878*4a1a9510SRong-En Fan 4879*4a1a9510SRong-En Fan /* Print a border around the main window and print a title */ 4880*4a1a9510SRong-En Fan box(my_menu_win, 0, 0); 4881*4a1a9510SRong-En Fan 4882*4a1a9510SRong-En Fan attron(COLOR_PAIR(2)); 4883*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll"); 4884*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)"); 4885*4a1a9510SRong-En Fan attroff(COLOR_PAIR(2)); 4886*4a1a9510SRong-En Fan refresh(); 4887*4a1a9510SRong-En Fan 4888*4a1a9510SRong-En Fan /* Post the menu */ 4889*4a1a9510SRong-En Fan post_menu(my_menu); 4890*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4891*4a1a9510SRong-En Fan 4892*4a1a9510SRong-En Fan while((c = wgetch(my_menu_win)) != KEY_F(1)) 4893*4a1a9510SRong-En Fan { switch(c) 4894*4a1a9510SRong-En Fan { case KEY_DOWN: 4895*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 4896*4a1a9510SRong-En Fan break; 4897*4a1a9510SRong-En Fan case KEY_UP: 4898*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 4899*4a1a9510SRong-En Fan break; 4900*4a1a9510SRong-En Fan case KEY_LEFT: 4901*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_LEFT_ITEM); 4902*4a1a9510SRong-En Fan break; 4903*4a1a9510SRong-En Fan case KEY_RIGHT: 4904*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_RIGHT_ITEM); 4905*4a1a9510SRong-En Fan break; 4906*4a1a9510SRong-En Fan case KEY_NPAGE: 4907*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_SCR_DPAGE); 4908*4a1a9510SRong-En Fan break; 4909*4a1a9510SRong-En Fan case KEY_PPAGE: 4910*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_SCR_UPAGE); 4911*4a1a9510SRong-En Fan break; 4912*4a1a9510SRong-En Fan } 4913*4a1a9510SRong-En Fan wrefresh(my_menu_win); 4914*4a1a9510SRong-En Fan } 4915*4a1a9510SRong-En Fan 4916*4a1a9510SRong-En Fan /* Unpost and free all the memory taken up */ 4917*4a1a9510SRong-En Fan unpost_menu(my_menu); 4918*4a1a9510SRong-En Fan free_menu(my_menu); 4919*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 4920*4a1a9510SRong-En Fan free_item(my_items[i]); 4921*4a1a9510SRong-En Fan endwin(); 4922*4a1a9510SRong-En Fan}</span> 4923*4a1a9510SRong-En Fan</pre> 4924*4a1a9510SRong-En Fan </div> 4925*4a1a9510SRong-En Fan 4926*4a1a9510SRong-En Fan <p>Watch the function call to set_menu_format(). It 4927*4a1a9510SRong-En Fan specifies the number of columns to be 3, thus displaying 3 4928*4a1a9510SRong-En Fan items per row. We have also switched off the showing 4929*4a1a9510SRong-En Fan descriptions with the function menu_opts_off(). There are 4930*4a1a9510SRong-En Fan couple of functions set_menu_opts(), menu_opts_on() and 4931*4a1a9510SRong-En Fan menu_opts() which can be used to manipulate menu options. 4932*4a1a9510SRong-En Fan The following menu options can be specified.</p> 4933*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4934*4a1a9510SRong-En Fan O_ONEVALUE 4935*4a1a9510SRong-En Fan Only one item can be selected for this menu. 4936*4a1a9510SRong-En Fan 4937*4a1a9510SRong-En Fan O_SHOWDESC 4938*4a1a9510SRong-En Fan Display the item descriptions when the menu is 4939*4a1a9510SRong-En Fan posted. 4940*4a1a9510SRong-En Fan 4941*4a1a9510SRong-En Fan O_ROWMAJOR 4942*4a1a9510SRong-En Fan Display the menu in row-major order. 4943*4a1a9510SRong-En Fan 4944*4a1a9510SRong-En Fan O_IGNORECASE 4945*4a1a9510SRong-En Fan Ignore the case when pattern-matching. 4946*4a1a9510SRong-En Fan 4947*4a1a9510SRong-En Fan O_SHOWMATCH 4948*4a1a9510SRong-En Fan Move the cursor to within the item name while pat­ 4949*4a1a9510SRong-En Fan tern-matching. 4950*4a1a9510SRong-En Fan 4951*4a1a9510SRong-En Fan O_NONCYCLIC 4952*4a1a9510SRong-En Fan Don't wrap around next-item and previous-item, 4953*4a1a9510SRong-En Fan requests to the other end of the menu. 4954*4a1a9510SRong-En Fan</pre> 4955*4a1a9510SRong-En Fan 4956*4a1a9510SRong-En Fan <p>All options are on by default. You can switch specific 4957*4a1a9510SRong-En Fan attributes on or off with menu_opts_on() and 4958*4a1a9510SRong-En Fan menu_opts_off() functions. You can also use set_menu_opts() 4959*4a1a9510SRong-En Fan to directly specify the options. The argument to this 4960*4a1a9510SRong-En Fan function should be a OR ed value of some of those above 4961*4a1a9510SRong-En Fan constants. The function menu_opts() can be used to find out 4962*4a1a9510SRong-En Fan a menu's present options.</p> 4963*4a1a9510SRong-En Fan </div> 4964*4a1a9510SRong-En Fan 4965*4a1a9510SRong-En Fan <div class="SECT2"> 4966*4a1a9510SRong-En Fan <hr> 4967*4a1a9510SRong-En Fan 4968*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MULTIVALUEMENUS" id= 4969*4a1a9510SRong-En Fan "MULTIVALUEMENUS">17.7. Multi Valued Menus</a></h3> 4970*4a1a9510SRong-En Fan 4971*4a1a9510SRong-En Fan <p>You might be wondering what if you switch off the option 4972*4a1a9510SRong-En Fan O_ONEVALUE. Then the menu becomes multi-valued. That means 4973*4a1a9510SRong-En Fan you can select more than one item. This brings us to the 4974*4a1a9510SRong-En Fan request REQ_TOGGLE_ITEM. Let's see it in action.</p> 4975*4a1a9510SRong-En Fan 4976*4a1a9510SRong-En Fan <div class="EXAMPLE"> 4977*4a1a9510SRong-En Fan <a name="MMETO" id="MMETO"></a> 4978*4a1a9510SRong-En Fan 4979*4a1a9510SRong-En Fan <p><b>Example 22. Multi Valued Menus example</b></p> 4980*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 4981*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <curses.h> 4982*4a1a9510SRong-En Fan#include <menu.h> 4983*4a1a9510SRong-En Fan 4984*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 4985*4a1a9510SRong-En Fan#define CTRLD 4 4986*4a1a9510SRong-En Fan 4987*4a1a9510SRong-En Fanchar *choices[] = { 4988*4a1a9510SRong-En Fan "Choice 1", 4989*4a1a9510SRong-En Fan "Choice 2", 4990*4a1a9510SRong-En Fan "Choice 3", 4991*4a1a9510SRong-En Fan "Choice 4", 4992*4a1a9510SRong-En Fan "Choice 5", 4993*4a1a9510SRong-En Fan "Choice 6", 4994*4a1a9510SRong-En Fan "Choice 7", 4995*4a1a9510SRong-En Fan "Exit", 4996*4a1a9510SRong-En Fan }; 4997*4a1a9510SRong-En Fan 4998*4a1a9510SRong-En Fanint main() 4999*4a1a9510SRong-En Fan{ ITEM **my_items; 5000*4a1a9510SRong-En Fan int c; 5001*4a1a9510SRong-En Fan MENU *my_menu; 5002*4a1a9510SRong-En Fan int n_choices, i; 5003*4a1a9510SRong-En Fan ITEM *cur_item; 5004*4a1a9510SRong-En Fan 5005*4a1a9510SRong-En Fan /* Initialize curses */ 5006*4a1a9510SRong-En Fan initscr(); 5007*4a1a9510SRong-En Fan cbreak(); 5008*4a1a9510SRong-En Fan noecho(); 5009*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5010*4a1a9510SRong-En Fan 5011*4a1a9510SRong-En Fan /* Initialize items */ 5012*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 5013*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 5014*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 5015*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 5016*4a1a9510SRong-En Fan my_items[n_choices] = (ITEM *)NULL; 5017*4a1a9510SRong-En Fan 5018*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 5019*4a1a9510SRong-En Fan 5020*4a1a9510SRong-En Fan /* Make the menu multi valued */ 5021*4a1a9510SRong-En Fan menu_opts_off(my_menu, O_ONEVALUE); 5022*4a1a9510SRong-En Fan 5023*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Use <SPACE> to select or unselect an item."); 5024*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "<ENTER> to see presently selected items(F1 to Exit)"); 5025*4a1a9510SRong-En Fan post_menu(my_menu); 5026*4a1a9510SRong-En Fan refresh(); 5027*4a1a9510SRong-En Fan 5028*4a1a9510SRong-En Fan while((c = getch()) != KEY_F(1)) 5029*4a1a9510SRong-En Fan { switch(c) 5030*4a1a9510SRong-En Fan { case KEY_DOWN: 5031*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 5032*4a1a9510SRong-En Fan break; 5033*4a1a9510SRong-En Fan case KEY_UP: 5034*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 5035*4a1a9510SRong-En Fan break; 5036*4a1a9510SRong-En Fan case ' ': 5037*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_TOGGLE_ITEM); 5038*4a1a9510SRong-En Fan break; 5039*4a1a9510SRong-En Fan case 10: /* Enter */ 5040*4a1a9510SRong-En Fan { char temp[200]; 5041*4a1a9510SRong-En Fan ITEM **items; 5042*4a1a9510SRong-En Fan 5043*4a1a9510SRong-En Fan items = menu_items(my_menu); 5044*4a1a9510SRong-En Fan temp[0] = '\0'; 5045*4a1a9510SRong-En Fan for(i = 0; i < item_count(my_menu); ++i) 5046*4a1a9510SRong-En Fan if(item_value(items[i]) == TRUE) 5047*4a1a9510SRong-En Fan { strcat(temp, item_name(items[i])); 5048*4a1a9510SRong-En Fan strcat(temp, " "); 5049*4a1a9510SRong-En Fan } 5050*4a1a9510SRong-En Fan move(20, 0); 5051*4a1a9510SRong-En Fan clrtoeol(); 5052*4a1a9510SRong-En Fan mvprintw(20, 0, temp); 5053*4a1a9510SRong-En Fan refresh(); 5054*4a1a9510SRong-En Fan } 5055*4a1a9510SRong-En Fan break; 5056*4a1a9510SRong-En Fan } 5057*4a1a9510SRong-En Fan } 5058*4a1a9510SRong-En Fan 5059*4a1a9510SRong-En Fan free_item(my_items[0]); 5060*4a1a9510SRong-En Fan free_item(my_items[1]); 5061*4a1a9510SRong-En Fan free_menu(my_menu); 5062*4a1a9510SRong-En Fan endwin(); 5063*4a1a9510SRong-En Fan} 5064*4a1a9510SRong-En Fan </span> 5065*4a1a9510SRong-En Fan</pre> 5066*4a1a9510SRong-En Fan </div> 5067*4a1a9510SRong-En Fan 5068*4a1a9510SRong-En Fan <p>Whew, A lot of new functions. Let's take them one after 5069*4a1a9510SRong-En Fan another. Firstly, the REQ_TOGGLE_ITEM. In a multi-valued 5070*4a1a9510SRong-En Fan menu, the user should be allowed to select or un select 5071*4a1a9510SRong-En Fan more than one item. The request REQ_TOGGLE_ITEM toggles the 5072*4a1a9510SRong-En Fan present selection. In this case when space is pressed 5073*4a1a9510SRong-En Fan REQ_TOGGLE_ITEM request is sent to menu_driver to achieve 5074*4a1a9510SRong-En Fan the result.</p> 5075*4a1a9510SRong-En Fan 5076*4a1a9510SRong-En Fan <p>Now when the user presses <ENTER> we show the 5077*4a1a9510SRong-En Fan items he presently selected. First we find out the items 5078*4a1a9510SRong-En Fan associated with the menu using the function menu_items(). 5079*4a1a9510SRong-En Fan Then we loop through the items to find out if the item is 5080*4a1a9510SRong-En Fan selected or not. The function item_value() returns TRUE if 5081*4a1a9510SRong-En Fan an item is selected. The function item_count() returns the 5082*4a1a9510SRong-En Fan number of items in the menu. The item name can be found 5083*4a1a9510SRong-En Fan with item_name(). You can also find the description 5084*4a1a9510SRong-En Fan associated with an item using item_description().</p> 5085*4a1a9510SRong-En Fan </div> 5086*4a1a9510SRong-En Fan 5087*4a1a9510SRong-En Fan <div class="SECT2"> 5088*4a1a9510SRong-En Fan <hr> 5089*4a1a9510SRong-En Fan 5090*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MENUOPT" id="MENUOPT">17.8. Menu 5091*4a1a9510SRong-En Fan Options</a></h3> 5092*4a1a9510SRong-En Fan 5093*4a1a9510SRong-En Fan <p>Well, by this time you must be itching for some 5094*4a1a9510SRong-En Fan difference in your menu, with lots of functionality. I 5095*4a1a9510SRong-En Fan know. You want Colors !!!. You want to create nice menus 5096*4a1a9510SRong-En Fan similar to those text mode <a href= 5097*4a1a9510SRong-En Fan "http://www.jersey.net/~debinjoe/games/" target="_top">dos 5098*4a1a9510SRong-En Fan games</a>. The functions set_menu_fore() and 5099*4a1a9510SRong-En Fan set_menu_back() can be used to change the attribute of the 5100*4a1a9510SRong-En Fan selected item and unselected item. The names are 5101*4a1a9510SRong-En Fan misleading. They don't change menu's foreground or 5102*4a1a9510SRong-En Fan background which would have been useless.</p> 5103*4a1a9510SRong-En Fan 5104*4a1a9510SRong-En Fan <p>The function set_menu_grey() can be used to set the 5105*4a1a9510SRong-En Fan display attribute for the non-selectable items in the menu. 5106*4a1a9510SRong-En Fan This brings us to the interesting option for an item the 5107*4a1a9510SRong-En Fan one and only O_SELECTABLE. We can turn it off by the 5108*4a1a9510SRong-En Fan function item_opts_off() and after that that item is not 5109*4a1a9510SRong-En Fan selectable. It's like a grayed item in those fancy windows 5110*4a1a9510SRong-En Fan menus. Let's put these concepts in practice with this 5111*4a1a9510SRong-En Fan example</p> 5112*4a1a9510SRong-En Fan 5113*4a1a9510SRong-En Fan <div class="EXAMPLE"> 5114*4a1a9510SRong-En Fan <a name="MMEAT" id="MMEAT"></a> 5115*4a1a9510SRong-En Fan 5116*4a1a9510SRong-En Fan <p><b>Example 23. Menu Options example</b></p> 5117*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5118*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <menu.h> 5119*4a1a9510SRong-En Fan 5120*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5121*4a1a9510SRong-En Fan#define CTRLD 4 5122*4a1a9510SRong-En Fan 5123*4a1a9510SRong-En Fanchar *choices[] = { 5124*4a1a9510SRong-En Fan "Choice 1", 5125*4a1a9510SRong-En Fan "Choice 2", 5126*4a1a9510SRong-En Fan "Choice 3", 5127*4a1a9510SRong-En Fan "Choice 4", 5128*4a1a9510SRong-En Fan "Choice 5", 5129*4a1a9510SRong-En Fan "Choice 6", 5130*4a1a9510SRong-En Fan "Choice 7", 5131*4a1a9510SRong-En Fan "Exit", 5132*4a1a9510SRong-En Fan }; 5133*4a1a9510SRong-En Fan 5134*4a1a9510SRong-En Fanint main() 5135*4a1a9510SRong-En Fan{ ITEM **my_items; 5136*4a1a9510SRong-En Fan int c; 5137*4a1a9510SRong-En Fan MENU *my_menu; 5138*4a1a9510SRong-En Fan int n_choices, i; 5139*4a1a9510SRong-En Fan ITEM *cur_item; 5140*4a1a9510SRong-En Fan 5141*4a1a9510SRong-En Fan /* Initialize curses */ 5142*4a1a9510SRong-En Fan initscr(); 5143*4a1a9510SRong-En Fan start_color(); 5144*4a1a9510SRong-En Fan cbreak(); 5145*4a1a9510SRong-En Fan noecho(); 5146*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5147*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 5148*4a1a9510SRong-En Fan init_pair(2, COLOR_GREEN, COLOR_BLACK); 5149*4a1a9510SRong-En Fan init_pair(3, COLOR_MAGENTA, COLOR_BLACK); 5150*4a1a9510SRong-En Fan 5151*4a1a9510SRong-En Fan /* Initialize items */ 5152*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 5153*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 5154*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 5155*4a1a9510SRong-En Fan my_items[i] = new_item(choices[i], choices[i]); 5156*4a1a9510SRong-En Fan my_items[n_choices] = (ITEM *)NULL; 5157*4a1a9510SRong-En Fan item_opts_off(my_items[3], O_SELECTABLE); 5158*4a1a9510SRong-En Fan item_opts_off(my_items[6], O_SELECTABLE); 5159*4a1a9510SRong-En Fan 5160*4a1a9510SRong-En Fan /* Create menu */ 5161*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 5162*4a1a9510SRong-En Fan 5163*4a1a9510SRong-En Fan /* Set fore ground and back ground of the menu */ 5164*4a1a9510SRong-En Fan set_menu_fore(my_menu, COLOR_PAIR(1) | A_REVERSE); 5165*4a1a9510SRong-En Fan set_menu_back(my_menu, COLOR_PAIR(2)); 5166*4a1a9510SRong-En Fan set_menu_grey(my_menu, COLOR_PAIR(3)); 5167*4a1a9510SRong-En Fan 5168*4a1a9510SRong-En Fan /* Post the menu */ 5169*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Press <ENTER> to see the option selected"); 5170*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)"); 5171*4a1a9510SRong-En Fan post_menu(my_menu); 5172*4a1a9510SRong-En Fan refresh(); 5173*4a1a9510SRong-En Fan 5174*4a1a9510SRong-En Fan while((c = getch()) != KEY_F(1)) 5175*4a1a9510SRong-En Fan { switch(c) 5176*4a1a9510SRong-En Fan { case KEY_DOWN: 5177*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 5178*4a1a9510SRong-En Fan break; 5179*4a1a9510SRong-En Fan case KEY_UP: 5180*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 5181*4a1a9510SRong-En Fan break; 5182*4a1a9510SRong-En Fan case 10: /* Enter */ 5183*4a1a9510SRong-En Fan move(20, 0); 5184*4a1a9510SRong-En Fan clrtoeol(); 5185*4a1a9510SRong-En Fan mvprintw(20, 0, "Item selected is : %s", 5186*4a1a9510SRong-En Fan item_name(current_item(my_menu))); 5187*4a1a9510SRong-En Fan pos_menu_cursor(my_menu); 5188*4a1a9510SRong-En Fan break; 5189*4a1a9510SRong-En Fan } 5190*4a1a9510SRong-En Fan } 5191*4a1a9510SRong-En Fan unpost_menu(my_menu); 5192*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 5193*4a1a9510SRong-En Fan free_item(my_items[i]); 5194*4a1a9510SRong-En Fan free_menu(my_menu); 5195*4a1a9510SRong-En Fan endwin(); 5196*4a1a9510SRong-En Fan} 5197*4a1a9510SRong-En Fan </span> 5198*4a1a9510SRong-En Fan</pre> 5199*4a1a9510SRong-En Fan </div> 5200*4a1a9510SRong-En Fan </div> 5201*4a1a9510SRong-En Fan 5202*4a1a9510SRong-En Fan <div class="SECT2"> 5203*4a1a9510SRong-En Fan <hr> 5204*4a1a9510SRong-En Fan 5205*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="MENUUSERPTR" id= 5206*4a1a9510SRong-En Fan "MENUUSERPTR">17.9. The useful User Pointer</a></h3> 5207*4a1a9510SRong-En Fan 5208*4a1a9510SRong-En Fan <p>We can associate a user pointer with each item in the 5209*4a1a9510SRong-En Fan menu. It works the same way as user pointer in panels. It's 5210*4a1a9510SRong-En Fan not touched by menu system. You can store any thing you 5211*4a1a9510SRong-En Fan like in that. I usually use it to store the function to be 5212*4a1a9510SRong-En Fan executed when the menu option is chosen (It's selected and 5213*4a1a9510SRong-En Fan may be the user pressed <ENTER>);</p> 5214*4a1a9510SRong-En Fan 5215*4a1a9510SRong-En Fan <div class="EXAMPLE"> 5216*4a1a9510SRong-En Fan <a name="MMEUS" id="MMEUS"></a> 5217*4a1a9510SRong-En Fan 5218*4a1a9510SRong-En Fan <p><b>Example 24. Menu User Pointer Usage</b></p> 5219*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5220*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <curses.h> 5221*4a1a9510SRong-En Fan#include <menu.h> 5222*4a1a9510SRong-En Fan 5223*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5224*4a1a9510SRong-En Fan#define CTRLD 4 5225*4a1a9510SRong-En Fan 5226*4a1a9510SRong-En Fanchar *choices[] = { 5227*4a1a9510SRong-En Fan "Choice 1", 5228*4a1a9510SRong-En Fan "Choice 2", 5229*4a1a9510SRong-En Fan "Choice 3", 5230*4a1a9510SRong-En Fan "Choice 4", 5231*4a1a9510SRong-En Fan "Choice 5", 5232*4a1a9510SRong-En Fan "Choice 6", 5233*4a1a9510SRong-En Fan "Choice 7", 5234*4a1a9510SRong-En Fan "Exit", 5235*4a1a9510SRong-En Fan }; 5236*4a1a9510SRong-En Fanvoid func(char *name); 5237*4a1a9510SRong-En Fan 5238*4a1a9510SRong-En Fanint main() 5239*4a1a9510SRong-En Fan{ ITEM **my_items; 5240*4a1a9510SRong-En Fan int c; 5241*4a1a9510SRong-En Fan MENU *my_menu; 5242*4a1a9510SRong-En Fan int n_choices, i; 5243*4a1a9510SRong-En Fan ITEM *cur_item; 5244*4a1a9510SRong-En Fan 5245*4a1a9510SRong-En Fan /* Initialize curses */ 5246*4a1a9510SRong-En Fan initscr(); 5247*4a1a9510SRong-En Fan start_color(); 5248*4a1a9510SRong-En Fan cbreak(); 5249*4a1a9510SRong-En Fan noecho(); 5250*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5251*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 5252*4a1a9510SRong-En Fan init_pair(2, COLOR_GREEN, COLOR_BLACK); 5253*4a1a9510SRong-En Fan init_pair(3, COLOR_MAGENTA, COLOR_BLACK); 5254*4a1a9510SRong-En Fan 5255*4a1a9510SRong-En Fan /* Initialize items */ 5256*4a1a9510SRong-En Fan n_choices = ARRAY_SIZE(choices); 5257*4a1a9510SRong-En Fan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 5258*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 5259*4a1a9510SRong-En Fan { my_items[i] = new_item(choices[i], choices[i]); 5260*4a1a9510SRong-En Fan /* Set the user pointer */ 5261*4a1a9510SRong-En Fan set_item_userptr(my_items[i], func); 5262*4a1a9510SRong-En Fan } 5263*4a1a9510SRong-En Fan my_items[n_choices] = (ITEM *)NULL; 5264*4a1a9510SRong-En Fan 5265*4a1a9510SRong-En Fan /* Create menu */ 5266*4a1a9510SRong-En Fan my_menu = new_menu((ITEM **)my_items); 5267*4a1a9510SRong-En Fan 5268*4a1a9510SRong-En Fan /* Post the menu */ 5269*4a1a9510SRong-En Fan mvprintw(LINES - 3, 0, "Press <ENTER> to see the option selected"); 5270*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)"); 5271*4a1a9510SRong-En Fan post_menu(my_menu); 5272*4a1a9510SRong-En Fan refresh(); 5273*4a1a9510SRong-En Fan 5274*4a1a9510SRong-En Fan while((c = getch()) != KEY_F(1)) 5275*4a1a9510SRong-En Fan { switch(c) 5276*4a1a9510SRong-En Fan { case KEY_DOWN: 5277*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_DOWN_ITEM); 5278*4a1a9510SRong-En Fan break; 5279*4a1a9510SRong-En Fan case KEY_UP: 5280*4a1a9510SRong-En Fan menu_driver(my_menu, REQ_UP_ITEM); 5281*4a1a9510SRong-En Fan break; 5282*4a1a9510SRong-En Fan case 10: /* Enter */ 5283*4a1a9510SRong-En Fan { ITEM *cur; 5284*4a1a9510SRong-En Fan void (*p)(char *); 5285*4a1a9510SRong-En Fan 5286*4a1a9510SRong-En Fan cur = current_item(my_menu); 5287*4a1a9510SRong-En Fan p = item_userptr(cur); 5288*4a1a9510SRong-En Fan p((char *)item_name(cur)); 5289*4a1a9510SRong-En Fan pos_menu_cursor(my_menu); 5290*4a1a9510SRong-En Fan break; 5291*4a1a9510SRong-En Fan } 5292*4a1a9510SRong-En Fan break; 5293*4a1a9510SRong-En Fan } 5294*4a1a9510SRong-En Fan } 5295*4a1a9510SRong-En Fan unpost_menu(my_menu); 5296*4a1a9510SRong-En Fan for(i = 0; i < n_choices; ++i) 5297*4a1a9510SRong-En Fan free_item(my_items[i]); 5298*4a1a9510SRong-En Fan free_menu(my_menu); 5299*4a1a9510SRong-En Fan endwin(); 5300*4a1a9510SRong-En Fan} 5301*4a1a9510SRong-En Fan 5302*4a1a9510SRong-En Fanvoid func(char *name) 5303*4a1a9510SRong-En Fan{ move(20, 0); 5304*4a1a9510SRong-En Fan clrtoeol(); 5305*4a1a9510SRong-En Fan mvprintw(20, 0, "Item selected is : %s", name); 5306*4a1a9510SRong-En Fan} </span> 5307*4a1a9510SRong-En Fan</pre> 5308*4a1a9510SRong-En Fan </div> 5309*4a1a9510SRong-En Fan </div> 5310*4a1a9510SRong-En Fan </div> 5311*4a1a9510SRong-En Fan 5312*4a1a9510SRong-En Fan <div class="SECT1"> 5313*4a1a9510SRong-En Fan <hr> 5314*4a1a9510SRong-En Fan 5315*4a1a9510SRong-En Fan <h2 class="SECT1"><a name="FORMS" id="FORMS">18. Forms 5316*4a1a9510SRong-En Fan Library</a></h2> 5317*4a1a9510SRong-En Fan 5318*4a1a9510SRong-En Fan <p>Well. If you have seen those forms on web pages which take 5319*4a1a9510SRong-En Fan input from users and do various kinds of things, you might be 5320*4a1a9510SRong-En Fan wondering how would any one create such forms in text mode 5321*4a1a9510SRong-En Fan display. It's quite difficult to write those nifty forms in 5322*4a1a9510SRong-En Fan plain ncurses. Forms library tries to provide a basic frame 5323*4a1a9510SRong-En Fan work to build and maintain forms with ease. It has lot of 5324*4a1a9510SRong-En Fan features(functions) which manage validation, dynamic 5325*4a1a9510SRong-En Fan expansion of fields etc.. Let's see it in full flow.</p> 5326*4a1a9510SRong-En Fan 5327*4a1a9510SRong-En Fan <p>A form is a collection of fields; each field can be either 5328*4a1a9510SRong-En Fan a label(static text) or a data-entry location. The forms also 5329*4a1a9510SRong-En Fan library provides functions to divide forms into multiple 5330*4a1a9510SRong-En Fan pages.</p> 5331*4a1a9510SRong-En Fan 5332*4a1a9510SRong-En Fan <div class="SECT2"> 5333*4a1a9510SRong-En Fan <hr> 5334*4a1a9510SRong-En Fan 5335*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="FORMBASICS" id= 5336*4a1a9510SRong-En Fan "FORMBASICS">18.1. The Basics</a></h3> 5337*4a1a9510SRong-En Fan 5338*4a1a9510SRong-En Fan <p>Forms are created in much the same way as menus. First 5339*4a1a9510SRong-En Fan the fields related to the form are created with 5340*4a1a9510SRong-En Fan new_field(). You can set options for the fields, so that 5341*4a1a9510SRong-En Fan they can be displayed with some fancy attributes, validated 5342*4a1a9510SRong-En Fan before the field looses focus etc.. Then the fields are 5343*4a1a9510SRong-En Fan attached to form. After this, the form can be posted to 5344*4a1a9510SRong-En Fan display and is ready to receive inputs. On the similar 5345*4a1a9510SRong-En Fan lines to menu_driver(), the form is manipulated with 5346*4a1a9510SRong-En Fan form_driver(). We can send requests to form_driver to move 5347*4a1a9510SRong-En Fan focus to a certain field, move cursor to end of the field 5348*4a1a9510SRong-En Fan etc.. After the user enters values in the fields and 5349*4a1a9510SRong-En Fan validation done, form can be unposted and memory allocated 5350*4a1a9510SRong-En Fan can be freed.</p> 5351*4a1a9510SRong-En Fan 5352*4a1a9510SRong-En Fan <p>The general flow of control of a forms program looks 5353*4a1a9510SRong-En Fan like this.</p> 5354*4a1a9510SRong-En Fan 5355*4a1a9510SRong-En Fan <ol type="1"> 5356*4a1a9510SRong-En Fan <li> 5357*4a1a9510SRong-En Fan <p>Initialize curses</p> 5358*4a1a9510SRong-En Fan </li> 5359*4a1a9510SRong-En Fan 5360*4a1a9510SRong-En Fan <li> 5361*4a1a9510SRong-En Fan <p>Create fields using new_field(). You can specify the 5362*4a1a9510SRong-En Fan height and width of the field, and its position on the 5363*4a1a9510SRong-En Fan form.</p> 5364*4a1a9510SRong-En Fan </li> 5365*4a1a9510SRong-En Fan 5366*4a1a9510SRong-En Fan <li> 5367*4a1a9510SRong-En Fan <p>Create the forms with new_form() by specifying the 5368*4a1a9510SRong-En Fan fields to be attached with.</p> 5369*4a1a9510SRong-En Fan </li> 5370*4a1a9510SRong-En Fan 5371*4a1a9510SRong-En Fan <li> 5372*4a1a9510SRong-En Fan <p>Post the form with form_post() and refresh the 5373*4a1a9510SRong-En Fan screen.</p> 5374*4a1a9510SRong-En Fan </li> 5375*4a1a9510SRong-En Fan 5376*4a1a9510SRong-En Fan <li> 5377*4a1a9510SRong-En Fan <p>Process the user requests with a loop and do 5378*4a1a9510SRong-En Fan necessary updates to form with form_driver.</p> 5379*4a1a9510SRong-En Fan </li> 5380*4a1a9510SRong-En Fan 5381*4a1a9510SRong-En Fan <li> 5382*4a1a9510SRong-En Fan <p>Unpost the menu with form_unpost()</p> 5383*4a1a9510SRong-En Fan </li> 5384*4a1a9510SRong-En Fan 5385*4a1a9510SRong-En Fan <li> 5386*4a1a9510SRong-En Fan <p>Free the memory allocated to menu by free_form()</p> 5387*4a1a9510SRong-En Fan </li> 5388*4a1a9510SRong-En Fan 5389*4a1a9510SRong-En Fan <li> 5390*4a1a9510SRong-En Fan <p>Free the memory allocated to the items with 5391*4a1a9510SRong-En Fan free_field()</p> 5392*4a1a9510SRong-En Fan </li> 5393*4a1a9510SRong-En Fan 5394*4a1a9510SRong-En Fan <li> 5395*4a1a9510SRong-En Fan <p>End curses</p> 5396*4a1a9510SRong-En Fan </li> 5397*4a1a9510SRong-En Fan </ol> 5398*4a1a9510SRong-En Fan 5399*4a1a9510SRong-En Fan <p>As you can see, working with forms library is much 5400*4a1a9510SRong-En Fan similar to handling menu library. The following examples 5401*4a1a9510SRong-En Fan will explore various aspects of form processing. Let's 5402*4a1a9510SRong-En Fan start the journey with a simple example. first.</p> 5403*4a1a9510SRong-En Fan </div> 5404*4a1a9510SRong-En Fan 5405*4a1a9510SRong-En Fan <div class="SECT2"> 5406*4a1a9510SRong-En Fan <hr> 5407*4a1a9510SRong-En Fan 5408*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="COMPILEFORMS" id= 5409*4a1a9510SRong-En Fan "COMPILEFORMS">18.2. Compiling With the Forms 5410*4a1a9510SRong-En Fan Library</a></h3> 5411*4a1a9510SRong-En Fan 5412*4a1a9510SRong-En Fan <p>To use forms library functions, you have to include 5413*4a1a9510SRong-En Fan form.h and to link the program with forms library the flag 5414*4a1a9510SRong-En Fan -lform should be added along with -lncurses in that 5415*4a1a9510SRong-En Fan order.</p> 5416*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5417*4a1a9510SRong-En Fan #include <form.h> 5418*4a1a9510SRong-En Fan . 5419*4a1a9510SRong-En Fan . 5420*4a1a9510SRong-En Fan . 5421*4a1a9510SRong-En Fan 5422*4a1a9510SRong-En Fan compile and link: gcc <program file> -lform -lncurses 5423*4a1a9510SRong-En Fan</pre> 5424*4a1a9510SRong-En Fan 5425*4a1a9510SRong-En Fan <div class="EXAMPLE"> 5426*4a1a9510SRong-En Fan <a name="FFOSI" id="FFOSI"></a> 5427*4a1a9510SRong-En Fan 5428*4a1a9510SRong-En Fan <p><b>Example 25. Forms Basics</b></p> 5429*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5430*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <form.h> 5431*4a1a9510SRong-En Fan 5432*4a1a9510SRong-En Fanint main() 5433*4a1a9510SRong-En Fan{ FIELD *field[3]; 5434*4a1a9510SRong-En Fan FORM *my_form; 5435*4a1a9510SRong-En Fan int ch; 5436*4a1a9510SRong-En Fan 5437*4a1a9510SRong-En Fan /* Initialize curses */ 5438*4a1a9510SRong-En Fan initscr(); 5439*4a1a9510SRong-En Fan cbreak(); 5440*4a1a9510SRong-En Fan noecho(); 5441*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5442*4a1a9510SRong-En Fan 5443*4a1a9510SRong-En Fan /* Initialize the fields */ 5444*4a1a9510SRong-En Fan field[0] = new_field(1, 10, 4, 18, 0, 0); 5445*4a1a9510SRong-En Fan field[1] = new_field(1, 10, 6, 18, 0, 0); 5446*4a1a9510SRong-En Fan field[2] = NULL; 5447*4a1a9510SRong-En Fan 5448*4a1a9510SRong-En Fan /* Set field options */ 5449*4a1a9510SRong-En Fan set_field_back(field[0], A_UNDERLINE); /* Print a line for the option */ 5450*4a1a9510SRong-En Fan field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 5451*4a1a9510SRong-En Fan /* Field is filled up */ 5452*4a1a9510SRong-En Fan set_field_back(field[1], A_UNDERLINE); 5453*4a1a9510SRong-En Fan field_opts_off(field[1], O_AUTOSKIP); 5454*4a1a9510SRong-En Fan 5455*4a1a9510SRong-En Fan /* Create the form and post it */ 5456*4a1a9510SRong-En Fan my_form = new_form(field); 5457*4a1a9510SRong-En Fan post_form(my_form); 5458*4a1a9510SRong-En Fan refresh(); 5459*4a1a9510SRong-En Fan 5460*4a1a9510SRong-En Fan mvprintw(4, 10, "Value 1:"); 5461*4a1a9510SRong-En Fan mvprintw(6, 10, "Value 2:"); 5462*4a1a9510SRong-En Fan refresh(); 5463*4a1a9510SRong-En Fan 5464*4a1a9510SRong-En Fan /* Loop through to get user requests */ 5465*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 5466*4a1a9510SRong-En Fan { switch(ch) 5467*4a1a9510SRong-En Fan { case KEY_DOWN: 5468*4a1a9510SRong-En Fan /* Go to next field */ 5469*4a1a9510SRong-En Fan form_driver(my_form, REQ_NEXT_FIELD); 5470*4a1a9510SRong-En Fan /* Go to the end of the present buffer */ 5471*4a1a9510SRong-En Fan /* Leaves nicely at the last character */ 5472*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5473*4a1a9510SRong-En Fan break; 5474*4a1a9510SRong-En Fan case KEY_UP: 5475*4a1a9510SRong-En Fan /* Go to previous field */ 5476*4a1a9510SRong-En Fan form_driver(my_form, REQ_PREV_FIELD); 5477*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5478*4a1a9510SRong-En Fan break; 5479*4a1a9510SRong-En Fan default: 5480*4a1a9510SRong-En Fan /* If this is a normal character, it gets */ 5481*4a1a9510SRong-En Fan /* Printed */ 5482*4a1a9510SRong-En Fan form_driver(my_form, ch); 5483*4a1a9510SRong-En Fan break; 5484*4a1a9510SRong-En Fan } 5485*4a1a9510SRong-En Fan } 5486*4a1a9510SRong-En Fan 5487*4a1a9510SRong-En Fan /* Un post form and free the memory */ 5488*4a1a9510SRong-En Fan unpost_form(my_form); 5489*4a1a9510SRong-En Fan free_form(my_form); 5490*4a1a9510SRong-En Fan free_field(field[0]); 5491*4a1a9510SRong-En Fan free_field(field[1]); 5492*4a1a9510SRong-En Fan 5493*4a1a9510SRong-En Fan endwin(); 5494*4a1a9510SRong-En Fan return 0; 5495*4a1a9510SRong-En Fan}</span> 5496*4a1a9510SRong-En Fan</pre> 5497*4a1a9510SRong-En Fan </div> 5498*4a1a9510SRong-En Fan 5499*4a1a9510SRong-En Fan <p>Above example is pretty straight forward. It creates two 5500*4a1a9510SRong-En Fan fields with <tt class="LITERAL">new_field()</tt>. 5501*4a1a9510SRong-En Fan new_field() takes height, width, starty, startx, number of 5502*4a1a9510SRong-En Fan offscreen rows and number of additional working buffers. 5503*4a1a9510SRong-En Fan The fifth argument number of offscreen rows specifies how 5504*4a1a9510SRong-En Fan much of the field to be shown. If it is zero, the entire 5505*4a1a9510SRong-En Fan field is always displayed otherwise the form will be 5506*4a1a9510SRong-En Fan scrollable when the user accesses not displayed parts of 5507*4a1a9510SRong-En Fan the field. The forms library allocates one buffer per field 5508*4a1a9510SRong-En Fan to store the data user enters. Using the last parameter to 5509*4a1a9510SRong-En Fan new_field() we can specify it to allocate some additional 5510*4a1a9510SRong-En Fan buffers. These can be used for any purpose you like.</p> 5511*4a1a9510SRong-En Fan 5512*4a1a9510SRong-En Fan <p>After creating the fields, back ground attribute of both 5513*4a1a9510SRong-En Fan of them is set to an underscore with set_field_back(). The 5514*4a1a9510SRong-En Fan AUTOSKIP option is turned off using field_opts_off(). If 5515*4a1a9510SRong-En Fan this option is turned on, focus will move to the next field 5516*4a1a9510SRong-En Fan in the form once the active field is filled up 5517*4a1a9510SRong-En Fan completely.</p> 5518*4a1a9510SRong-En Fan 5519*4a1a9510SRong-En Fan <p>After attaching the fields to the form, it is posted. 5520*4a1a9510SRong-En Fan Here on, user inputs are processed in the while loop, by 5521*4a1a9510SRong-En Fan making corresponding requests to form_driver. The details 5522*4a1a9510SRong-En Fan of all the requests to the form_driver() are explained 5523*4a1a9510SRong-En Fan later.</p> 5524*4a1a9510SRong-En Fan </div> 5525*4a1a9510SRong-En Fan 5526*4a1a9510SRong-En Fan <div class="SECT2"> 5527*4a1a9510SRong-En Fan <hr> 5528*4a1a9510SRong-En Fan 5529*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="PLAYFIELDS" id= 5530*4a1a9510SRong-En Fan "PLAYFIELDS">18.3. Playing with Fields</a></h3> 5531*4a1a9510SRong-En Fan 5532*4a1a9510SRong-En Fan <p>Each form field is associated with a lot of attributes. 5533*4a1a9510SRong-En Fan They can be manipulated to get the required effect and to 5534*4a1a9510SRong-En Fan have fun !!!. So why wait?</p> 5535*4a1a9510SRong-En Fan 5536*4a1a9510SRong-En Fan <div class="SECT3"> 5537*4a1a9510SRong-En Fan <hr> 5538*4a1a9510SRong-En Fan 5539*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="FETCHINFO" id= 5540*4a1a9510SRong-En Fan "FETCHINFO">18.3.1. Fetching Size and Location of 5541*4a1a9510SRong-En Fan Field</a></h4> 5542*4a1a9510SRong-En Fan 5543*4a1a9510SRong-En Fan <p>The parameters we have given at the time of creation 5544*4a1a9510SRong-En Fan of a field can be retrieved with field_info(). It returns 5545*4a1a9510SRong-En Fan height, width, starty, startx, number of offscreen rows, 5546*4a1a9510SRong-En Fan and number of additional buffers into the parameters 5547*4a1a9510SRong-En Fan given to it. It is a sort of inverse of new_field().</p> 5548*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5549*4a1a9510SRong-En Fanint field_info( FIELD *field, /* field from which to fetch */ 5550*4a1a9510SRong-En Fan int *height, *int width, /* field size */ 5551*4a1a9510SRong-En Fan int *top, int *left, /* upper left corner */ 5552*4a1a9510SRong-En Fan int *offscreen, /* number of offscreen rows */ 5553*4a1a9510SRong-En Fan int *nbuf); /* number of working buffers */ 5554*4a1a9510SRong-En Fan</pre> 5555*4a1a9510SRong-En Fan </div> 5556*4a1a9510SRong-En Fan 5557*4a1a9510SRong-En Fan <div class="SECT3"> 5558*4a1a9510SRong-En Fan <hr> 5559*4a1a9510SRong-En Fan 5560*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="MOVEFIELD" id= 5561*4a1a9510SRong-En Fan "MOVEFIELD">18.3.2. Moving the field</a></h4> 5562*4a1a9510SRong-En Fan 5563*4a1a9510SRong-En Fan <p>The location of the field can be moved to a different 5564*4a1a9510SRong-En Fan position with move_field().</p> 5565*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5566*4a1a9510SRong-En Fanint move_field( FIELD *field, /* field to alter */ 5567*4a1a9510SRong-En Fan int top, int left); /* new upper-left corner */ 5568*4a1a9510SRong-En Fan</pre> 5569*4a1a9510SRong-En Fan 5570*4a1a9510SRong-En Fan <p>As usual, the changed position can be queried with 5571*4a1a9510SRong-En Fan field_infor().</p> 5572*4a1a9510SRong-En Fan </div> 5573*4a1a9510SRong-En Fan 5574*4a1a9510SRong-En Fan <div class="SECT3"> 5575*4a1a9510SRong-En Fan <hr> 5576*4a1a9510SRong-En Fan 5577*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="JUSTIFYFIELD" id= 5578*4a1a9510SRong-En Fan "JUSTIFYFIELD">18.3.3. Field Justification</a></h4> 5579*4a1a9510SRong-En Fan 5580*4a1a9510SRong-En Fan <p>The justification to be done for the field can be 5581*4a1a9510SRong-En Fan fixed using the function set_field_just().</p> 5582*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5583*4a1a9510SRong-En Fan int set_field_just(FIELD *field, /* field to alter */ 5584*4a1a9510SRong-En Fan int justmode); /* mode to set */ 5585*4a1a9510SRong-En Fan int field_just(FIELD *field); /* fetch justify mode of field */ 5586*4a1a9510SRong-En Fan</pre> 5587*4a1a9510SRong-En Fan 5588*4a1a9510SRong-En Fan <p>The justification mode valued accepted and returned by 5589*4a1a9510SRong-En Fan these functions are NO_JUSTIFICATION, JUSTIFY_RIGHT, 5590*4a1a9510SRong-En Fan JUSTIFY_LEFT, or JUSTIFY_CENTER.</p> 5591*4a1a9510SRong-En Fan </div> 5592*4a1a9510SRong-En Fan 5593*4a1a9510SRong-En Fan <div class="SECT3"> 5594*4a1a9510SRong-En Fan <hr> 5595*4a1a9510SRong-En Fan 5596*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="FIELDDISPATTRIB" id= 5597*4a1a9510SRong-En Fan "FIELDDISPATTRIB">18.3.4. Field Display 5598*4a1a9510SRong-En Fan Attributes</a></h4> 5599*4a1a9510SRong-En Fan 5600*4a1a9510SRong-En Fan <p>As you have seen, in the above example, display 5601*4a1a9510SRong-En Fan attribute for the fields can be set with set_field_fore() 5602*4a1a9510SRong-En Fan and setfield_back(). These functions set foreground and 5603*4a1a9510SRong-En Fan background attribute of the fields. You can also specify 5604*4a1a9510SRong-En Fan a pad character which will be filled in the unfilled 5605*4a1a9510SRong-En Fan portion of the field. The pad character is set with a 5606*4a1a9510SRong-En Fan call to set_field_pad(). Default pad value is a space. 5607*4a1a9510SRong-En Fan The functions field_fore(), field_back, field_pad() can 5608*4a1a9510SRong-En Fan be used to query the present foreground, background 5609*4a1a9510SRong-En Fan attributes and pad character for the field. The following 5610*4a1a9510SRong-En Fan list gives the usage of functions.</p> 5611*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5612*4a1a9510SRong-En Fan int set_field_fore(FIELD *field, /* field to alter */ 5613*4a1a9510SRong-En Fan chtype attr); /* attribute to set */ 5614*4a1a9510SRong-En Fan 5615*4a1a9510SRong-En Fanchtype field_fore(FIELD *field); /* field to query */ 5616*4a1a9510SRong-En Fan /* returns foreground attribute */ 5617*4a1a9510SRong-En Fan 5618*4a1a9510SRong-En Fanint set_field_back(FIELD *field, /* field to alter */ 5619*4a1a9510SRong-En Fan chtype attr); /* attribute to set */ 5620*4a1a9510SRong-En Fan 5621*4a1a9510SRong-En Fanchtype field_back(FIELD *field); /* field to query */ 5622*4a1a9510SRong-En Fan /* returns background attribute */ 5623*4a1a9510SRong-En Fan 5624*4a1a9510SRong-En Fanint set_field_pad(FIELD *field, /* field to alter */ 5625*4a1a9510SRong-En Fan int pad); /* pad character to set */ 5626*4a1a9510SRong-En Fan 5627*4a1a9510SRong-En Fanchtype field_pad(FIELD *field); /* field to query */ 5628*4a1a9510SRong-En Fan /* returns present pad character */ 5629*4a1a9510SRong-En Fan</pre> 5630*4a1a9510SRong-En Fan 5631*4a1a9510SRong-En Fan <p>Though above functions seem quite simple, using colors 5632*4a1a9510SRong-En Fan with set_field_fore() may be frustrating in the 5633*4a1a9510SRong-En Fan beginning. Let me first explain about foreground and 5634*4a1a9510SRong-En Fan background attributes of a field. The foreground 5635*4a1a9510SRong-En Fan attribute is associated with the character. That means a 5636*4a1a9510SRong-En Fan character in the field is printed with the attribute you 5637*4a1a9510SRong-En Fan have set with set_field_fore(). Background attribute is 5638*4a1a9510SRong-En Fan the attribute used to fill background of field, whether 5639*4a1a9510SRong-En Fan any character is there or not. So what about colors? 5640*4a1a9510SRong-En Fan Since colors are always defined in pairs, what is the 5641*4a1a9510SRong-En Fan right way to display colored fields? Here's an example 5642*4a1a9510SRong-En Fan clarifying color attributes.</p> 5643*4a1a9510SRong-En Fan 5644*4a1a9510SRong-En Fan <div class="EXAMPLE"> 5645*4a1a9510SRong-En Fan <a name="FFOAT" id="FFOAT"></a> 5646*4a1a9510SRong-En Fan 5647*4a1a9510SRong-En Fan <p><b>Example 26. Form Attributes example</b></p> 5648*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5649*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <form.h> 5650*4a1a9510SRong-En Fan 5651*4a1a9510SRong-En Fanint main() 5652*4a1a9510SRong-En Fan{ FIELD *field[3]; 5653*4a1a9510SRong-En Fan FORM *my_form; 5654*4a1a9510SRong-En Fan int ch; 5655*4a1a9510SRong-En Fan 5656*4a1a9510SRong-En Fan /* Initialize curses */ 5657*4a1a9510SRong-En Fan initscr(); 5658*4a1a9510SRong-En Fan start_color(); 5659*4a1a9510SRong-En Fan cbreak(); 5660*4a1a9510SRong-En Fan noecho(); 5661*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5662*4a1a9510SRong-En Fan 5663*4a1a9510SRong-En Fan /* Initialize few color pairs */ 5664*4a1a9510SRong-En Fan init_pair(1, COLOR_WHITE, COLOR_BLUE); 5665*4a1a9510SRong-En Fan init_pair(2, COLOR_WHITE, COLOR_BLUE); 5666*4a1a9510SRong-En Fan 5667*4a1a9510SRong-En Fan /* Initialize the fields */ 5668*4a1a9510SRong-En Fan field[0] = new_field(1, 10, 4, 18, 0, 0); 5669*4a1a9510SRong-En Fan field[1] = new_field(1, 10, 6, 18, 0, 0); 5670*4a1a9510SRong-En Fan field[2] = NULL; 5671*4a1a9510SRong-En Fan 5672*4a1a9510SRong-En Fan /* Set field options */ 5673*4a1a9510SRong-En Fan set_field_fore(field[0], COLOR_PAIR(1));/* Put the field with blue background */ 5674*4a1a9510SRong-En Fan set_field_back(field[0], COLOR_PAIR(2));/* and white foreground (characters */ 5675*4a1a9510SRong-En Fan /* are printed in white */ 5676*4a1a9510SRong-En Fan field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 5677*4a1a9510SRong-En Fan /* Field is filled up */ 5678*4a1a9510SRong-En Fan set_field_back(field[1], A_UNDERLINE); 5679*4a1a9510SRong-En Fan field_opts_off(field[1], O_AUTOSKIP); 5680*4a1a9510SRong-En Fan 5681*4a1a9510SRong-En Fan /* Create the form and post it */ 5682*4a1a9510SRong-En Fan my_form = new_form(field); 5683*4a1a9510SRong-En Fan post_form(my_form); 5684*4a1a9510SRong-En Fan refresh(); 5685*4a1a9510SRong-En Fan 5686*4a1a9510SRong-En Fan set_current_field(my_form, field[0]); /* Set focus to the colored field */ 5687*4a1a9510SRong-En Fan mvprintw(4, 10, "Value 1:"); 5688*4a1a9510SRong-En Fan mvprintw(6, 10, "Value 2:"); 5689*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields"); 5690*4a1a9510SRong-En Fan refresh(); 5691*4a1a9510SRong-En Fan 5692*4a1a9510SRong-En Fan /* Loop through to get user requests */ 5693*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 5694*4a1a9510SRong-En Fan { switch(ch) 5695*4a1a9510SRong-En Fan { case KEY_DOWN: 5696*4a1a9510SRong-En Fan /* Go to next field */ 5697*4a1a9510SRong-En Fan form_driver(my_form, REQ_NEXT_FIELD); 5698*4a1a9510SRong-En Fan /* Go to the end of the present buffer */ 5699*4a1a9510SRong-En Fan /* Leaves nicely at the last character */ 5700*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5701*4a1a9510SRong-En Fan break; 5702*4a1a9510SRong-En Fan case KEY_UP: 5703*4a1a9510SRong-En Fan /* Go to previous field */ 5704*4a1a9510SRong-En Fan form_driver(my_form, REQ_PREV_FIELD); 5705*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5706*4a1a9510SRong-En Fan break; 5707*4a1a9510SRong-En Fan default: 5708*4a1a9510SRong-En Fan /* If this is a normal character, it gets */ 5709*4a1a9510SRong-En Fan /* Printed */ 5710*4a1a9510SRong-En Fan form_driver(my_form, ch); 5711*4a1a9510SRong-En Fan break; 5712*4a1a9510SRong-En Fan } 5713*4a1a9510SRong-En Fan } 5714*4a1a9510SRong-En Fan 5715*4a1a9510SRong-En Fan /* Un post form and free the memory */ 5716*4a1a9510SRong-En Fan unpost_form(my_form); 5717*4a1a9510SRong-En Fan free_form(my_form); 5718*4a1a9510SRong-En Fan free_field(field[0]); 5719*4a1a9510SRong-En Fan free_field(field[1]); 5720*4a1a9510SRong-En Fan 5721*4a1a9510SRong-En Fan endwin(); 5722*4a1a9510SRong-En Fan return 0; 5723*4a1a9510SRong-En Fan}</span> 5724*4a1a9510SRong-En Fan</pre> 5725*4a1a9510SRong-En Fan </div> 5726*4a1a9510SRong-En Fan 5727*4a1a9510SRong-En Fan <p>Play with the color pairs and try to understand the 5728*4a1a9510SRong-En Fan foreground and background attributes. In my programs 5729*4a1a9510SRong-En Fan using color attributes, I usually set only the background 5730*4a1a9510SRong-En Fan with set_field_back(). Curses simply doesn't allow 5731*4a1a9510SRong-En Fan defining individual color attributes.</p> 5732*4a1a9510SRong-En Fan </div> 5733*4a1a9510SRong-En Fan 5734*4a1a9510SRong-En Fan <div class="SECT3"> 5735*4a1a9510SRong-En Fan <hr> 5736*4a1a9510SRong-En Fan 5737*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="FIELDOPTIONBITS" id= 5738*4a1a9510SRong-En Fan "FIELDOPTIONBITS">18.3.5. Field Option Bits</a></h4> 5739*4a1a9510SRong-En Fan 5740*4a1a9510SRong-En Fan <p>There is also a large collection of field option bits 5741*4a1a9510SRong-En Fan you can set to control various aspects of forms 5742*4a1a9510SRong-En Fan processing. You can manipulate them with these 5743*4a1a9510SRong-En Fan functions:</p> 5744*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5745*4a1a9510SRong-En Fanint set_field_opts(FIELD *field, /* field to alter */ 5746*4a1a9510SRong-En Fan int attr); /* attribute to set */ 5747*4a1a9510SRong-En Fan 5748*4a1a9510SRong-En Fanint field_opts_on(FIELD *field, /* field to alter */ 5749*4a1a9510SRong-En Fan int attr); /* attributes to turn on */ 5750*4a1a9510SRong-En Fan 5751*4a1a9510SRong-En Fanint field_opts_off(FIELD *field, /* field to alter */ 5752*4a1a9510SRong-En Fan int attr); /* attributes to turn off */ 5753*4a1a9510SRong-En Fan 5754*4a1a9510SRong-En Fanint field_opts(FIELD *field); /* field to query */ 5755*4a1a9510SRong-En Fan</pre> 5756*4a1a9510SRong-En Fan 5757*4a1a9510SRong-En Fan <p>The function set_field_opts() can be used to directly 5758*4a1a9510SRong-En Fan set attributes of a field or you can choose to switch a 5759*4a1a9510SRong-En Fan few attributes on and off with field_opts_on() and 5760*4a1a9510SRong-En Fan field_opts_off() selectively. Anytime you can query the 5761*4a1a9510SRong-En Fan attributes of a field with field_opts(). The following is 5762*4a1a9510SRong-En Fan the list of available options. By default, all options 5763*4a1a9510SRong-En Fan are on.</p> 5764*4a1a9510SRong-En Fan 5765*4a1a9510SRong-En Fan <div class="VARIABLELIST"> 5766*4a1a9510SRong-En Fan <dl> 5767*4a1a9510SRong-En Fan <dt>O_VISIBLE</dt> 5768*4a1a9510SRong-En Fan 5769*4a1a9510SRong-En Fan <dd> 5770*4a1a9510SRong-En Fan <p>Controls whether the field is visible on the 5771*4a1a9510SRong-En Fan screen. Can be used during form processing to hide 5772*4a1a9510SRong-En Fan or pop up fields depending on the value of parent 5773*4a1a9510SRong-En Fan fields.</p> 5774*4a1a9510SRong-En Fan </dd> 5775*4a1a9510SRong-En Fan 5776*4a1a9510SRong-En Fan <dt>O_ACTIVE</dt> 5777*4a1a9510SRong-En Fan 5778*4a1a9510SRong-En Fan <dd> 5779*4a1a9510SRong-En Fan <p>Controls whether the field is active during 5780*4a1a9510SRong-En Fan forms processing (i.e. visited by form navigation 5781*4a1a9510SRong-En Fan keys). Can be used to make labels or derived fields 5782*4a1a9510SRong-En Fan with buffer values alterable by the forms 5783*4a1a9510SRong-En Fan application, not the user.</p> 5784*4a1a9510SRong-En Fan </dd> 5785*4a1a9510SRong-En Fan 5786*4a1a9510SRong-En Fan <dt>O_PUBLIC</dt> 5787*4a1a9510SRong-En Fan 5788*4a1a9510SRong-En Fan <dd> 5789*4a1a9510SRong-En Fan <p>Controls whether data is displayed during field 5790*4a1a9510SRong-En Fan entry. If this option is turned off on a field, the 5791*4a1a9510SRong-En Fan library will accept and edit data in that field, 5792*4a1a9510SRong-En Fan but it will not be displayed and the visible field 5793*4a1a9510SRong-En Fan cursor will not move. You can turn off the O_PUBLIC 5794*4a1a9510SRong-En Fan bit to define password fields.</p> 5795*4a1a9510SRong-En Fan </dd> 5796*4a1a9510SRong-En Fan 5797*4a1a9510SRong-En Fan <dt>O_EDIT</dt> 5798*4a1a9510SRong-En Fan 5799*4a1a9510SRong-En Fan <dd> 5800*4a1a9510SRong-En Fan <p>Controls whether the field's data can be 5801*4a1a9510SRong-En Fan modified. When this option is off, all editing 5802*4a1a9510SRong-En Fan requests except <tt class= 5803*4a1a9510SRong-En Fan "LITERAL">REQ_PREV_CHOICE</tt> and <tt class= 5804*4a1a9510SRong-En Fan "LITERAL">REQ_NEXT_CHOICE</tt>will fail. Such 5805*4a1a9510SRong-En Fan read-only fields may be useful for help 5806*4a1a9510SRong-En Fan messages.</p> 5807*4a1a9510SRong-En Fan </dd> 5808*4a1a9510SRong-En Fan 5809*4a1a9510SRong-En Fan <dt>O_WRAP</dt> 5810*4a1a9510SRong-En Fan 5811*4a1a9510SRong-En Fan <dd> 5812*4a1a9510SRong-En Fan <p>Controls word-wrapping in multi-line fields. 5813*4a1a9510SRong-En Fan Normally, when any character of a (blank-separated) 5814*4a1a9510SRong-En Fan word reaches the end of the current line, the 5815*4a1a9510SRong-En Fan entire word is wrapped to the next line (assuming 5816*4a1a9510SRong-En Fan there is one). When this option is off, the word 5817*4a1a9510SRong-En Fan will be split across the line break.</p> 5818*4a1a9510SRong-En Fan </dd> 5819*4a1a9510SRong-En Fan 5820*4a1a9510SRong-En Fan <dt>O_BLANK</dt> 5821*4a1a9510SRong-En Fan 5822*4a1a9510SRong-En Fan <dd> 5823*4a1a9510SRong-En Fan <p>Controls field blanking. When this option is on, 5824*4a1a9510SRong-En Fan entering a character at the first field position 5825*4a1a9510SRong-En Fan erases the entire field (except for the 5826*4a1a9510SRong-En Fan just-entered character).</p> 5827*4a1a9510SRong-En Fan </dd> 5828*4a1a9510SRong-En Fan 5829*4a1a9510SRong-En Fan <dt>O_AUTOSKIP</dt> 5830*4a1a9510SRong-En Fan 5831*4a1a9510SRong-En Fan <dd> 5832*4a1a9510SRong-En Fan <p>Controls automatic skip to next field when this 5833*4a1a9510SRong-En Fan one fills. Normally, when the forms user tries to 5834*4a1a9510SRong-En Fan type more data into a field than will fit, the 5835*4a1a9510SRong-En Fan editing location jumps to next field. When this 5836*4a1a9510SRong-En Fan option is off, the user's cursor will hang at the 5837*4a1a9510SRong-En Fan end of the field. This option is ignored in dynamic 5838*4a1a9510SRong-En Fan fields that have not reached their size limit.</p> 5839*4a1a9510SRong-En Fan </dd> 5840*4a1a9510SRong-En Fan 5841*4a1a9510SRong-En Fan <dt>O_NULLOK</dt> 5842*4a1a9510SRong-En Fan 5843*4a1a9510SRong-En Fan <dd> 5844*4a1a9510SRong-En Fan <p>Controls whether validation is applied to blank 5845*4a1a9510SRong-En Fan fields. Normally, it is not; the user can leave a 5846*4a1a9510SRong-En Fan field blank without invoking the usual validation 5847*4a1a9510SRong-En Fan check on exit. If this option is off on a field, 5848*4a1a9510SRong-En Fan exit from it will invoke a validation check.</p> 5849*4a1a9510SRong-En Fan </dd> 5850*4a1a9510SRong-En Fan 5851*4a1a9510SRong-En Fan <dt>O_PASSOK</dt> 5852*4a1a9510SRong-En Fan 5853*4a1a9510SRong-En Fan <dd> 5854*4a1a9510SRong-En Fan <p>Controls whether validation occurs on every 5855*4a1a9510SRong-En Fan exit, or only after the field is modified. Normally 5856*4a1a9510SRong-En Fan the latter is true. Setting O_PASSOK may be useful 5857*4a1a9510SRong-En Fan if your field's validation function may change 5858*4a1a9510SRong-En Fan during forms processing.</p> 5859*4a1a9510SRong-En Fan </dd> 5860*4a1a9510SRong-En Fan 5861*4a1a9510SRong-En Fan <dt>O_STATIC</dt> 5862*4a1a9510SRong-En Fan 5863*4a1a9510SRong-En Fan <dd> 5864*4a1a9510SRong-En Fan <p>Controls whether the field is fixed to its 5865*4a1a9510SRong-En Fan initial dimensions. If you turn this off, the field 5866*4a1a9510SRong-En Fan becomes dynamic and will stretch to fit entered 5867*4a1a9510SRong-En Fan data.</p> 5868*4a1a9510SRong-En Fan </dd> 5869*4a1a9510SRong-En Fan </dl> 5870*4a1a9510SRong-En Fan </div> 5871*4a1a9510SRong-En Fan 5872*4a1a9510SRong-En Fan <p>A field's options cannot be changed while the field is 5873*4a1a9510SRong-En Fan currently selected. However, options may be changed on 5874*4a1a9510SRong-En Fan posted fields that are not current.</p> 5875*4a1a9510SRong-En Fan 5876*4a1a9510SRong-En Fan <p>The option values are bit-masks and can be composed 5877*4a1a9510SRong-En Fan with logical-or in the obvious way. You have seen the 5878*4a1a9510SRong-En Fan usage of switching off O_AUTOSKIP option. The following 5879*4a1a9510SRong-En Fan example clarifies usage of some more options. Other 5880*4a1a9510SRong-En Fan options are explained where appropriate.</p> 5881*4a1a9510SRong-En Fan 5882*4a1a9510SRong-En Fan <div class="EXAMPLE"> 5883*4a1a9510SRong-En Fan <a name="FFOOP" id="FFOOP"></a> 5884*4a1a9510SRong-En Fan 5885*4a1a9510SRong-En Fan <p><b>Example 27. Field Options Usage example</b></p> 5886*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5887*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <form.h> 5888*4a1a9510SRong-En Fan 5889*4a1a9510SRong-En Fan#define STARTX 15 5890*4a1a9510SRong-En Fan#define STARTY 4 5891*4a1a9510SRong-En Fan#define WIDTH 25 5892*4a1a9510SRong-En Fan 5893*4a1a9510SRong-En Fan#define N_FIELDS 3 5894*4a1a9510SRong-En Fan 5895*4a1a9510SRong-En Fanint main() 5896*4a1a9510SRong-En Fan{ FIELD *field[N_FIELDS]; 5897*4a1a9510SRong-En Fan FORM *my_form; 5898*4a1a9510SRong-En Fan int ch, i; 5899*4a1a9510SRong-En Fan 5900*4a1a9510SRong-En Fan /* Initialize curses */ 5901*4a1a9510SRong-En Fan initscr(); 5902*4a1a9510SRong-En Fan cbreak(); 5903*4a1a9510SRong-En Fan noecho(); 5904*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 5905*4a1a9510SRong-En Fan 5906*4a1a9510SRong-En Fan /* Initialize the fields */ 5907*4a1a9510SRong-En Fan for(i = 0; i < N_FIELDS - 1; ++i) 5908*4a1a9510SRong-En Fan field[i] = new_field(1, WIDTH, STARTY + i * 2, STARTX, 0, 0); 5909*4a1a9510SRong-En Fan field[N_FIELDS - 1] = NULL; 5910*4a1a9510SRong-En Fan 5911*4a1a9510SRong-En Fan /* Set field options */ 5912*4a1a9510SRong-En Fan set_field_back(field[1], A_UNDERLINE); /* Print a line for the option */ 5913*4a1a9510SRong-En Fan 5914*4a1a9510SRong-En Fan field_opts_off(field[0], O_ACTIVE); /* This field is a static label */ 5915*4a1a9510SRong-En Fan field_opts_off(field[1], O_PUBLIC); /* This filed is like a password field*/ 5916*4a1a9510SRong-En Fan field_opts_off(field[1], O_AUTOSKIP); /* To avoid entering the same field */ 5917*4a1a9510SRong-En Fan /* after last character is entered */ 5918*4a1a9510SRong-En Fan 5919*4a1a9510SRong-En Fan /* Create the form and post it */ 5920*4a1a9510SRong-En Fan my_form = new_form(field); 5921*4a1a9510SRong-En Fan post_form(my_form); 5922*4a1a9510SRong-En Fan refresh(); 5923*4a1a9510SRong-En Fan 5924*4a1a9510SRong-En Fan set_field_just(field[0], JUSTIFY_CENTER); /* Center Justification */ 5925*4a1a9510SRong-En Fan set_field_buffer(field[0], 0, "This is a static Field"); 5926*4a1a9510SRong-En Fan /* Initialize the field */ 5927*4a1a9510SRong-En Fan mvprintw(STARTY, STARTX - 10, "Field 1:"); 5928*4a1a9510SRong-En Fan mvprintw(STARTY + 2, STARTX - 10, "Field 2:"); 5929*4a1a9510SRong-En Fan refresh(); 5930*4a1a9510SRong-En Fan 5931*4a1a9510SRong-En Fan /* Loop through to get user requests */ 5932*4a1a9510SRong-En Fan while((ch = getch()) != KEY_F(1)) 5933*4a1a9510SRong-En Fan { switch(ch) 5934*4a1a9510SRong-En Fan { case KEY_DOWN: 5935*4a1a9510SRong-En Fan /* Go to next field */ 5936*4a1a9510SRong-En Fan form_driver(my_form, REQ_NEXT_FIELD); 5937*4a1a9510SRong-En Fan /* Go to the end of the present buffer */ 5938*4a1a9510SRong-En Fan /* Leaves nicely at the last character */ 5939*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5940*4a1a9510SRong-En Fan break; 5941*4a1a9510SRong-En Fan case KEY_UP: 5942*4a1a9510SRong-En Fan /* Go to previous field */ 5943*4a1a9510SRong-En Fan form_driver(my_form, REQ_PREV_FIELD); 5944*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 5945*4a1a9510SRong-En Fan break; 5946*4a1a9510SRong-En Fan default: 5947*4a1a9510SRong-En Fan /* If this is a normal character, it gets */ 5948*4a1a9510SRong-En Fan /* Printed */ 5949*4a1a9510SRong-En Fan form_driver(my_form, ch); 5950*4a1a9510SRong-En Fan break; 5951*4a1a9510SRong-En Fan } 5952*4a1a9510SRong-En Fan } 5953*4a1a9510SRong-En Fan 5954*4a1a9510SRong-En Fan /* Un post form and free the memory */ 5955*4a1a9510SRong-En Fan unpost_form(my_form); 5956*4a1a9510SRong-En Fan free_form(my_form); 5957*4a1a9510SRong-En Fan free_field(field[0]); 5958*4a1a9510SRong-En Fan free_field(field[1]); 5959*4a1a9510SRong-En Fan 5960*4a1a9510SRong-En Fan endwin(); 5961*4a1a9510SRong-En Fan return 0; 5962*4a1a9510SRong-En Fan}</span> 5963*4a1a9510SRong-En Fan</pre> 5964*4a1a9510SRong-En Fan </div> 5965*4a1a9510SRong-En Fan 5966*4a1a9510SRong-En Fan <p>This example, though useless, shows the usage of 5967*4a1a9510SRong-En Fan options. If used properly, they can present information 5968*4a1a9510SRong-En Fan very effectively in a form. The second field being not 5969*4a1a9510SRong-En Fan O_PUBLIC, does not show the characters you are 5970*4a1a9510SRong-En Fan typing.</p> 5971*4a1a9510SRong-En Fan </div> 5972*4a1a9510SRong-En Fan 5973*4a1a9510SRong-En Fan <div class="SECT3"> 5974*4a1a9510SRong-En Fan <hr> 5975*4a1a9510SRong-En Fan 5976*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="FIELDSTATUS" id= 5977*4a1a9510SRong-En Fan "FIELDSTATUS">18.3.6. Field Status</a></h4> 5978*4a1a9510SRong-En Fan 5979*4a1a9510SRong-En Fan <p>The field status specifies whether the field has got 5980*4a1a9510SRong-En Fan edited or not. It is initially set to FALSE and when user 5981*4a1a9510SRong-En Fan enters something and the data buffer gets modified it 5982*4a1a9510SRong-En Fan becomes TRUE. So a field's status can be queried to find 5983*4a1a9510SRong-En Fan out whether it has been modified or not. The following 5984*4a1a9510SRong-En Fan functions can assist in those operations.</p> 5985*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 5986*4a1a9510SRong-En Fanint set_field_status(FIELD *field, /* field to alter */ 5987*4a1a9510SRong-En Fan int status); /* status to set */ 5988*4a1a9510SRong-En Fan 5989*4a1a9510SRong-En Fanint field_status(FIELD *field); /* fetch status of field */ 5990*4a1a9510SRong-En Fan</pre> 5991*4a1a9510SRong-En Fan 5992*4a1a9510SRong-En Fan <p>It's better to check the field's status only after 5993*4a1a9510SRong-En Fan after leaving the field, as data buffer might not have 5994*4a1a9510SRong-En Fan been updated yet as the validation is still due. To 5995*4a1a9510SRong-En Fan guarantee that right status is returned, call 5996*4a1a9510SRong-En Fan field_status() either (1) in the field's exit validation 5997*4a1a9510SRong-En Fan check routine, (2) from the field's or form's 5998*4a1a9510SRong-En Fan initialization or termination hooks, or (3) just after a 5999*4a1a9510SRong-En Fan REQ_VALIDATION request has been processed by the forms 6000*4a1a9510SRong-En Fan driver</p> 6001*4a1a9510SRong-En Fan </div> 6002*4a1a9510SRong-En Fan 6003*4a1a9510SRong-En Fan <div class="SECT3"> 6004*4a1a9510SRong-En Fan <hr> 6005*4a1a9510SRong-En Fan 6006*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="FIELDUSERPTR" id= 6007*4a1a9510SRong-En Fan "FIELDUSERPTR">18.3.7. Field User Pointer</a></h4> 6008*4a1a9510SRong-En Fan 6009*4a1a9510SRong-En Fan <p>Every field structure contains one pointer that can be 6010*4a1a9510SRong-En Fan used by the user for various purposes. It is not touched 6011*4a1a9510SRong-En Fan by forms library and can be used for any purpose by the 6012*4a1a9510SRong-En Fan user. The following functions set and fetch user 6013*4a1a9510SRong-En Fan pointer.</p> 6014*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6015*4a1a9510SRong-En Fanint set_field_userptr(FIELD *field, 6016*4a1a9510SRong-En Fan char *userptr); /* the user pointer you wish to associate */ 6017*4a1a9510SRong-En Fan /* with the field */ 6018*4a1a9510SRong-En Fan 6019*4a1a9510SRong-En Fanchar *field_userptr(FIELD *field); /* fetch user pointer of the field */ 6020*4a1a9510SRong-En Fan</pre> 6021*4a1a9510SRong-En Fan </div> 6022*4a1a9510SRong-En Fan 6023*4a1a9510SRong-En Fan <div class="SECT3"> 6024*4a1a9510SRong-En Fan <hr> 6025*4a1a9510SRong-En Fan 6026*4a1a9510SRong-En Fan <h4 class="SECT3"><a name="VARIABLESIZEFIELDS" id= 6027*4a1a9510SRong-En Fan "VARIABLESIZEFIELDS">18.3.8. Variable-Sized 6028*4a1a9510SRong-En Fan Fields</a></h4> 6029*4a1a9510SRong-En Fan 6030*4a1a9510SRong-En Fan <p>If you want a dynamically changing field with variable 6031*4a1a9510SRong-En Fan width, this is the feature you want to put to full use. 6032*4a1a9510SRong-En Fan This will allow the user to enter more data than the 6033*4a1a9510SRong-En Fan original size of the field and let the field grow. 6034*4a1a9510SRong-En Fan According to the field orientation it will scroll 6035*4a1a9510SRong-En Fan horizontally or vertically to incorporate the new 6036*4a1a9510SRong-En Fan data.</p> 6037*4a1a9510SRong-En Fan 6038*4a1a9510SRong-En Fan <p>To make a field dynamically growable, the option 6039*4a1a9510SRong-En Fan O_STATIC should be turned off. This can be done with 6040*4a1a9510SRong-En Fan a</p> 6041*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6042*4a1a9510SRong-En Fan field_opts_off(field_pointer, O_STATIC); 6043*4a1a9510SRong-En Fan</pre> 6044*4a1a9510SRong-En Fan 6045*4a1a9510SRong-En Fan <p>But it's usually not advisable to allow a field to 6046*4a1a9510SRong-En Fan grow infinitely. You can set a maximum limit to the 6047*4a1a9510SRong-En Fan growth of the field with</p> 6048*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6049*4a1a9510SRong-En Fanint set_max_field(FIELD *field, /* Field on which to operate */ 6050*4a1a9510SRong-En Fan int max_growth); /* maximum growth allowed for the field */ 6051*4a1a9510SRong-En Fan</pre> 6052*4a1a9510SRong-En Fan 6053*4a1a9510SRong-En Fan <p>The field info for a dynamically growable field can be 6054*4a1a9510SRong-En Fan retrieved by</p> 6055*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6056*4a1a9510SRong-En Fanint dynamic_field_info( FIELD *field, /* Field on which to operate */ 6057*4a1a9510SRong-En Fan int *prows, /* number of rows will be filled in this */ 6058*4a1a9510SRong-En Fan int *pcols, /* number of columns will be filled in this*/ 6059*4a1a9510SRong-En Fan int *pmax) /* maximum allowable growth will be filled */ 6060*4a1a9510SRong-En Fan /* in this */ 6061*4a1a9510SRong-En Fan</pre>Though field_info work as usual, it is advisable to use this 6062*4a1a9510SRong-En Fanfunction to get the proper attributes of a dynamically growable 6063*4a1a9510SRong-En Fanfield. 6064*4a1a9510SRong-En Fan 6065*4a1a9510SRong-En Fan <p>Recall the library routine new_field; a new field 6066*4a1a9510SRong-En Fan created with height set to one will be defined to be a 6067*4a1a9510SRong-En Fan one line field. A new field created with height greater 6068*4a1a9510SRong-En Fan than one will be defined to be a multi line field.</p> 6069*4a1a9510SRong-En Fan 6070*4a1a9510SRong-En Fan <p>A one line field with O_STATIC turned off (dynamically 6071*4a1a9510SRong-En Fan growable field) will contain a single fixed row, but the 6072*4a1a9510SRong-En Fan number of columns can increase if the user enters more 6073*4a1a9510SRong-En Fan data than the initial field will hold. The number of 6074*4a1a9510SRong-En Fan columns displayed will remain fixed and the additional 6075*4a1a9510SRong-En Fan data will scroll horizontally.</p> 6076*4a1a9510SRong-En Fan 6077*4a1a9510SRong-En Fan <p>A multi line field with O_STATIC turned off 6078*4a1a9510SRong-En Fan (dynamically growable field) will contain a fixed number 6079*4a1a9510SRong-En Fan of columns, but the number of rows can increase if the 6080*4a1a9510SRong-En Fan user enters more data than the initial field will hold. 6081*4a1a9510SRong-En Fan The number of rows displayed will remain fixed and the 6082*4a1a9510SRong-En Fan additional data will scroll vertically.</p> 6083*4a1a9510SRong-En Fan 6084*4a1a9510SRong-En Fan <p>The above two paragraphs pretty much describe a 6085*4a1a9510SRong-En Fan dynamically growable field's behavior. The way other 6086*4a1a9510SRong-En Fan parts of forms library behaves is described below:</p> 6087*4a1a9510SRong-En Fan 6088*4a1a9510SRong-En Fan <ol type="1"> 6089*4a1a9510SRong-En Fan <li> 6090*4a1a9510SRong-En Fan <p>The field option O_AUTOSKIP will be ignored if the 6091*4a1a9510SRong-En Fan option O_STATIC is off and there is no maximum growth 6092*4a1a9510SRong-En Fan specified for the field. Currently, O_AUTOSKIP 6093*4a1a9510SRong-En Fan generates an automatic REQ_NEXT_FIELD form driver 6094*4a1a9510SRong-En Fan request when the user types in the last character 6095*4a1a9510SRong-En Fan position of a field. On a growable field with no 6096*4a1a9510SRong-En Fan maximum growth specified, there is no last character 6097*4a1a9510SRong-En Fan position. If a maximum growth is specified, the 6098*4a1a9510SRong-En Fan O_AUTOSKIP option will work as normal if the field 6099*4a1a9510SRong-En Fan has grown to its maximum size.</p> 6100*4a1a9510SRong-En Fan </li> 6101*4a1a9510SRong-En Fan 6102*4a1a9510SRong-En Fan <li> 6103*4a1a9510SRong-En Fan <p>The field justification will be ignored if the 6104*4a1a9510SRong-En Fan option O_STATIC is off. Currently, set_field_just can 6105*4a1a9510SRong-En Fan be used to JUSTIFY_LEFT, JUSTIFY_RIGHT, 6106*4a1a9510SRong-En Fan JUSTIFY_CENTER the contents of a one line field. A 6107*4a1a9510SRong-En Fan growable one line field will, by definition, grow and 6108*4a1a9510SRong-En Fan scroll horizontally and may contain more data than 6109*4a1a9510SRong-En Fan can be justified. The return from field_just will be 6110*4a1a9510SRong-En Fan unchanged.</p> 6111*4a1a9510SRong-En Fan </li> 6112*4a1a9510SRong-En Fan 6113*4a1a9510SRong-En Fan <li> 6114*4a1a9510SRong-En Fan <p>The overloaded form driver request REQ_NEW_LINE 6115*4a1a9510SRong-En Fan will operate the same way regardless of the 6116*4a1a9510SRong-En Fan O_NL_OVERLOAD form option if the field option 6117*4a1a9510SRong-En Fan O_STATIC is off and there is no maximum growth 6118*4a1a9510SRong-En Fan specified for the field. Currently, if the form 6119*4a1a9510SRong-En Fan option O_NL_OVERLOAD is on, REQ_NEW_LINE implicitly 6120*4a1a9510SRong-En Fan generates a REQ_NEXT_FIELD if called from the last 6121*4a1a9510SRong-En Fan line of a field. If a field can grow without bound, 6122*4a1a9510SRong-En Fan there is no last line, so REQ_NEW_LINE will never 6123*4a1a9510SRong-En Fan implicitly generate a REQ_NEXT_FIELD. If a maximum 6124*4a1a9510SRong-En Fan growth limit is specified and the O_NL_OVERLOAD form 6125*4a1a9510SRong-En Fan option is on, REQ_NEW_LINE will only implicitly 6126*4a1a9510SRong-En Fan generate REQ_NEXT_FIELD if the field has grown to its 6127*4a1a9510SRong-En Fan maximum size and the user is on the last line.</p> 6128*4a1a9510SRong-En Fan </li> 6129*4a1a9510SRong-En Fan 6130*4a1a9510SRong-En Fan <li> 6131*4a1a9510SRong-En Fan <p>The library call dup_field will work as usual; it 6132*4a1a9510SRong-En Fan will duplicate the field, including the current 6133*4a1a9510SRong-En Fan buffer size and contents of the field being 6134*4a1a9510SRong-En Fan duplicated. Any specified maximum growth will also be 6135*4a1a9510SRong-En Fan duplicated.</p> 6136*4a1a9510SRong-En Fan </li> 6137*4a1a9510SRong-En Fan 6138*4a1a9510SRong-En Fan <li> 6139*4a1a9510SRong-En Fan <p>The library call link_field will work as usual; it 6140*4a1a9510SRong-En Fan will duplicate all field attributes and share buffers 6141*4a1a9510SRong-En Fan with the field being linked. If the O_STATIC field 6142*4a1a9510SRong-En Fan option is subsequently changed by a field sharing 6143*4a1a9510SRong-En Fan buffers, how the system reacts to an attempt to enter 6144*4a1a9510SRong-En Fan more data into the field than the buffer will 6145*4a1a9510SRong-En Fan currently hold will depend on the setting of the 6146*4a1a9510SRong-En Fan option in the current field.</p> 6147*4a1a9510SRong-En Fan </li> 6148*4a1a9510SRong-En Fan 6149*4a1a9510SRong-En Fan <li> 6150*4a1a9510SRong-En Fan <p>The library call field_info will work as usual; 6151*4a1a9510SRong-En Fan the variable nrow will contain the value of the 6152*4a1a9510SRong-En Fan original call to new_field. The user should use 6153*4a1a9510SRong-En Fan dynamic_field_info, described above, to query the 6154*4a1a9510SRong-En Fan current size of the buffer.</p> 6155*4a1a9510SRong-En Fan </li> 6156*4a1a9510SRong-En Fan </ol> 6157*4a1a9510SRong-En Fan 6158*4a1a9510SRong-En Fan <p>Some of the above points make sense only after 6159*4a1a9510SRong-En Fan explaining form driver. We will be looking into that in 6160*4a1a9510SRong-En Fan next few sections.</p> 6161*4a1a9510SRong-En Fan </div> 6162*4a1a9510SRong-En Fan </div> 6163*4a1a9510SRong-En Fan 6164*4a1a9510SRong-En Fan <div class="SECT2"> 6165*4a1a9510SRong-En Fan <hr> 6166*4a1a9510SRong-En Fan 6167*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="FORMWINDOWS" id= 6168*4a1a9510SRong-En Fan "FORMWINDOWS">18.4. Form Windows</a></h3> 6169*4a1a9510SRong-En Fan 6170*4a1a9510SRong-En Fan <p>The form windows concept is pretty much similar to menu 6171*4a1a9510SRong-En Fan windows. Every form is associated with a main window and a 6172*4a1a9510SRong-En Fan sub window. The form main window displays any title or 6173*4a1a9510SRong-En Fan border associated or whatever the user wishes. Then the sub 6174*4a1a9510SRong-En Fan window contains all the fields and displays them according 6175*4a1a9510SRong-En Fan to their position. This gives the flexibility of 6176*4a1a9510SRong-En Fan manipulating fancy form displaying very easily.</p> 6177*4a1a9510SRong-En Fan 6178*4a1a9510SRong-En Fan <p>Since this is pretty much similar to menu windows, I am 6179*4a1a9510SRong-En Fan providing an example with out much explanation. The 6180*4a1a9510SRong-En Fan functions are similar and they work the same way.</p> 6181*4a1a9510SRong-En Fan 6182*4a1a9510SRong-En Fan <div class="EXAMPLE"> 6183*4a1a9510SRong-En Fan <a name="FFOWI" id="FFOWI"></a> 6184*4a1a9510SRong-En Fan 6185*4a1a9510SRong-En Fan <p><b>Example 28. Form Windows Example</b></p> 6186*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6187*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include <form.h> 6188*4a1a9510SRong-En Fan 6189*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 6190*4a1a9510SRong-En Fan 6191*4a1a9510SRong-En Fanint main() 6192*4a1a9510SRong-En Fan{ 6193*4a1a9510SRong-En Fan FIELD *field[3]; 6194*4a1a9510SRong-En Fan FORM *my_form; 6195*4a1a9510SRong-En Fan WINDOW *my_form_win; 6196*4a1a9510SRong-En Fan int ch, rows, cols; 6197*4a1a9510SRong-En Fan 6198*4a1a9510SRong-En Fan /* Initialize curses */ 6199*4a1a9510SRong-En Fan initscr(); 6200*4a1a9510SRong-En Fan start_color(); 6201*4a1a9510SRong-En Fan cbreak(); 6202*4a1a9510SRong-En Fan noecho(); 6203*4a1a9510SRong-En Fan keypad(stdscr, TRUE); 6204*4a1a9510SRong-En Fan 6205*4a1a9510SRong-En Fan /* Initialize few color pairs */ 6206*4a1a9510SRong-En Fan init_pair(1, COLOR_RED, COLOR_BLACK); 6207*4a1a9510SRong-En Fan 6208*4a1a9510SRong-En Fan /* Initialize the fields */ 6209*4a1a9510SRong-En Fan field[0] = new_field(1, 10, 6, 1, 0, 0); 6210*4a1a9510SRong-En Fan field[1] = new_field(1, 10, 8, 1, 0, 0); 6211*4a1a9510SRong-En Fan field[2] = NULL; 6212*4a1a9510SRong-En Fan 6213*4a1a9510SRong-En Fan /* Set field options */ 6214*4a1a9510SRong-En Fan set_field_back(field[0], A_UNDERLINE); 6215*4a1a9510SRong-En Fan field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 6216*4a1a9510SRong-En Fan /* Field is filled up */ 6217*4a1a9510SRong-En Fan set_field_back(field[1], A_UNDERLINE); 6218*4a1a9510SRong-En Fan field_opts_off(field[1], O_AUTOSKIP); 6219*4a1a9510SRong-En Fan 6220*4a1a9510SRong-En Fan /* Create the form and post it */ 6221*4a1a9510SRong-En Fan my_form = new_form(field); 6222*4a1a9510SRong-En Fan 6223*4a1a9510SRong-En Fan /* Calculate the area required for the form */ 6224*4a1a9510SRong-En Fan scale_form(my_form, &rows, &cols); 6225*4a1a9510SRong-En Fan 6226*4a1a9510SRong-En Fan /* Create the window to be associated with the form */ 6227*4a1a9510SRong-En Fan my_form_win = newwin(rows + 4, cols + 4, 4, 4); 6228*4a1a9510SRong-En Fan keypad(my_form_win, TRUE); 6229*4a1a9510SRong-En Fan 6230*4a1a9510SRong-En Fan /* Set main window and sub window */ 6231*4a1a9510SRong-En Fan set_form_win(my_form, my_form_win); 6232*4a1a9510SRong-En Fan set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2)); 6233*4a1a9510SRong-En Fan 6234*4a1a9510SRong-En Fan /* Print a border around the main window and print a title */ 6235*4a1a9510SRong-En Fan box(my_form_win, 0, 0); 6236*4a1a9510SRong-En Fan print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1)); 6237*4a1a9510SRong-En Fan 6238*4a1a9510SRong-En Fan post_form(my_form); 6239*4a1a9510SRong-En Fan wrefresh(my_form_win); 6240*4a1a9510SRong-En Fan 6241*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields"); 6242*4a1a9510SRong-En Fan refresh(); 6243*4a1a9510SRong-En Fan 6244*4a1a9510SRong-En Fan /* Loop through to get user requests */ 6245*4a1a9510SRong-En Fan while((ch = wgetch(my_form_win)) != KEY_F(1)) 6246*4a1a9510SRong-En Fan { switch(ch) 6247*4a1a9510SRong-En Fan { case KEY_DOWN: 6248*4a1a9510SRong-En Fan /* Go to next field */ 6249*4a1a9510SRong-En Fan form_driver(my_form, REQ_NEXT_FIELD); 6250*4a1a9510SRong-En Fan /* Go to the end of the present buffer */ 6251*4a1a9510SRong-En Fan /* Leaves nicely at the last character */ 6252*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 6253*4a1a9510SRong-En Fan break; 6254*4a1a9510SRong-En Fan case KEY_UP: 6255*4a1a9510SRong-En Fan /* Go to previous field */ 6256*4a1a9510SRong-En Fan form_driver(my_form, REQ_PREV_FIELD); 6257*4a1a9510SRong-En Fan form_driver(my_form, REQ_END_LINE); 6258*4a1a9510SRong-En Fan break; 6259*4a1a9510SRong-En Fan default: 6260*4a1a9510SRong-En Fan /* If this is a normal character, it gets */ 6261*4a1a9510SRong-En Fan /* Printed */ 6262*4a1a9510SRong-En Fan form_driver(my_form, ch); 6263*4a1a9510SRong-En Fan break; 6264*4a1a9510SRong-En Fan } 6265*4a1a9510SRong-En Fan } 6266*4a1a9510SRong-En Fan 6267*4a1a9510SRong-En Fan /* Un post form and free the memory */ 6268*4a1a9510SRong-En Fan unpost_form(my_form); 6269*4a1a9510SRong-En Fan free_form(my_form); 6270*4a1a9510SRong-En Fan free_field(field[0]); 6271*4a1a9510SRong-En Fan free_field(field[1]); 6272*4a1a9510SRong-En Fan 6273*4a1a9510SRong-En Fan endwin(); 6274*4a1a9510SRong-En Fan return 0; 6275*4a1a9510SRong-En Fan} 6276*4a1a9510SRong-En Fan 6277*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 6278*4a1a9510SRong-En Fan{ int length, x, y; 6279*4a1a9510SRong-En Fan float temp; 6280*4a1a9510SRong-En Fan 6281*4a1a9510SRong-En Fan if(win == NULL) 6282*4a1a9510SRong-En Fan win = stdscr; 6283*4a1a9510SRong-En Fan getyx(win, y, x); 6284*4a1a9510SRong-En Fan if(startx != 0) 6285*4a1a9510SRong-En Fan x = startx; 6286*4a1a9510SRong-En Fan if(starty != 0) 6287*4a1a9510SRong-En Fan y = starty; 6288*4a1a9510SRong-En Fan if(width == 0) 6289*4a1a9510SRong-En Fan width = 80; 6290*4a1a9510SRong-En Fan 6291*4a1a9510SRong-En Fan length = strlen(string); 6292*4a1a9510SRong-En Fan temp = (width - length)/ 2; 6293*4a1a9510SRong-En Fan x = startx + (int)temp; 6294*4a1a9510SRong-En Fan wattron(win, color); 6295*4a1a9510SRong-En Fan mvwprintw(win, y, x, "%s", string); 6296*4a1a9510SRong-En Fan wattroff(win, color); 6297*4a1a9510SRong-En Fan refresh(); 6298*4a1a9510SRong-En Fan}</span> 6299*4a1a9510SRong-En Fan</pre> 6300*4a1a9510SRong-En Fan </div> 6301*4a1a9510SRong-En Fan </div> 6302*4a1a9510SRong-En Fan 6303*4a1a9510SRong-En Fan <div class="SECT2"> 6304*4a1a9510SRong-En Fan <hr> 6305*4a1a9510SRong-En Fan 6306*4a1a9510SRong-En Fan <h3 class="SECT2"><a name="FILEDVALIDATE" id= 6307*4a1a9510SRong-En Fan "FILEDVALIDATE">18.5. Field Validation</a></h3> 6308*4a1a9510SRong-En Fan 6309*4a1a9510SRong-En Fan <p>By default, a field will accept any data input by the 6310*4a1a9510SRong-En Fan user. It is possible to attach validation to the field. 6311*4a1a9510SRong-En Fan Then any attempt by the user to leave the field, while it 6312*4a1a9510SRong-En Fan contains data that doesn't match the validation type will 6313*4a1a9510SRong-En Fan fail. Some validation types also have a character-validity 6314*4a1a9510SRong-En Fan check for each time a character is entered in the 6315*4a1a9510SRong-En Fan field.</p> 6316*4a1a9510SRong-En Fan 6317*4a1a9510SRong-En Fan <p>Validation can be attached to a field with the following 6318*4a1a9510SRong-En Fan function.</p> 6319*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6320*4a1a9510SRong-En Fanint set_field_type(FIELD *field, /* field to alter */ 6321*4a1a9510SRong-En Fan FIELDTYPE *ftype, /* type to associate */ 6322*4a1a9510SRong-En Fan ...); /* additional arguments*/ 6323*4a1a9510SRong-En Fan</pre>Once set, the validation type for a field can be queried with 6324*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6325*4a1a9510SRong-En FanFIELDTYPE *field_type(FIELD *field); /* field to query */ 6326*4a1a9510SRong-En Fan</pre> 6327*4a1a9510SRong-En Fan 6328*4a1a9510SRong-En Fan <p>The form driver validates the data in a field only when 6329*4a1a9510SRong-En Fan data is entered by the end-user. Validation does not occur 6330*4a1a9510SRong-En Fan when</p> 6331*4a1a9510SRong-En Fan 6332*4a1a9510SRong-En Fan <ul> 6333*4a1a9510SRong-En Fan <li> 6334*4a1a9510SRong-En Fan <p>the application program changes the field value by 6335*4a1a9510SRong-En Fan calling set_field_buffer.</p> 6336*4a1a9510SRong-En Fan </li> 6337*4a1a9510SRong-En Fan 6338*4a1a9510SRong-En Fan <li> 6339*4a1a9510SRong-En Fan <p>linked field values are changed indirectly -- by 6340*4a1a9510SRong-En Fan changing the field to which they are linked</p> 6341*4a1a9510SRong-En Fan </li> 6342*4a1a9510SRong-En Fan </ul> 6343*4a1a9510SRong-En Fan 6344*4a1a9510SRong-En Fan <p>The following are the pre-defined validation types. You 6345*4a1a9510SRong-En Fan can also specify custom validation, though it's a bit 6346*4a1a9510SRong-En Fan tricky and cumbersome.</p> 6347*4a1a9510SRong-En Fan 6348*4a1a9510SRong-En Fan <h1 class="BRIDGEHEAD"><a name="AEN1069" id= 6349*4a1a9510SRong-En Fan "AEN1069"></a>TYPE_ALPHA</h1> 6350*4a1a9510SRong-En Fan 6351*4a1a9510SRong-En Fan <p>This field type accepts alphabetic data; no blanks, no 6352*4a1a9510SRong-En Fan digits, no special characters (this is checked at 6353*4a1a9510SRong-En Fan character-entry time). It is set up with:</p> 6354*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6355*4a1a9510SRong-En Fanint set_field_type(FIELD *field, /* field to alter */ 6356*4a1a9510SRong-En Fan TYPE_ALPHA, /* type to associate */ 6357*4a1a9510SRong-En Fan int width); /* minimum width of field */ 6358*4a1a9510SRong-En Fan</pre> 6359*4a1a9510SRong-En Fan 6360*4a1a9510SRong-En Fan <p>The width argument sets a minimum width of data. The 6361*4a1a9510SRong-En Fan user has to enter at-least width number of characters 6362*4a1a9510SRong-En Fan before he can leave the field. Typically you'll want to set 6363*4a1a9510SRong-En Fan this to the field width; if it's greater than the field 6364*4a1a9510SRong-En Fan width, the validation check will always fail. A minimum 6365*4a1a9510SRong-En Fan width of zero makes field completion optional.</p> 6366*4a1a9510SRong-En Fan 6367*4a1a9510SRong-En Fan <h1 class="BRIDGEHEAD"><a name="AEN1073" id= 6368*4a1a9510SRong-En Fan "AEN1073"></a>TYPE_ALNUM</h1> 6369*4a1a9510SRong-En Fan 6370*4a1a9510SRong-En Fan <p>This field type accepts alphabetic data and digits; no 6371*4a1a9510SRong-En Fan blanks, no special characters (this is checked at 6372*4a1a9510SRong-En Fan character-entry time). It is set up with:</p> 6373*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6374*4a1a9510SRong-En Fanint set_field_type(FIELD *field, /* field to alter */ 6375*4a1a9510SRong-En Fan TYPE_ALNUM, /* type to associate */ 6376*4a1a9510SRong-En Fan int width); /* minimum width of field */ 6377*4a1a9510SRong-En Fan</pre> 6378*4a1a9510SRong-En Fan 6379*4a1a9510SRong-En Fan <p>The width argument sets a minimum width of data. As with 6380*4a1a9510SRong-En Fan TYPE_ALPHA, typically you'll want to set this to the field 6381*4a1a9510SRong-En Fan width; if it's greater than the field width, the validation 6382*4a1a9510SRong-En Fan check will always fail. A minimum width of zero makes field 6383*4a1a9510SRong-En Fan completion optional.</p> 6384*4a1a9510SRong-En Fan 6385*4a1a9510SRong-En Fan <h1 class="BRIDGEHEAD"><a name="AEN1077" id= 6386*4a1a9510SRong-En Fan "AEN1077"></a>TYPE_ENUM</h1> 6387*4a1a9510SRong-En Fan 6388*4a1a9510SRong-En Fan <p>This type allows you to restrict a field's values to be 6389*4a1a9510SRong-En Fan among a specified set of string values (for example, the 6390*4a1a9510SRong-En Fan two-letter postal codes for U.S. states). It is set up 6391*4a1a9510SRong-En Fan with:</p> 6392*4a1a9510SRong-En Fan <pre class="PROGRAMLISTING"> 6393*4a1a9510SRong-En Fanint set_field_type(FIELD *field, /* field to alter */ 6394*4a1a9510SRong-En Fan TYPE_ENUM, /* type to associate */ 6395*4a1a9510SRong-En Fan char **valuelist; /* list of possible values */ 6396*4a1a9510SRong-En Fan int checkcase; /* case-sensitive? */ 6397*4a1a9510SRong-En Fan int checkunique); /* must specify uniquely? */ 6398*4a1a9510SRong-En Fan</pre> 6399*4a1a9510SRong-En Fan 6400*4a1a9510SRong-En Fan <p>The valuelist parameter must point at a NULL-terminated 6401*4a1a9510SRong-En Fan list of valid strings. The checkcase argument, if true, 6402*4a1a9510SRong-En Fan makes comparison with the string case-sensitive.</p> 6403*4a1a9510SRong-En Fan 6404*4a1a9510SRong-En Fan <p>When the user exits a TYPE_ENUM field, the validation 6405*4a1a9510SRong-En Fan procedure tries to complete the data in the buffer to a 6406*4a1a9510SRong-En Fan valid entry. If a complete choice string has been entered, 6407*4a1a9510SRong-En Fan it is of course valid. But it is also possible to enter a 6408*4a1a9510SRong-En Fan prefix of a valid string and have it completed for you.</p> 6409*4a1a9510SRong-En Fan 6410*4a1a9510SRong-En Fan <p>By default, if you enter such a prefix and it matches 6411*4a1a9510SRong-En Fan more than one value in the string list, the prefix will be 6412*4a1a9510SRong-En Fan completed to the first matching value. But the checkunique 6413*4a1a9510SRong-En Fan argument, if true, requires prefix matches to be unique in 6414 order to be valid.</p> 6415 6416 <p>The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests 6417 can be particularly useful with these fields.</p> 6418 6419 <h1 class="BRIDGEHEAD"><a name="AEN1084" id= 6420 "AEN1084"></a>TYPE_INTEGER</h1> 6421 6422 <p>This field type accepts an integer. It is set up as 6423 follows:</p> 6424 <pre class="PROGRAMLISTING"> 6425int set_field_type(FIELD *field, /* field to alter */ 6426 TYPE_INTEGER, /* type to associate */ 6427 int padding, /* # places to zero-pad to */ 6428 int vmin, int vmax); /* valid range */ 6429</pre> 6430 6431 <p>Valid characters consist of an optional leading minus 6432 and digits. The range check is performed on exit. If the 6433 range maximum is less than or equal to the minimum, the 6434 range is ignored.</p> 6435 6436 <p>If the value passes its range check, it is padded with 6437 as many leading zero digits as necessary to meet the 6438 padding argument.</p> 6439 6440 <p>A TYPE_INTEGER value buffer can conveniently be 6441 interpreted with the C library function atoi(3).</p> 6442 6443 <h1 class="BRIDGEHEAD"><a name="AEN1090" id= 6444 "AEN1090"></a>TYPE_NUMERIC</h1> 6445 6446 <p>This field type accepts a decimal number. It is set up 6447 as follows:</p> 6448 <pre class="PROGRAMLISTING"> 6449int set_field_type(FIELD *field, /* field to alter */ 6450 TYPE_NUMERIC, /* type to associate */ 6451 int padding, /* # places of precision */ 6452 int vmin, int vmax); /* valid range */ 6453</pre> 6454 6455 <p>Valid characters consist of an optional leading minus 6456 and digits. possibly including a decimal point. The range 6457 check is performed on exit. If the range maximum is less 6458 than or equal to the minimum, the range is ignored.</p> 6459 6460 <p>If the value passes its range check, it is padded with 6461 as many trailing zero digits as necessary to meet the 6462 padding argument.</p> 6463 6464 <p>A TYPE_NUMERIC value buffer can conveniently be 6465 interpreted with the C library function atof(3).</p> 6466 6467 <h1 class="BRIDGEHEAD"><a name="AEN1096" id= 6468 "AEN1096"></a>TYPE_REGEXP</h1> 6469 6470 <p>This field type accepts data matching a regular 6471 expression. It is set up as follows:</p> 6472 <pre class="PROGRAMLISTING"> 6473int set_field_type(FIELD *field, /* field to alter */ 6474 TYPE_REGEXP, /* type to associate */ 6475 char *regexp); /* expression to match */ 6476</pre> 6477 6478 <p>The syntax for regular expressions is that of 6479 regcomp(3). The check for regular-expression match is 6480 performed on exit.</p> 6481 </div> 6482 6483 <div class="SECT2"> 6484 <hr> 6485 6486 <h3 class="SECT2"><a name="FORMDRIVER" id= 6487 "FORMDRIVER">18.6. Form Driver: The work horse of the forms 6488 system</a></h3> 6489 6490 <p>As in the menu system, form_driver() plays a very 6491 important role in forms system. All types of requests to 6492 forms system should be funneled through form_driver().</p> 6493 <pre class="PROGRAMLISTING"> 6494int form_driver(FORM *form, /* form on which to operate */ 6495 int request) /* form request code */ 6496</pre> 6497 6498 <p>As you have seen some of the examples above, you have to 6499 be in a loop looking for user input and then decide whether 6500 it's a field data or a form request. The form requests are 6501 then passed to form_driver() to do the work.</p> 6502 6503 <p>The requests roughly can be divided into following 6504 categories. Different requests and their usage is explained 6505 below:</p> 6506 6507 <div class="SECT3"> 6508 <hr> 6509 6510 <h4 class="SECT3"><a name="PAGENAVREQ" id= 6511 "PAGENAVREQ">18.6.1. Page Navigation Requests</a></h4> 6512 6513 <p>These requests cause page-level moves through the 6514 form, triggering display of a new form screen. A form can 6515 be made of multiple pages. If you have a big form with 6516 lot of fields and logical sections, then you can divide 6517 the form into pages. The function set_new_page() to set a 6518 new page at the field specified.</p> 6519 <pre class="PROGRAMLISTING"> 6520int set_new_page(FIELD *field,/* Field at which page break to be set or unset */ 6521 bool new_page_flag); /* should be TRUE to put a break */ 6522</pre> 6523 6524 <p>The following requests allow you to move to different 6525 pages</p> 6526 6527 <ul> 6528 <li> 6529 <p><span class="emphasis"><i class= 6530 "EMPHASIS">REQ_NEXT_PAGE</i></span> Move to the next 6531 form page.</p> 6532 </li> 6533 6534 <li> 6535 <p><span class="emphasis"><i class= 6536 "EMPHASIS">REQ_PREV_PAGE</i></span> Move to the 6537 previous form page.</p> 6538 </li> 6539 6540 <li> 6541 <p><span class="emphasis"><i class= 6542 "EMPHASIS">REQ_FIRST_PAGE</i></span> Move to the 6543 first form page.</p> 6544 </li> 6545 6546 <li> 6547 <p><span class="emphasis"><i class= 6548 "EMPHASIS">REQ_LAST_PAGE</i></span> Move to the last 6549 form page.</p> 6550 </li> 6551 </ul> 6552 6553 <p>These requests treat the list as cyclic; that is, 6554 REQ_NEXT_PAGE from the last page goes to the first, and 6555 REQ_PREV_PAGE from the first page goes to the last.</p> 6556 </div> 6557 6558 <div class="SECT3"> 6559 <hr> 6560 6561 <h4 class="SECT3"><a name="INTERFIELDNAVREQ" id= 6562 "INTERFIELDNAVREQ">18.6.2. Inter-Field Navigation 6563 Requests</a></h4> 6564 6565 <p>These requests handle navigation between fields on the 6566 same page.</p> 6567 6568 <ul> 6569 <li> 6570 <p><span class="emphasis"><i class= 6571 "EMPHASIS">REQ_NEXT_FIELD</i></span> Move to next 6572 field.</p> 6573 </li> 6574 6575 <li> 6576 <p><span class="emphasis"><i class= 6577 "EMPHASIS">REQ_PREV_FIELD</i></span> Move to previous 6578 field.</p> 6579 </li> 6580 6581 <li> 6582 <p><span class="emphasis"><i class= 6583 "EMPHASIS">REQ_FIRST_FIELD</i></span> Move to the 6584 first field.</p> 6585 </li> 6586 6587 <li> 6588 <p><span class="emphasis"><i class= 6589 "EMPHASIS">REQ_LAST_FIELD</i></span> Move to the last 6590 field.</p> 6591 </li> 6592 6593 <li> 6594 <p><span class="emphasis"><i class= 6595 "EMPHASIS">REQ_SNEXT_FIELD</i></span> Move to sorted 6596 next field.</p> 6597 </li> 6598 6599 <li> 6600 <p><span class="emphasis"><i class= 6601 "EMPHASIS">REQ_SPREV_FIELD</i></span> Move to sorted 6602 previous field.</p> 6603 </li> 6604 6605 <li> 6606 <p><span class="emphasis"><i class= 6607 "EMPHASIS">REQ_SFIRST_FIELD</i></span> Move to the 6608 sorted first field.</p> 6609 </li> 6610 6611 <li> 6612 <p><span class="emphasis"><i class= 6613 "EMPHASIS">REQ_SLAST_FIELD</i></span> Move to the 6614 sorted last field.</p> 6615 </li> 6616 6617 <li> 6618 <p><span class="emphasis"><i class= 6619 "EMPHASIS">REQ_LEFT_FIELD</i></span> Move left to 6620 field.</p> 6621 </li> 6622 6623 <li> 6624 <p><span class="emphasis"><i class= 6625 "EMPHASIS">REQ_RIGHT_FIELD</i></span> Move right to 6626 field.</p> 6627 </li> 6628 6629 <li> 6630 <p><span class="emphasis"><i class= 6631 "EMPHASIS">REQ_UP_FIELD</i></span> Move up to 6632 field.</p> 6633 </li> 6634 6635 <li> 6636 <p><span class="emphasis"><i class= 6637 "EMPHASIS">REQ_DOWN_FIELD</i></span> Move down to 6638 field.</p> 6639 </li> 6640 </ul> 6641 6642 <p>These requests treat the list of fields on a page as 6643 cyclic; that is, REQ_NEXT_FIELD from the last field goes 6644 to the first, and REQ_PREV_FIELD from the first field 6645 goes to the last. The order of the fields for these (and 6646 the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is 6647 simply the order of the field pointers in the form array 6648 (as set up by new_form() or set_form_fields()</p> 6649 6650 <p>It is also possible to traverse the fields as if they 6651 had been sorted in screen-position order, so the sequence 6652 goes left-to-right and top-to-bottom. To do this, use the 6653 second group of four sorted-movement requests.</p> 6654 6655 <p>Finally, it is possible to move between fields using 6656 visual directions up, down, right, and left. To 6657 accomplish this, use the third group of four requests. 6658 Note, however, that the position of a form for purposes 6659 of these requests is its upper-left corner.</p> 6660 6661 <p>For example, suppose you have a multi-line field B, 6662 and two single-line fields A and C on the same line with 6663 B, with A to the left of B and C to the right of B. A 6664 REQ_MOVE_RIGHT from A will go to B only if A, B, and C 6665 all share the same first line; otherwise it will skip 6666 over B to C.</p> 6667 </div> 6668 6669 <div class="SECT3"> 6670 <hr> 6671 6672 <h4 class="SECT3"><a name="INTRAFIELDNAVREQ" id= 6673 "INTRAFIELDNAVREQ">18.6.3. Intra-Field Navigation 6674 Requests</a></h4> 6675 6676 <p>These requests drive movement of the edit cursor 6677 within the currently selected field.</p> 6678 6679 <ul> 6680 <li> 6681 <p><span class="emphasis"><i class= 6682 "EMPHASIS">REQ_NEXT_CHAR</i></span> Move to next 6683 character.</p> 6684 </li> 6685 6686 <li> 6687 <p><span class="emphasis"><i class= 6688 "EMPHASIS">REQ_PREV_CHAR</i></span> Move to previous 6689 character.</p> 6690 </li> 6691 6692 <li> 6693 <p><span class="emphasis"><i class= 6694 "EMPHASIS">REQ_NEXT_LINE</i></span> Move to next 6695 line.</p> 6696 </li> 6697 6698 <li> 6699 <p><span class="emphasis"><i class= 6700 "EMPHASIS">REQ_PREV_LINE</i></span> Move to previous 6701 line.</p> 6702 </li> 6703 6704 <li> 6705 <p><span class="emphasis"><i class= 6706 "EMPHASIS">REQ_NEXT_WORD</i></span> Move to next 6707 word.</p> 6708 </li> 6709 6710 <li> 6711 <p><span class="emphasis"><i class= 6712 "EMPHASIS">REQ_PREV_WORD</i></span> Move to previous 6713 word.</p> 6714 </li> 6715 6716 <li> 6717 <p><span class="emphasis"><i class= 6718 "EMPHASIS">REQ_BEG_FIELD</i></span> Move to beginning 6719 of field.</p> 6720 </li> 6721 6722 <li> 6723 <p><span class="emphasis"><i class= 6724 "EMPHASIS">REQ_END_FIELD</i></span> Move to end of 6725 field.</p> 6726 </li> 6727 6728 <li> 6729 <p><span class="emphasis"><i class= 6730 "EMPHASIS">REQ_BEG_LINE</i></span> Move to beginning 6731 of line.</p> 6732 </li> 6733 6734 <li> 6735 <p><span class="emphasis"><i class= 6736 "EMPHASIS">REQ_END_LINE</i></span> Move to end of 6737 line.</p> 6738 </li> 6739 6740 <li> 6741 <p><span class="emphasis"><i class= 6742 "EMPHASIS">REQ_LEFT_CHAR</i></span> Move left in 6743 field.</p> 6744 </li> 6745 6746 <li> 6747 <p><span class="emphasis"><i class= 6748 "EMPHASIS">REQ_RIGHT_CHAR</i></span> Move right in 6749 field.</p> 6750 </li> 6751 6752 <li> 6753 <p><span class="emphasis"><i class= 6754 "EMPHASIS">REQ_UP_CHAR</i></span> Move up in 6755 field.</p> 6756 </li> 6757 6758 <li> 6759 <p><span class="emphasis"><i class= 6760 "EMPHASIS">REQ_DOWN_CHAR</i></span> Move down in 6761 field.</p> 6762 </li> 6763 </ul> 6764 6765 <p>Each word is separated from the previous and next 6766 characters by whitespace. The commands to move to 6767 beginning and end of line or field look for the first or 6768 last non-pad character in their ranges.</p> 6769 </div> 6770 6771 <div class="SECT3"> 6772 <hr> 6773 6774 <h4 class="SECT3"><a name="SCROLLREQ" id= 6775 "SCROLLREQ">18.6.4. Scrolling Requests</a></h4> 6776 6777 <p>Fields that are dynamic and have grown and fields 6778 explicitly created with offscreen rows are scrollable. 6779 One-line fields scroll horizontally; multi-line fields 6780 scroll vertically. Most scrolling is triggered by editing 6781 and intra-field movement (the library scrolls the field 6782 to keep the cursor visible). It is possible to explicitly 6783 request scrolling with the following requests:</p> 6784 6785 <ul> 6786 <li> 6787 <p><span class="emphasis"><i class= 6788 "EMPHASIS">REQ_SCR_FLINE</i></span> Scroll vertically 6789 forward a line.</p> 6790 </li> 6791 6792 <li> 6793 <p><span class="emphasis"><i class= 6794 "EMPHASIS">REQ_SCR_BLINE</i></span> Scroll vertically 6795 backward a line.</p> 6796 </li> 6797 6798 <li> 6799 <p><span class="emphasis"><i class= 6800 "EMPHASIS">REQ_SCR_FPAGE</i></span> Scroll vertically 6801 forward a page.</p> 6802 </li> 6803 6804 <li> 6805 <p><span class="emphasis"><i class= 6806 "EMPHASIS">REQ_SCR_BPAGE</i></span> Scroll vertically 6807 backward a page.</p> 6808 </li> 6809 6810 <li> 6811 <p><span class="emphasis"><i class= 6812 "EMPHASIS">REQ_SCR_FHPAGE</i></span> Scroll 6813 vertically forward half a page.</p> 6814 </li> 6815 6816 <li> 6817 <p><span class="emphasis"><i class= 6818 "EMPHASIS">REQ_SCR_BHPAGE</i></span> Scroll 6819 vertically backward half a page.</p> 6820 </li> 6821 6822 <li> 6823 <p><span class="emphasis"><i class= 6824 "EMPHASIS">REQ_SCR_FCHAR</i></span> Scroll 6825 horizontally forward a character.</p> 6826 </li> 6827 6828 <li> 6829 <p><span class="emphasis"><i class= 6830 "EMPHASIS">REQ_SCR_BCHAR</i></span> Scroll 6831 horizontally backward a character.</p> 6832 </li> 6833 6834 <li> 6835 <p><span class="emphasis"><i class= 6836 "EMPHASIS">REQ_SCR_HFLINE</i></span> Scroll 6837 horizontally one field width forward.</p> 6838 </li> 6839 6840 <li> 6841 <p><span class="emphasis"><i class= 6842 "EMPHASIS">REQ_SCR_HBLINE</i></span> Scroll 6843 horizontally one field width backward.</p> 6844 </li> 6845 6846 <li> 6847 <p><span class="emphasis"><i class= 6848 "EMPHASIS">REQ_SCR_HFHALF</i></span> Scroll 6849 horizontally one half field width forward.</p> 6850 </li> 6851 6852 <li> 6853 <p><span class="emphasis"><i class= 6854 "EMPHASIS">REQ_SCR_HBHALF</i></span> Scroll 6855 horizontally one half field width backward.</p> 6856 </li> 6857 </ul> 6858 6859 <p>For scrolling purposes, a page of a field is the 6860 height of its visible part.</p> 6861 </div> 6862 6863 <div class="SECT3"> 6864 <hr> 6865 6866 <h4 class="SECT3"><a name="EDITREQ" id="EDITREQ">18.6.5. 6867 Editing Requests</a></h4> 6868 6869 <p>When you pass the forms driver an ASCII character, it 6870 is treated as a request to add the character to the 6871 field's data buffer. Whether this is an insertion or a 6872 replacement depends on the field's edit mode (insertion 6873 is the default.</p> 6874 6875 <p>The following requests support editing the field and 6876 changing the edit mode:</p> 6877 6878 <ul> 6879 <li> 6880 <p><span class="emphasis"><i class= 6881 "EMPHASIS">REQ_INS_MODE</i></span> Set insertion 6882 mode.</p> 6883 </li> 6884 6885 <li> 6886 <p><span class="emphasis"><i class= 6887 "EMPHASIS">REQ_OVL_MODE</i></span> Set overlay 6888 mode.</p> 6889 </li> 6890 6891 <li> 6892 <p><span class="emphasis"><i class= 6893 "EMPHASIS">REQ_NEW_LINE</i></span> New line request 6894 (see below for explanation).</p> 6895 </li> 6896 6897 <li> 6898 <p><span class="emphasis"><i class= 6899 "EMPHASIS">REQ_INS_CHAR</i></span> Insert space at 6900 character location.</p> 6901 </li> 6902 6903 <li> 6904 <p><span class="emphasis"><i class= 6905 "EMPHASIS">REQ_INS_LINE</i></span> Insert blank line 6906 at character location.</p> 6907 </li> 6908 6909 <li> 6910 <p><span class="emphasis"><i class= 6911 "EMPHASIS">REQ_DEL_CHAR</i></span> Delete character 6912 at cursor.</p> 6913 </li> 6914 6915 <li> 6916 <p><span class="emphasis"><i class= 6917 "EMPHASIS">REQ_DEL_PREV</i></span> Delete previous 6918 word at cursor.</p> 6919 </li> 6920 6921 <li> 6922 <p><span class="emphasis"><i class= 6923 "EMPHASIS">REQ_DEL_LINE</i></span> Delete line at 6924 cursor.</p> 6925 </li> 6926 6927 <li> 6928 <p><span class="emphasis"><i class= 6929 "EMPHASIS">REQ_DEL_WORD</i></span> Delete word at 6930 cursor.</p> 6931 </li> 6932 6933 <li> 6934 <p><span class="emphasis"><i class= 6935 "EMPHASIS">REQ_CLR_EOL</i></span> Clear to end of 6936 line.</p> 6937 </li> 6938 6939 <li> 6940 <p><span class="emphasis"><i class= 6941 "EMPHASIS">REQ_CLR_EOF</i></span> Clear to end of 6942 field.</p> 6943 </li> 6944 6945 <li> 6946 <p><span class="emphasis"><i class= 6947 "EMPHASIS">REQ_CLR_FIELD</i></span> Clear entire 6948 field.</p> 6949 </li> 6950 </ul> 6951 6952 <p>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV 6953 requests is complicated and partly controlled by a pair 6954 of forms options. The special cases are triggered when 6955 the cursor is at the beginning of a field, or on the last 6956 line of the field.</p> 6957 6958 <p>First, we consider REQ_NEW_LINE:</p> 6959 6960 <p>The normal behavior of REQ_NEW_LINE in insert mode is 6961 to break the current line at the position of the edit 6962 cursor, inserting the portion of the current line after 6963 the cursor as a new line following the current and moving 6964 the cursor to the beginning of that new line (you may 6965 think of this as inserting a newline in the field 6966 buffer).</p> 6967 6968 <p>The normal behavior of REQ_NEW_LINE in overlay mode is 6969 to clear the current line from the position of the edit 6970 cursor to end of line. The cursor is then moved to the 6971 beginning of the next line.</p> 6972 6973 <p>However, REQ_NEW_LINE at the beginning of a field, or 6974 on the last line of a field, instead does a 6975 REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this special 6976 action is disabled.</p> 6977 6978 <p>Now, let us consider REQ_DEL_PREV:</p> 6979 6980 <p>The normal behavior of REQ_DEL_PREV is to delete the 6981 previous character. If insert mode is on, and the cursor 6982 is at the start of a line, and the text on that line will 6983 fit on the previous one, it instead appends the contents 6984 of the current line to the previous one and deletes the 6985 current line (you may think of this as deleting a newline 6986 from the field buffer).</p> 6987 6988 <p>However, REQ_DEL_PREV at the beginning of a field is 6989 instead treated as a REQ_PREV_FIELD.</p> 6990 6991 <p>If the O_BS_OVERLOAD option is off, this special 6992 action is disabled and the forms driver just returns 6993 E_REQUEST_DENIED.</p> 6994 </div> 6995 6996 <div class="SECT3"> 6997 <hr> 6998 6999 <h4 class="SECT3"><a name="ORDERREQ" id= 7000 "ORDERREQ">18.6.6. Order Requests</a></h4> 7001 7002 <p>If the type of your field is ordered, and has 7003 associated functions for getting the next and previous 7004 values of the type from a given value, there are requests 7005 that can fetch that value into the field buffer:</p> 7006 7007 <ul> 7008 <li> 7009 <p><span class="emphasis"><i class= 7010 "EMPHASIS">REQ_NEXT_CHOICE</i></span> Place the 7011 successor value of the current value in the 7012 buffer.</p> 7013 </li> 7014 7015 <li> 7016 <p><span class="emphasis"><i class= 7017 "EMPHASIS">REQ_PREV_CHOICE</i></span> Place the 7018 predecessor value of the current value in the 7019 buffer.</p> 7020 </li> 7021 </ul> 7022 7023 <p>Of the built-in field types, only TYPE_ENUM has 7024 built-in successor and predecessor functions. When you 7025 define a field type of your own (see Custom Validation 7026 Types), you can associate our own ordering functions.</p> 7027 </div> 7028 7029 <div class="SECT3"> 7030 <hr> 7031 7032 <h4 class="SECT3"><a name="APPLICCOMMANDS" id= 7033 "APPLICCOMMANDS">18.6.7. Application Commands</a></h4> 7034 7035 <p>Form requests are represented as integers above the 7036 curses value greater than KEY_MAX and less than or equal 7037 to the constant MAX_COMMAND. A value within this range 7038 gets ignored by form_driver(). So this can be used for 7039 any purpose by the application. It can be treated as an 7040 application specific action and take corresponding 7041 action.</p> 7042 </div> 7043 </div> 7044 </div> 7045 7046 <div class="SECT1"> 7047 <hr> 7048 7049 <h2 class="SECT1"><a name="TOOLS" id="TOOLS">19. Tools and 7050 Widget Libraries</a></h2> 7051 7052 <p>Now that you have seen the capabilities of ncurses and its 7053 sister libraries, you are rolling your sleeves up and gearing 7054 for a project that heavily manipulates screen. But wait.. It 7055 can be pretty difficult to write and maintain complex GUI 7056 widgets in plain ncurses or even with the additional 7057 libraries. There are some ready-to-use tools and widget 7058 libraries that can be used instead of writing your own 7059 widgets. You can use some of them, get ideas from the code, 7060 or even extend them.</p> 7061 7062 <div class="SECT2"> 7063 <hr> 7064 7065 <h3 class="SECT2"><a name="CDK" id="CDK">19.1. CDK (Curses 7066 Development Kit)</a></h3> 7067 7068 <p>In the author's words</p> 7069 7070 <p><span class="emphasis"><i class="EMPHASIS">CDK stands 7071 for 'Curses Development Kit' and it currently contains 21 7072 ready to use widgets which facilitate the speedy 7073 development of full screen curses programs.</i></span></p> 7074 7075 <p>The kit provides some useful widgets, which can be used 7076 in your programs directly. It's pretty well written and the 7077 documentation is very good. The examples in the examples 7078 directory can be a good place to start for beginners. The 7079 CDK can be downloaded from <a href= 7080 "https://invisible-island.net/cdk/" target= 7081 "_top">https://invisible-island.net/cdk/</a> . Follow the 7082 instructions in README file to install it.</p> 7083 7084 <div class="SECT3"> 7085 <hr> 7086 7087 <h4 class="SECT3"><a name="WIDGETLIST" id= 7088 "WIDGETLIST">19.1.1. Widget List</a></h4> 7089 7090 <p>The following is the list of widgets provided with cdk 7091 and their description.</p> 7092 <pre class="PROGRAMLISTING"> 7093Widget Type Quick Description 7094=========================================================================== 7095Alphalist Allows a user to select from a list of words, with 7096 the ability to narrow the search list by typing in a 7097 few characters of the desired word. 7098Buttonbox This creates a multiple button widget. 7099Calendar Creates a little simple calendar widget. 7100Dialog Prompts the user with a message, and the user 7101 can pick an answer from the buttons provided. 7102Entry Allows the user to enter various types of information. 7103File Selector A file selector built from Cdk base widgets. This 7104 example shows how to create more complicated widgets 7105 using the Cdk widget library. 7106Graph Draws a graph. 7107Histogram Draws a histogram. 7108Item List Creates a pop up field which allows the user to select 7109 one of several choices in a small field. Very useful 7110 for things like days of the week or month names. 7111Label Displays messages in a pop up box, or the label can be 7112 considered part of the screen. 7113Marquee Displays a message in a scrolling marquee. 7114Matrix Creates a complex matrix with lots of options. 7115Menu Creates a pull-down menu interface. 7116Multiple Line Entry A multiple line entry field. Very useful 7117 for long fields. (like a description 7118 field) 7119Radio List Creates a radio button list. 7120Scale Creates a numeric scale. Used for allowing a user to 7121 pick a numeric value and restrict them to a range of 7122 values. 7123Scrolling List Creates a scrolling list/menu list. 7124Scrolling Window Creates a scrolling log file viewer. Can add 7125 information into the window while its running. 7126 A good widget for displaying the progress of 7127 something. (akin to a console window) 7128Selection List Creates a multiple option selection list. 7129Slider Akin to the scale widget, this widget provides a 7130 visual slide bar to represent the numeric value. 7131Template Creates a entry field with character sensitive 7132 positions. Used for pre-formatted fields like 7133 dates and phone numbers. 7134Viewer This is a file/information viewer. Very useful 7135 when you need to display loads of information. 7136=========================================================================== 7137</pre> 7138 7139 <p>A few of the widgets are modified by Thomas Dickey in 7140 recent versions.</p> 7141 </div> 7142 7143 <div class="SECT3"> 7144 <hr> 7145 7146 <h4 class="SECT3"><a name="CDKATTRACT" id= 7147 "CDKATTRACT">19.1.2. Some Attractive Features</a></h4> 7148 7149 <p>Apart from making our life easier with readily usable 7150 widgets, cdk solves one frustrating problem with printing 7151 multi colored strings, justified strings elegantly. 7152 Special formatting tags can be embedded in the strings 7153 which are passed to CDK functions. For Example</p> 7154 7155 <p>If the string</p> 7156 <pre class="PROGRAMLISTING"> 7157"</B/1>This line should have a yellow foreground and a blue 7158background.<!1>" 7159</pre> 7160 7161 <p>given as a parameter to newCDKLabel(), it prints the 7162 line with yellow foreground and blue background. There 7163 are other tags available for justifying string, embedding 7164 special drawing characters etc.. Please refer to the man 7165 page cdk_display(3X) for details. The man page explains 7166 the usage with nice examples.</p> 7167 </div> 7168 7169 <div class="SECT3"> 7170 <hr> 7171 7172 <h4 class="SECT3"><a name="CDKCONCLUSION" id= 7173 "CDKCONCLUSION">19.1.3. Conclusion</a></h4> 7174 7175 <p>All in all, CDK is a well-written package of widgets, 7176 which if used properly can form a strong frame work for 7177 developing complex GUI.</p> 7178 </div> 7179 </div> 7180 7181 <div class="SECT2"> 7182 <hr> 7183 7184 <h3 class="SECT2"><a name="DIALOG" id="DIALOG">19.2. The 7185 dialog</a></h3> 7186 7187 <p>Long long ago, in September 1994, when few people knew 7188 linux, Jeff Tranter wrote an <a href= 7189 "http://www2.linuxjournal.com/lj-issues/issue5/2807.html" 7190 target="_top">article</a> on dialog in Linux Journal. He 7191 starts the article with these words..</p> 7192 7193 <p><span class="emphasis"><i class="EMPHASIS">Linux is 7194 based on the Unix operating system, but also features a 7195 number of unique and useful kernel features and application 7196 programs that often go beyond what is available under Unix. 7197 One little-known gem is "dialog", a utility for creating 7198 professional-looking dialog boxes from within shell 7199 scripts. This article presents a tutorial introduction to 7200 the dialog utility, and shows examples of how and where it 7201 can be used</i></span></p> 7202 7203 <p>As he explains, dialog is a real gem in making 7204 professional-looking dialog boxes with ease. It creates a 7205 variety of dialog boxes, menus, check lists etc.. It is 7206 usually installed by default. If not, you can download it 7207 from <a href="https://invisible-island.net/dialog/" target= 7208 "_top">Thomas Dickey</a>'s site.</p> 7209 7210 <p>The above-mentioned article gives a very good overview 7211 of its uses and capabilites. The man page has more details. 7212 It can be used in variety of situations. One good example 7213 is building of linux kernel in text mode. Linux kernel uses 7214 a modified version of dialog tailored for its needs.</p> 7215 7216 <p>dialog was initially designed to be used with shell 7217 scripts. If you want to use its functionality in a c 7218 program, then you can use libdialog. The documentation 7219 regarding this is sparse. Definitive reference is the 7220 dialog.h header file which comes with the library. You may 7221 need to hack here and there to get the required output. The 7222 source is easily customizable. I have used it on a number 7223 of occasions by modifying the code.</p> 7224 </div> 7225 7226 <div class="SECT2"> 7227 <hr> 7228 7229 <h3 class="SECT2"><a name="PERLCURSES" id= 7230 "PERLCURSES">19.3. Perl Curses Modules CURSES::FORM and 7231 CURSES::WIDGETS</a></h3> 7232 7233 <p>The perl module Curses, Curses::Form and Curses::Widgets 7234 give access to curses from perl. If you have curses and 7235 basic perl is installed, you can get these modules from 7236 <a href="http://www.cpan.org/modules/01modules.index.html" 7237 target="_top">CPAN All Modules page</a>. Get the three 7238 zipped modules in the Curses category. Once installed you 7239 can use these modules from perl scripts like any other 7240 module. For more information on perl modules see perlmod 7241 man page. The above modules come with good documentation 7242 and they have some demo scripts to test the functionality. 7243 Though the widgets provided are very rudimentary, these 7244 modules provide good access to curses library from 7245 perl.</p> 7246 7247 <p>Some of my code examples are converted to perl by 7248 Anuradha Ratnaweera and they are available in the 7249 <tt class="LITERAL">perl</tt> directory.</p> 7250 7251 <p>For more information see man pages Curses(3) , 7252 Curses::Form(3) and Curses::Widgets(3). These pages are 7253 installed only when the above modules are acquired and 7254 installed.</p> 7255 </div> 7256 </div> 7257 7258 <div class="SECT1"> 7259 <hr> 7260 7261 <h2 class="SECT1"><a name="JUSTFORFUN" id="JUSTFORFUN">20. 7262 Just For Fun !!!</a></h2> 7263 7264 <p>This section contains few programs written by me just for 7265 fun. They don't signify a better programming practice or the 7266 best way of using ncurses. They are provided here so as to 7267 allow beginners to get ideas and add more programs to this 7268 section. If you have written a couple of nice, simple 7269 programs in curses and want them to included here, contact 7270 <a href="mailto:[email protected]" target="_top">me</a>.</p> 7271 7272 <div class="SECT2"> 7273 <hr> 7274 7275 <h3 class="SECT2"><a name="GAMEOFLIFE" id= 7276 "GAMEOFLIFE">20.1. The Game of Life</a></h3> 7277 7278 <p>Game of life is a wonder of math. In <a href= 7279 "http://www.math.com/students/wonders/life/life.html" 7280 target="_top">Paul Callahan</a>'s words</p> 7281 <pre class="PROGRAMLISTING"> 7282<span class="emphasis"><i class= 7283"EMPHASIS">The Game of Life (or simply Life) is not a game in the conventional sense. There 7284are no players, and no winning or losing. Once the "pieces" are placed in the 7285starting position, the rules determine everything that happens later. 7286Nevertheless, Life is full of surprises! In most cases, it is impossible to look 7287at a starting position (or pattern) and see what will happen in the future. The 7288only way to find out is to follow the rules of the game.</i></span> 7289</pre> 7290 7291 <p>This program starts with a simple inverted U pattern and 7292 shows how wonderful life works. There is a lot of room for 7293 improvement in the program. You can let the user enter 7294 pattern of his choice or even take input from a file. You 7295 can also change rules and play with a lot of variations. 7296 Search on <a href="http://www.google.com" target= 7297 "_top">google</a> for interesting information on game of 7298 life.</p> 7299 7300 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7301 JustForFun/life.c</i></span></p> 7302 </div> 7303 7304 <div class="SECT2"> 7305 <hr> 7306 7307 <h3 class="SECT2"><a name="MAGIC" id="MAGIC">20.2. Magic 7308 Square</a></h3> 7309 7310 <p>Magic Square, another wonder of math, is very simple to 7311 understand but very difficult to make. In a magic square 7312 sum of the numbers in each row, each column is equal. Even 7313 diagnol sum can be equal. There are many variations which 7314 have special properties.</p> 7315 7316 <p>This program creates a simple magic square of odd 7317 order.</p> 7318 7319 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7320 JustForFun/magic.c</i></span></p> 7321 </div> 7322 7323 <div class="SECT2"> 7324 <hr> 7325 7326 <h3 class="SECT2"><a name="HANOI" id="HANOI">20.3. Towers 7327 of Hanoi</a></h3> 7328 7329 <p>The famous towers of hanoi solver. The aim of the game 7330 is to move the disks on the first peg to last peg, using 7331 middle peg as a temporary stay. The catch is not to place a 7332 larger disk over a small disk at any time.</p> 7333 7334 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7335 JustForFun/hanoi.c</i></span></p> 7336 </div> 7337 7338 <div class="SECT2"> 7339 <hr> 7340 7341 <h3 class="SECT2"><a name="QUEENS" id="QUEENS">20.4. Queens 7342 Puzzle</a></h3> 7343 7344 <p>The objective of the famous N-Queen puzzle is to put N 7345 queens on a N X N chess board without attacking each 7346 other.</p> 7347 7348 <p>This program solves it with a simple backtracking 7349 technique.</p> 7350 7351 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7352 JustForFun/queens.c</i></span></p> 7353 </div> 7354 7355 <div class="SECT2"> 7356 <hr> 7357 7358 <h3 class="SECT2"><a name="SHUFFLE" id="SHUFFLE">20.5. 7359 Shuffle</a></h3> 7360 7361 <p>A fun game, if you have time to kill.</p> 7362 7363 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7364 JustForFun/shuffle.c</i></span></p> 7365 </div> 7366 7367 <div class="SECT2"> 7368 <hr> 7369 7370 <h3 class="SECT2"><a name="TT" id="TT">20.6. Typing 7371 Tutor</a></h3> 7372 7373 <p>A simple typing tutor, I created more out of need than 7374 for ease of use. If you know how to put your fingers 7375 correctly on the keyboard, but lack practice, this can be 7376 helpful.</p> 7377 7378 <p><span class="emphasis"><i class="EMPHASIS">File Path: 7379 JustForFun/tt.c</i></span></p> 7380 </div> 7381 </div> 7382 7383 <div class="SECT1"> 7384 <hr> 7385 7386 <h2 class="SECT1"><a name="REF" id="REF">21. 7387 References</a></h2> 7388 7389 <ul> 7390 <li> 7391 <p>NCURSES man pages</p> 7392 </li> 7393 7394 <li> 7395 <p>NCURSES FAQ at <a href= 7396 "https://invisible-island.net/ncurses/ncurses.faq.html" 7397 target= 7398 "_top">https://invisible-island.net/ncurses/ncurses.faq.html</a></p> 7399 </li> 7400 7401 <li> 7402 <p>Writing programs with NCURSES by Eric Raymond and Zeyd 7403 M. Ben-Halim at <a href= 7404 "https://invisible-island.net/ncurses/ncurses-intro.html" 7405 target= 7406 "_top">https://invisible-island.net/ncurses/ncurses-intro.html</a> 7407 - somewhat obsolete. I was inspired by this document and 7408 the structure of this HOWTO follows from the original 7409 document</p> 7410 </li> 7411 </ul> 7412 </div> 7413 </div> 7414</body> 7415</html> 7416