]> ncurses.scripts.mit.edu Git - ncurses.git/blob - doc/html/NCURSES-Programming-HOWTO.html
ncurses 6.3 - patch 20221126
[ncurses.git] / doc / html / NCURSES-Programming-HOWTO.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
2 "http://www.w3.org/TR/html4/strict.dtd">
3 <html>
4 <head>
5   <meta name="generator" content=
6   "HTML Tidy for HTML5 for Linux version 5.6.0">
7   <title>NCURSES Programming HOWTO</title>
8   <meta name="GENERATOR" content=
9   "Modular DocBook HTML Stylesheet Version 1.79">
10 </head>
11 <body class="ARTICLE" bgcolor="#FFFFFF" text="#000000" link=
12 "#0000FF" vlink="#840084" alink="#0000FF">
13   <div class="ARTICLE">
14     <div class="TITLEPAGE">
15       <h1 class="TITLE"><a name="AEN2" id="AEN2">NCURSES
16       Programming HOWTO</a></h1>
17
18       <h3 class="AUTHOR"><a name="AEN4" id="AEN4">Pradeep
19       Padala</a></h3>
20
21       <div class="AFFILIATION">
22         <div class="ADDRESS">
23           <p class="ADDRESS"><code class="EMAIL">&lt;<a href=
24           "mailto:ppadala@gmail.com">ppadala@gmail.com</a>&gt;</code>
25           </p>
26         </div>
27       </div>
28
29       <p class="PUBDATE">v1.9, 2005-06-20<br></p>
30
31       <div class="REVHISTORY">
32         <table width="100%" border="0" summary="revisions">
33           <tr>
34             <th align="left" valign="top" colspan="3"><b>Revision
35             History</b>
36             </th>
37           </tr>
38
39           <tr>
40             <td align="left">Revision 1.9</td>
41             <td align="left">2005-06-20</td>
42             <td align="left">Revised by: ppadala</td>
43           </tr>
44
45           <tr>
46             <td align="left" colspan="3">The license has been
47             changed to the MIT-style license used by NCURSES. Note
48             that the programs are also re-licensed under this.</td>
49           </tr>
50
51           <tr>
52             <td align="left">Revision 1.8</td>
53             <td align="left">2005-06-17</td>
54             <td align="left">Revised by: ppadala</td>
55           </tr>
56
57           <tr>
58             <td align="left" colspan="3">Lots of updates. Added
59             references and perl examples. Changes to examples. Many
60             grammatical and stylistic changes to the content.
61             Changes to NCURSES history.</td>
62           </tr>
63
64           <tr>
65             <td align="left">Revision 1.7.1</td>
66             <td align="left">2002-06-25</td>
67             <td align="left">Revised by: ppadala</td>
68           </tr>
69
70           <tr>
71             <td align="left" colspan="3">Added a README file for
72             building and instructions for building from
73             source.</td>
74           </tr>
75
76           <tr>
77             <td align="left">Revision 1.7</td>
78             <td align="left">2002-06-25</td>
79             <td align="left">Revised by: ppadala</td>
80           </tr>
81
82           <tr>
83             <td align="left" colspan="3">Added "Other formats"
84             section and made a lot of fancy changes to the
85             programs. Inlining of programs is gone.</td>
86           </tr>
87
88           <tr>
89             <td align="left">Revision 1.6.1</td>
90             <td align="left">2002-02-24</td>
91             <td align="left">Revised by: ppadala</td>
92           </tr>
93
94           <tr>
95             <td align="left" colspan="3">Removed the old Changelog
96             section, cleaned the makefiles</td>
97           </tr>
98
99           <tr>
100             <td align="left">Revision 1.6</td>
101             <td align="left">2002-02-16</td>
102             <td align="left">Revised by: ppadala</td>
103           </tr>
104
105           <tr>
106             <td align="left" colspan="3">Corrected a lot of
107             spelling mistakes, added ACS variables section</td>
108           </tr>
109
110           <tr>
111             <td align="left">Revision 1.5</td>
112             <td align="left">2002-01-05</td>
113             <td align="left">Revised by: ppadala</td>
114           </tr>
115
116           <tr>
117             <td align="left" colspan="3">Changed structure to
118             present proper TOC</td>
119           </tr>
120
121           <tr>
122             <td align="left">Revision 1.3.1</td>
123             <td align="left">2001-07-26</td>
124             <td align="left">Revised by: ppadala</td>
125           </tr>
126
127           <tr>
128             <td align="left" colspan="3">Corrected maintainers
129             paragraph, Corrected stable release number</td>
130           </tr>
131
132           <tr>
133             <td align="left">Revision 1.3</td>
134             <td align="left">2001-07-24</td>
135             <td align="left">Revised by: ppadala</td>
136           </tr>
137
138           <tr>
139             <td align="left" colspan="3">Added copyright notices to
140             main document (LDP license) and programs (GPL),
141             Corrected printw_example.</td>
142           </tr>
143
144           <tr>
145             <td align="left">Revision 1.2</td>
146             <td align="left">2001-06-05</td>
147             <td align="left">Revised by: ppadala</td>
148           </tr>
149
150           <tr>
151             <td align="left" colspan="3">Incorporated ravi's
152             changes. Mainly to introduction, menu, form, justforfun
153             sections</td>
154           </tr>
155
156           <tr>
157             <td align="left">Revision 1.1</td>
158             <td align="left">2001-05-22</td>
159             <td align="left">Revised by: ppadala</td>
160           </tr>
161
162           <tr>
163             <td align="left" colspan="3">Added "a word about
164             window" section, Added scanw_example.</td>
165           </tr>
166         </table>
167       </div>
168
169       <div>
170         <div class="ABSTRACT">
171           <a name="AEN67" id="AEN67"></a>
172           <p><span class="emphasis"><i class="EMPHASIS">This
173           document is intended to be an "All in One" guide for
174           programming with ncurses and its sister libraries. We
175           graduate from a simple "Hello World" program to more
176           complex form manipulation. No prior experience in ncurses
177           is assumed. Send comments to <a href=
178           "mailto:ppadala@gmail.com" target="_top">this
179           address</a></i></span>
180           </p>
181         </div>
182       </div>
183
184       <hr>
185     </div>
186
187     <div class="TOC">
188       <dl>
189         <dt><b>Table of Contents</b>
190         </dt>
191
192         <dt>1. <a href="#INTRO">Introduction</a></dt>
193
194         <dd>
195           <dl>
196             <dt>1.1. <a href="#WHATIS">What is NCURSES?</a></dt>
197
198             <dt>1.2. <a href="#WHATCANWEDO">What we can do with
199             NCURSES</a></dt>
200
201             <dt>1.3. <a href="#WHERETOGETIT">Where to get
202             it</a></dt>
203
204             <dt>1.4. <a href="#PURPOSE">Purpose/Scope of the
205             document</a></dt>
206
207             <dt>1.5. <a href="#ABOUTPROGRAMS">About the
208             Programs</a></dt>
209
210             <dt>1.6. <a href="#OTHERFORMATS">Other Formats of the
211             document</a></dt>
212
213             <dd>
214               <dl>
215                 <dt>1.6.1. <a href="#LISTFORMATS">Readily available
216                 formats from tldp.org</a></dt>
217
218                 <dt>1.6.2. <a href="#BUILDSOURCE">Building from
219                 source</a></dt>
220               </dl>
221             </dd>
222
223             <dt>1.7. <a href="#CREDITS">Credits</a></dt>
224
225             <dt>1.8. <a href="#WISHLIST">Wish List</a></dt>
226
227             <dt>1.9. <a href="#COPYRIGHT">Copyright</a></dt>
228           </dl>
229         </dd>
230
231         <dt>2. <a href="#HELLOWORLD">Hello World !!!</a></dt>
232
233         <dd>
234           <dl>
235             <dt>2.1. <a href="#COMPILECURSES">Compiling With the
236             NCURSES Library</a></dt>
237
238             <dt>2.2. <a href="#DISSECTION">Dissection</a></dt>
239
240             <dd>
241               <dl>
242                 <dt>2.2.1. <a href="#ABOUT-INITSCR">About
243                 initscr()</a></dt>
244
245                 <dt>2.2.2. <a href="#MYST-REFRESH">The mysterious
246                 refresh()</a></dt>
247
248                 <dt>2.2.3. <a href="#ABOUT-ENDWIN">About
249                 endwin()</a></dt>
250               </dl>
251             </dd>
252           </dl>
253         </dd>
254
255         <dt>3. <a href="#GORY">The Gory Details</a></dt>
256
257         <dt>4. <a href="#INIT">Initialization</a></dt>
258
259         <dd>
260           <dl>
261             <dt>4.1. <a href="#ABOUTINIT">Initialization
262             functions</a></dt>
263
264             <dt>4.2. <a href="#RAWCBREAK">raw() and
265             cbreak()</a></dt>
266
267             <dt>4.3. <a href="#ECHONOECHO">echo() and
268             noecho()</a></dt>
269
270             <dt>4.4. <a href="#KEYPAD">keypad()</a></dt>
271
272             <dt>4.5. <a href="#HALFDELAY">halfdelay()</a></dt>
273
274             <dt>4.6. <a href="#MISCINIT">Miscellaneous
275             Initialization functions</a></dt>
276
277             <dt>4.7. <a href="#INITEX">An Example</a></dt>
278           </dl>
279         </dd>
280
281         <dt>5. <a href="#AWORDWINDOWS">A Word about
282         Windows</a></dt>
283
284         <dt>6. <a href="#PRINTW">Output functions</a></dt>
285
286         <dd>
287           <dl>
288             <dt>6.1. <a href="#ADDCHCLASS">addch() class of
289             functions</a></dt>
290
291             <dt>6.2. <a href="#AEN298">mvaddch(), waddch() and
292             mvwaddch()</a></dt>
293
294             <dt>6.3. <a href="#PRINTWCLASS">printw() class of
295             functions</a></dt>
296
297             <dd>
298               <dl>
299                 <dt>6.3.1. <a href="#PRINTWMVPRINTW">printw() and
300                 mvprintw</a></dt>
301
302                 <dt>6.3.2. <a href="#WPRINTWMVWPRINTW">wprintw()
303                 and mvwprintw</a></dt>
304
305                 <dt>6.3.3. <a href="#VWPRINTW">vw_printw()</a></dt>
306
307                 <dt>6.3.4. <a href="#SIMPLEPRINTWEX">A Simple
308                 printw example</a></dt>
309               </dl>
310             </dd>
311
312             <dt>6.4. <a href="#ADDSTRCLASS">addstr() class of
313             functions</a></dt>
314
315             <dt>6.5. <a href="#ACAUTION">A word of caution</a></dt>
316           </dl>
317         </dd>
318
319         <dt>7. <a href="#SCANW">Input functions</a></dt>
320
321         <dd>
322           <dl>
323             <dt>7.1. <a href="#GETCHCLASS">getch() class of
324             functions</a></dt>
325
326             <dt>7.2. <a href="#SCANWCLASS">scanw() class of
327             functions</a></dt>
328
329             <dd>
330               <dl>
331                 <dt>7.2.1. <a href="#SCANWMVSCANW">scanw() and
332                 mvscanw</a></dt>
333
334                 <dt>7.2.2. <a href="#WSCANWMVWSCANW">wscanw() and
335                 mvwscanw()</a></dt>
336
337                 <dt>7.2.3. <a href="#VWSCANW">vw_scanw()</a></dt>
338               </dl>
339             </dd>
340
341             <dt>7.3. <a href="#GETSTRCLASS">getstr() class of
342             functions</a></dt>
343
344             <dt>7.4. <a href="#GETSTREX">Some examples</a></dt>
345           </dl>
346         </dd>
347
348         <dt>8. <a href="#ATTRIB">Attributes</a></dt>
349
350         <dd>
351           <dl>
352             <dt>8.1. <a href="#ATTRIBDETAILS">The details</a></dt>
353
354             <dt>8.2. <a href="#ATTRONVSATTRSET">attron() vs
355             attrset()</a></dt>
356
357             <dt>8.3. <a href="#ATTRGET">attr_get()</a></dt>
358
359             <dt>8.4. <a href="#ATTRFUNCS">attr_ functions</a></dt>
360
361             <dt>8.5. <a href="#WATTRFUNCS">wattr functions</a></dt>
362
363             <dt>8.6. <a href="#CHGAT">chgat() functions</a></dt>
364           </dl>
365         </dd>
366
367         <dt>9. <a href="#WINDOWS">Windows</a></dt>
368
369         <dd>
370           <dl>
371             <dt>9.1. <a href="#WINDOWBASICS">The basics</a></dt>
372
373             <dt>9.2. <a href="#LETBEWINDOW">Let there be a Window
374             !!!</a></dt>
375
376             <dt>9.3. <a href="#BORDEREXEXPL">Explanation</a></dt>
377
378             <dt>9.4. <a href="#OTHERSTUFF">The other stuff in the
379             example</a></dt>
380
381             <dt>9.5. <a href="#OTHERBORDERFUNCS">Other Border
382             functions</a></dt>
383           </dl>
384         </dd>
385
386         <dt>10. <a href="#COLOR">Colors</a></dt>
387
388         <dd>
389           <dl>
390             <dt>10.1. <a href="#COLORBASICS">The basics</a></dt>
391
392             <dt>10.2. <a href="#CHANGECOLORDEFS">Changing Color
393             Definitions</a></dt>
394
395             <dt>10.3. <a href="#COLORCONTENT">Color
396             Content</a></dt>
397           </dl>
398         </dd>
399
400         <dt>11. <a href="#KEYS">Interfacing with the key
401         board</a></dt>
402
403         <dd>
404           <dl>
405             <dt>11.1. <a href="#KEYSBASICS">The Basics</a></dt>
406
407             <dt>11.2. <a href="#SIMPLEKEYEX">A Simple Key Usage
408             example</a></dt>
409           </dl>
410         </dd>
411
412         <dt>12. <a href="#MOUSE">Interfacing with the
413         mouse</a></dt>
414
415         <dd>
416           <dl>
417             <dt>12.1. <a href="#MOUSEBASICS">The Basics</a></dt>
418
419             <dt>12.2. <a href="#GETTINGEVENTS">Getting the
420             events</a></dt>
421
422             <dt>12.3. <a href="#MOUSETOGETHER">Putting it all
423             Together</a></dt>
424
425             <dt>12.4. <a href="#MISCMOUSEFUNCS">Miscellaneous
426             Functions</a></dt>
427           </dl>
428         </dd>
429
430         <dt>13. <a href="#SCREEN">Screen Manipulation</a></dt>
431
432         <dd>
433           <dl>
434             <dt>13.1. <a href="#GETYX">getyx() functions</a></dt>
435
436             <dt>13.2. <a href="#SCREENDUMP">Screen Dumping</a></dt>
437
438             <dt>13.3. <a href="#WINDOWDUMP">Window Dumping</a></dt>
439           </dl>
440         </dd>
441
442         <dt>14. <a href="#MISC">Miscellaneous features</a></dt>
443
444         <dd>
445           <dl>
446             <dt>14.1. <a href="#CURSSET">curs_set()</a></dt>
447
448             <dt>14.2. <a href="#TEMPLEAVE">Temporarily Leaving
449             Curses mode</a></dt>
450
451             <dt>14.3. <a href="#ACSVARS">ACS_ variables</a></dt>
452           </dl>
453         </dd>
454
455         <dt>15. <a href="#OTHERLIB">Other libraries</a></dt>
456
457         <dt>16. <a href="#PANELS">Panel Library</a></dt>
458
459         <dd>
460           <dl>
461             <dt>16.1. <a href="#PANELBASICS">The Basics</a></dt>
462
463             <dt>16.2. <a href="#COMPILEPANELS">Compiling With the
464             Panels Library</a></dt>
465
466             <dt>16.3. <a href="#PANELBROWSING">Panel Window
467             Browsing</a></dt>
468
469             <dt>16.4. <a href="#USERPTRUSING">Using User
470             Pointers</a></dt>
471
472             <dt>16.5. <a href="#PANELMOVERESIZE">Moving and
473             Resizing Panels</a></dt>
474
475             <dt>16.6. <a href="#PANELSHOWHIDE">Hiding and Showing
476             Panels</a></dt>
477
478             <dt>16.7. <a href="#PANELABOVE">panel_above() and
479             panel_below() Functions</a></dt>
480           </dl>
481         </dd>
482
483         <dt>17. <a href="#MENUS">Menus Library</a></dt>
484
485         <dd>
486           <dl>
487             <dt>17.1. <a href="#MENUBASICS">The Basics</a></dt>
488
489             <dt>17.2. <a href="#COMPILEMENUS">Compiling With the
490             Menu Library</a></dt>
491
492             <dt>17.3. <a href="#MENUDRIVER">Menu Driver: The work
493             horse of the menu system</a></dt>
494
495             <dt>17.4. <a href="#MENUWINDOWS">Menu Windows</a></dt>
496
497             <dt>17.5. <a href="#SCROLLMENUS">Scrolling
498             Menus</a></dt>
499
500             <dt>17.6. <a href="#MULTICOLUMN">Multi Columnar
501             Menus</a></dt>
502
503             <dt>17.7. <a href="#MULTIVALUEMENUS">Multi Valued
504             Menus</a></dt>
505
506             <dt>17.8. <a href="#MENUOPT">Menu Options</a></dt>
507
508             <dt>17.9. <a href="#MENUUSERPTR">The useful User
509             Pointer</a></dt>
510           </dl>
511         </dd>
512
513         <dt>18. <a href="#FORMS">Forms Library</a></dt>
514
515         <dd>
516           <dl>
517             <dt>18.1. <a href="#FORMBASICS">The Basics</a></dt>
518
519             <dt>18.2. <a href="#COMPILEFORMS">Compiling With the
520             Forms Library</a></dt>
521
522             <dt>18.3. <a href="#PLAYFIELDS">Playing with
523             Fields</a></dt>
524
525             <dd>
526               <dl>
527                 <dt>18.3.1. <a href="#FETCHINFO">Fetching Size and
528                 Location of Field</a></dt>
529
530                 <dt>18.3.2. <a href="#MOVEFIELD">Moving the
531                 field</a></dt>
532
533                 <dt>18.3.3. <a href="#JUSTIFYFIELD">Field
534                 Justification</a></dt>
535
536                 <dt>18.3.4. <a href="#FIELDDISPATTRIB">Field
537                 Display Attributes</a></dt>
538
539                 <dt>18.3.5. <a href="#FIELDOPTIONBITS">Field Option
540                 Bits</a></dt>
541
542                 <dt>18.3.6. <a href="#FIELDSTATUS">Field
543                 Status</a></dt>
544
545                 <dt>18.3.7. <a href="#FIELDUSERPTR">Field User
546                 Pointer</a></dt>
547
548                 <dt>18.3.8. <a href=
549                 "#VARIABLESIZEFIELDS">Variable-Sized
550                 Fields</a></dt>
551               </dl>
552             </dd>
553
554             <dt>18.4. <a href="#FORMWINDOWS">Form Windows</a></dt>
555
556             <dt>18.5. <a href="#FILEDVALIDATE">Field
557             Validation</a></dt>
558
559             <dt>18.6. <a href="#FORMDRIVER">Form Driver: The work
560             horse of the forms system</a></dt>
561
562             <dd>
563               <dl>
564                 <dt>18.6.1. <a href="#PAGENAVREQ">Page Navigation
565                 Requests</a></dt>
566
567                 <dt>18.6.2. <a href="#INTERFIELDNAVREQ">Inter-Field
568                 Navigation Requests</a></dt>
569
570                 <dt>18.6.3. <a href="#INTRAFIELDNAVREQ">Intra-Field
571                 Navigation Requests</a></dt>
572
573                 <dt>18.6.4. <a href="#SCROLLREQ">Scrolling
574                 Requests</a></dt>
575
576                 <dt>18.6.5. <a href="#EDITREQ">Editing
577                 Requests</a></dt>
578
579                 <dt>18.6.6. <a href="#ORDERREQ">Order
580                 Requests</a></dt>
581
582                 <dt>18.6.7. <a href="#APPLICCOMMANDS">Application
583                 Commands</a></dt>
584               </dl>
585             </dd>
586           </dl>
587         </dd>
588
589         <dt>19. <a href="#TOOLS">Tools and Widget
590         Libraries</a></dt>
591
592         <dd>
593           <dl>
594             <dt>19.1. <a href="#CDK">CDK (Curses Development
595             Kit)</a></dt>
596
597             <dd>
598               <dl>
599                 <dt>19.1.1. <a href="#WIDGETLIST">Widget
600                 List</a></dt>
601
602                 <dt>19.1.2. <a href="#CDKATTRACT">Some Attractive
603                 Features</a></dt>
604
605                 <dt>19.1.3. <a href=
606                 "#CDKCONCLUSION">Conclusion</a></dt>
607               </dl>
608             </dd>
609
610             <dt>19.2. <a href="#DIALOG">The dialog</a></dt>
611
612             <dt>19.3. <a href="#PERLCURSES">Perl Curses Modules
613             CURSES::FORM and CURSES::WIDGETS</a></dt>
614           </dl>
615         </dd>
616
617         <dt>20. <a href="#JUSTFORFUN">Just For Fun !!!</a></dt>
618
619         <dd>
620           <dl>
621             <dt>20.1. <a href="#GAMEOFLIFE">The Game of
622             Life</a></dt>
623
624             <dt>20.2. <a href="#MAGIC">Magic Square</a></dt>
625
626             <dt>20.3. <a href="#HANOI">Towers of Hanoi</a></dt>
627
628             <dt>20.4. <a href="#QUEENS">Queens Puzzle</a></dt>
629
630             <dt>20.5. <a href="#SHUFFLE">Shuffle</a></dt>
631
632             <dt>20.6. <a href="#TT">Typing Tutor</a></dt>
633           </dl>
634         </dd>
635
636         <dt>21. <a href="#REF">References</a></dt>
637       </dl>
638     </div>
639
640     <div class="SECT1">
641       <h2 class="SECT1"><a name="INTRO" id="INTRO">1.
642       Introduction</a></h2>
643
644       <p>In the olden days of teletype terminals, terminals were
645       away from computers and were connected to them through serial
646       cables. The terminals could be configured by sending a series
647       of bytes. All the capabilities (such as moving the cursor to
648       a new location, erasing part of the screen, scrolling the
649       screen, changing modes etc.) of terminals could be accessed
650       through these series of bytes. These control seeuqnces are
651       usually called escape sequences, because they start with an
652       escape(0x1B) character. Even today, with proper emulation, we
653       can send escape sequences to the emulator and achieve the
654       same effect on a terminal window.</p>
655
656       <p>Suppose you wanted to print a line in color. Try typing
657       this on your console.</p>
658
659       <pre class="PROGRAMLISTING">
660 echo "^[[0;31;40mIn Color"
661 </pre>
662       <p>The first character is an escape character, which looks
663       like two characters ^ and [. To be able to print it, you have
664       to press CTRL+V and then the ESC key. All the others are
665       normal printable characters. You should be able to see the
666       string "In Color" in red. It stays that way and to revert
667       back to the original mode type this.</p>
668
669       <pre class="PROGRAMLISTING">
670 echo "^[[0;37;40m"
671 </pre>
672       <p>Now, what do these magic characters mean? Difficult to
673       comprehend? They might even be different for different
674       terminals. So the designers of UNIX invented a mechanism
675       named <tt class="LITERAL">termcap</tt>. It is a file that
676       lists all the capabilities of a particular terminal, along
677       with the escape sequences needed to achieve a particular
678       effect. In the later years, this was replaced by <tt class=
679       "LITERAL">terminfo</tt>. Without delving too much into
680       details, this mechanism allows application programs to query
681       the terminfo database and obtain the control characters to be
682       sent to a terminal or terminal emulator.</p>
683
684       <div class="SECT2">
685         <hr>
686
687         <h3 class="SECT2"><a name="WHATIS" id="WHATIS">1.1. What is
688         NCURSES?</a></h3>
689
690         <p>You might be wondering, what the import of all this
691         technical gibberish is. In the above scenario, every
692         application program is supposed to query the terminfo and
693         perform the necessary stuff (sending control characters
694         etc.). It soon became difficult to manage this complexity
695         and this gave birth to 'CURSES'. Curses is a pun on the
696         name "cursor optimization". The Curses library forms a
697         wrapper over working with raw terminal codes, and provides
698         highly flexible and efficient API (Application Programming
699         Interface). It provides functions to move the cursor,
700         create windows, produce colors, play with mouse etc. The
701         application programs need not worry about the underlying
702         terminal capabilities.</p>
703
704         <p>So what is NCURSES? NCURSES is a clone of the original
705         System V Release 4.0 (SVr4) curses. It is a freely
706         distributable library, fully compatible with older version
707         of curses. In short, it is a library of functions that
708         manages an application's display on character-cell
709         terminals. In the remainder of the document, the terms
710         curses and ncurses are used interchangeably.</p>
711
712         <p>A detailed history of NCURSES can be found in the NEWS
713         file from the source distribution. The current package is
714         maintained by <a href="mailto:dickey@his.com" target=
715         "_top">Thomas Dickey</a>. You can contact the maintainers
716         at <a href="mailto:bug-ncurses@gnu.org" target=
717         "_top">bug-ncurses@gnu.org</a>.</p>
718       </div>
719
720       <div class="SECT2">
721         <hr>
722
723         <h3 class="SECT2"><a name="WHATCANWEDO" id=
724         "WHATCANWEDO">1.2. What we can do with NCURSES</a></h3>
725
726         <p>NCURSES not only creates a wrapper over terminal
727         capabilities, but also gives a robust framework to create
728         nice looking UI (User Interface)s in text mode. It provides
729         functions to create windows etc. Its sister libraries
730         panel, menu and form provide an extension to the basic
731         curses library. These libraries usually come along with
732         curses. One can create applications that contain multiple
733         windows, menus, panels and forms. Windows can be managed
734         independently, can provide 'scrollability' and even can be
735         hidden.</p>
736
737         <p>Menus provide the user with an easy command selection
738         option. Forms allow the creation of easy-to-use data entry
739         and display windows. Panels extend the capabilities of
740         ncurses to deal with overlapping and stacked windows.</p>
741
742         <p>These are just some of the basic things we can do with
743         ncurses. As we move along, We will see all the capabilities
744         of these libraries.</p>
745       </div>
746
747       <div class="SECT2">
748         <hr>
749
750         <h3 class="SECT2"><a name="WHERETOGETIT" id=
751         "WHERETOGETIT">1.3. Where to get it</a></h3>
752
753         <p>All right, now that you know what you can do with
754         ncurses, you must be rearing to get started. NCURSES is
755         usually shipped with your installation. In case you don't
756         have the library or want to compile it on your own, read
757         on.</p>
758
759         <p><span class="emphasis"><i class="EMPHASIS">Compiling the
760         package</i></span>
761         </p>
762
763         <p>NCURSES can be obtained from <a href=
764         "ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz" target=
765         "_top">ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</a>
766         or any of the ftp sites mentioned in <a href=
767         "http://www.gnu.org/order/ftp.html" target=
768         "_top">http://www.gnu.org/order/ftp.html</a>.</p>
769
770         <p>Read the README and INSTALL files for details on to how
771         to install it. It usually involves the following
772         operations.</p>
773
774         <pre class="PROGRAMLISTING">
775     tar zxvf ncurses&lt;version&gt;.tar.gz  # unzip and untar the archive
776     cd ncurses&lt;version&gt;               # cd to the directory
777     ./configure                             # configure the build according to your 
778                                             # environment
779     make                                    # make it
780     su root                                 # become root
781     make install                            # install it
782 </pre>
783         <p><span class="emphasis"><i class="EMPHASIS">Using the
784         RPM</i></span>
785         </p>
786
787         <p>NCURSES RPM can be found and downloaded from <a href=
788         "http://rpmfind.net" target="_top">http://rpmfind.net</a> .
789         The RPM can be installed with the following command after
790         becoming root.</p>
791
792         <pre class="PROGRAMLISTING">
793     rpm -i &lt;downloaded rpm&gt;
794 </pre>
795       </div>
796
797       <div class="SECT2">
798         <hr>
799
800         <h3 class="SECT2"><a name="PURPOSE" id="PURPOSE">1.4.
801         Purpose/Scope of the document</a></h3>
802
803         <p>This document is intended to be a "All in One" guide for
804         programming with ncurses and its sister libraries. We
805         graduate from a simple "Hello World" program to more
806         complex form manipulation. No prior experience in ncurses
807         is assumed. The writing is informal, but a lot of detail is
808         provided for each of the examples.</p>
809       </div>
810
811       <div class="SECT2">
812         <hr>
813
814         <h3 class="SECT2"><a name="ABOUTPROGRAMS" id=
815         "ABOUTPROGRAMS">1.5. About the Programs</a></h3>
816
817         <p>All the programs in the document are available in zipped
818         form <a href=
819         "http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz"
820         target="_top">here</a>. Unzip and untar it. The directory
821         structure looks like this.</p>
822
823         <pre class="PROGRAMLISTING">
824 ncurses
825    |
826    |----&gt; JustForFun     -- just for fun programs
827    |----&gt; basics         -- basic programs
828    |----&gt; demo           -- output files go into this directory after make
829    |          |
830    |          |----&gt; exe -- exe files of all example programs
831    |----&gt; forms          -- programs related to form library
832    |----&gt; menus          -- programs related to menus library
833    |----&gt; panels         -- programs related to panels library
834    |----&gt; perl           -- perl equivalents of the examples (contributed
835    |                            by Anuradha Ratnaweera)
836    |----&gt; Makefile       -- the top level Makefile
837    |----&gt; README         -- the top level README file. contains instructions
838    |----&gt; COPYING        -- copyright notice
839 </pre>
840         <p>The individual directories contain the following
841         files.</p>
842
843         <pre class="PROGRAMLISTING">
844 Description of files in each directory
845 --------------------------------------
846 JustForFun
847     |
848     |----&gt; hanoi.c   -- The Towers of Hanoi Solver
849     |----&gt; life.c    -- The Game of Life demo
850     |----&gt; magic.c   -- An Odd Order Magic Square builder 
851     |----&gt; queens.c  -- The famous N-Queens Solver
852     |----&gt; shuffle.c -- A fun game, if you have time to kill
853     |----&gt; tt.c      -- A very trivial typing tutor
854
855   basics
856     |
857     |----&gt; acs_vars.c            -- ACS_ variables example
858     |----&gt; hello_world.c         -- Simple "Hello World" Program
859     |----&gt; init_func_example.c   -- Initialization functions example
860     |----&gt; key_code.c            -- Shows the scan code of the key pressed
861     |----&gt; mouse_menu.c          -- A menu accessible by mouse
862     |----&gt; other_border.c        -- Shows usage of other border functions apa
863     |                               -- rt from box()
864     |----&gt; printw_example.c      -- A very simple printw() example
865     |----&gt; scanw_example.c       -- A very simple getstr() example
866     |----&gt; simple_attr.c         -- A program that can print a c file with 
867     |                               -- comments in attribute
868     |----&gt; simple_color.c        -- A simple example demonstrating colors
869     |----&gt; simple_key.c          -- A menu accessible with keyboard UP, DOWN 
870     |                               -- arrows
871     |----&gt; temp_leave.c          -- Demonstrates temporarily leaving curses mode
872     |----&gt; win_border.c          -- Shows Creation of windows and borders
873     |----&gt; with_chgat.c          -- chgat() usage example
874
875   forms 
876     |
877     |----&gt; form_attrib.c     -- Usage of field attributes
878     |----&gt; form_options.c    -- Usage of field options
879     |----&gt; form_simple.c     -- A simple form example
880     |----&gt; form_win.c        -- Demo of windows associated with forms
881
882   menus 
883     |
884     |----&gt; menu_attrib.c     -- Usage of menu attributes
885     |----&gt; menu_item_data.c  -- Usage of item_name() etc.. functions
886     |----&gt; menu_multi_column.c    -- Creates multi columnar menus
887     |----&gt; menu_scroll.c     -- Demonstrates scrolling capability of menus
888     |----&gt; menu_simple.c     -- A simple menu accessed by arrow keys
889     |----&gt; menu_toggle.c     -- Creates multi valued menus and explains
890     |                           -- REQ_TOGGLE_ITEM
891     |----&gt; menu_userptr.c    -- Usage of user pointer
892     |----&gt; menu_win.c        -- Demo of windows associated with menus
893
894   panels 
895     |
896     |----&gt; panel_browse.c    -- Panel browsing through tab. Usage of user 
897     |                           -- pointer
898     |----&gt; panel_hide.c      -- Hiding and Un hiding of panels
899     |----&gt; panel_resize.c    -- Moving and resizing of panels
900     |----&gt; panel_simple.c    -- A simple panel example
901
902   perl
903     |----&gt; 01-10.pl          -- Perl equivalents of first ten example programs
904 </pre>
905         <p>There is a top level Makefile included in the main
906         directory. It builds all the files and puts the
907         ready-to-use exes in demo/exe directory. You can also do
908         selective make by going into the corresponding directory.
909         Each directory contains a README file explaining the
910         purpose of each c file in the directory.</p>
911
912         <p>For every example, I have included path name for the
913         file relative to the examples directory.</p>
914
915         <p>If you prefer browsing individual programs, point your
916         browser to <a href=
917         "http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/"
918         target=
919         "_top">http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</a></p>
920
921         <p>All the programs are released under the same license
922         that is used by ncurses (MIT-style). This gives you the
923         ability to do pretty much anything other than claiming them
924         as yours. Feel free to use them in your programs as
925         appropriate.</p>
926       </div>
927
928       <div class="SECT2">
929         <hr>
930
931         <h3 class="SECT2"><a name="OTHERFORMATS" id=
932         "OTHERFORMATS">1.6. Other Formats of the document</a></h3>
933
934         <p>This howto is also availabe in various other formats on
935         the tldp.org site. Here are the links to other formats of
936         this document.</p>
937
938         <div class="SECT3">
939           <hr>
940
941           <h4 class="SECT3"><a name="LISTFORMATS" id=
942           "LISTFORMATS">1.6.1. Readily available formats from
943           tldp.org</a></h4>
944
945           <ul>
946             <li>
947               <p><a href=
948               "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf"
949               target="_top">Acrobat PDF Format</a></p>
950             </li>
951
952             <li>
953               <p><a href=
954               "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz"
955               target="_top">PostScript Format</a></p>
956             </li>
957
958             <li>
959               <p><a href=
960               "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz"
961               target="_top">In Multiple HTML pages</a></p>
962             </li>
963
964             <li>
965               <p><a href=
966               "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html"
967               target="_top">In One big HTML format</a></p>
968             </li>
969           </ul>
970         </div>
971
972         <div class="SECT3">
973           <hr>
974
975           <h4 class="SECT3"><a name="BUILDSOURCE" id=
976           "BUILDSOURCE">1.6.2. Building from source</a></h4>
977
978           <p>If above links are broken or if you want to experiment
979           with sgml read on.</p>
980
981           <pre class="PROGRAMLISTING">
982 &#13;    Get both the source and the tar,gzipped programs, available at
983         http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
984         NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml
985         http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
986         NCURSES-HOWTO/ncurses_programs.tar.gz
987
988     Unzip ncurses_programs.tar.gz with
989     tar zxvf ncurses_programs.tar.gz
990
991     Use jade to create various formats. For example if you just want to create
992     the multiple html files, you would use
993         jade -t sgml -i html -d &lt;path to docbook html stylesheet&gt;
994         NCURSES-Programming-HOWTO.sgml
995     to get pdf, first create a single html file of the HOWTO with 
996         jade -t sgml -i html -d &lt;path to docbook html stylesheet&gt; -V nochunks
997         NCURSES-Programming-HOWTO.sgml &gt; NCURSES-ONE-BIG-FILE.html
998     then use htmldoc to get pdf file with
999         htmldoc --size universal -t pdf --firstpage p1 -f &lt;output file name.pdf&gt;
1000         NCURSES-ONE-BIG-FILE.html
1001     for ps, you would use
1002         htmldoc --size universal -t ps --firstpage p1 -f &lt;output file name.ps&gt;
1003         NCURSES-ONE-BIG-FILE.html
1004 </pre>
1005           <p>See <a href=
1006           "http://www.tldp.org/LDP/LDP-Author-Guide/" target=
1007           "_top">LDP Author guide</a> for more details. If all else
1008           failes, mail me at <a href="ppadala@gmail.com" target=
1009           "_top">ppadala@gmail.com</a></p>
1010         </div>
1011       </div>
1012
1013       <div class="SECT2">
1014         <hr>
1015
1016         <h3 class="SECT2"><a name="CREDITS" id="CREDITS">1.7.
1017         Credits</a></h3>
1018
1019         <p>I thank <a href="mailto:sharath_1@usa.net" target=
1020         "_top">Sharath</a> and Emre Akbas for helping me with few
1021         sections. The introduction was initially written by
1022         sharath. I rewrote it with few excerpts taken from his
1023         initial work. Emre helped in writing printw and scanw
1024         sections.</p>
1025
1026         <p>Perl equivalents of the example programs are contributed
1027         by <a href="mailto:Aratnaweera@virtusa.com" target=
1028         "_top">Anuradha Ratnaweera</a>.</p>
1029
1030         <p>Then comes <a href="mailto:parimi@ece.arizona.edu"
1031         target="_top">Ravi Parimi</a>, my dearest friend, who has
1032         been on this project before even one line was written. He
1033         constantly bombarded me with suggestions and patiently
1034         reviewed the whole text. He also checked each program on
1035         Linux and Solaris.</p>
1036       </div>
1037
1038       <div class="SECT2">
1039         <hr>
1040
1041         <h3 class="SECT2"><a name="WISHLIST" id="WISHLIST">1.8.
1042         Wish List</a></h3>
1043
1044         <p>This is the wish list, in the order of priority. If you
1045         have a wish or you want to work on completing the wish,
1046         mail <a href="mailto:ppadala@gmail.com" target=
1047         "_top">me</a>.</p>
1048
1049         <ul>
1050           <li>
1051             <p>Add examples to last parts of forms section.</p>
1052           </li>
1053
1054           <li>
1055             <p>Prepare a Demo showing all the programs and allow
1056             the user to browse through description of each program.
1057             Let the user compile and see the program in action. A
1058             dialog based interface is preferred.</p>
1059           </li>
1060
1061           <li>
1062             <p>Add debug info. _tracef, _tracemouse stuff.</p>
1063           </li>
1064
1065           <li>
1066             <p>Accessing termcap, terminfo using functions provided
1067             by ncurses package.</p>
1068           </li>
1069
1070           <li>
1071             <p>Working on two terminals simultaneously.</p>
1072           </li>
1073
1074           <li>
1075             <p>Add more stuff to miscellaneous section.</p>
1076           </li>
1077         </ul>
1078       </div>
1079
1080       <div class="SECT2">
1081         <hr>
1082
1083         <h3 class="SECT2"><a name="COPYRIGHT" id="COPYRIGHT">1.9.
1084         Copyright</a></h3>
1085
1086         <p>Copyright &copy; 2001 by Pradeep Padala.</p>
1087
1088         <p>Permission is hereby granted, free of charge, to any
1089         person obtaining a copy of this software and associated
1090         documentation files (the "Software"), to deal in the
1091         Software without restriction, including without limitation
1092         the rights to use, copy, modify, merge, publish,
1093         distribute, distribute with modifications, sublicense,
1094         and/or sell copies of the Software, and to permit persons
1095         to whom the Software is furnished to do so, subject to the
1096         following conditions:</p>
1097
1098         <p>The above copyright notice and this permission notice
1099         shall be included in all copies or substantial portions of
1100         the Software.</p>
1101
1102         <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1103         ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
1104         THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1105         PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE
1106         COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1107         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1108         OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1109         SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
1110
1111         <p>Except as contained in this notice, the name(s) of the
1112         above copyright holders shall not be used in advertising or
1113         otherwise to promote the sale, use or other dealings in
1114         this Software without prior written authorization.</p>
1115       </div>
1116     </div>
1117
1118     <div class="SECT1">
1119       <hr>
1120
1121       <h2 class="SECT1"><a name="HELLOWORLD" id="HELLOWORLD">2.
1122       Hello World !!!</a></h2>
1123
1124       <p>Welcome to the world of curses. Before we plunge into the
1125       library and look into its various features, let's write a
1126       simple program and say hello to the world.</p>
1127
1128       <div class="SECT2">
1129         <hr>
1130
1131         <h3 class="SECT2"><a name="COMPILECURSES" id=
1132         "COMPILECURSES">2.1. Compiling With the NCURSES Library</a></h3>
1133
1134         <p>To use ncurses library functions, you have to include
1135         ncurses.h in your programs. To link the program with
1136         ncurses the flag -lncurses should be added.</p>
1137
1138         <pre class="PROGRAMLISTING">
1139     #include &lt;ncurses.h&gt;
1140     .
1141     .
1142     .
1143
1144     compile and link: gcc &lt;program file&gt; -lncurses
1145 </pre>
1146         <div class="EXAMPLE">
1147           <a name="BHW" id="BHW"></a>
1148           <p><b>Example 1. The Hello World !!! Program</b>
1149           </p>
1150
1151           <pre class="PROGRAMLISTING">
1152 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
1153
1154 int main()
1155 {       
1156         initscr();                      /* Start curses mode              */
1157         printw("Hello World !!!");      /* Print Hello World              */
1158         refresh();                      /* Print it on to the real screen */
1159         getch();                        /* Wait for user input */
1160         endwin();                       /* End curses mode                */
1161
1162         return 0;
1163 }</span>
1164 </pre>
1165         </div>
1166       </div>
1167
1168       <div class="SECT2">
1169         <hr>
1170
1171         <h3 class="SECT2"><a name="DISSECTION" id="DISSECTION">2.2.
1172         Dissection</a></h3>
1173
1174         <p>The above program prints "Hello World !!!" to the screen
1175         and exits. This program shows how to initialize curses and
1176         do screen manipulation and end curses mode. Let's dissect
1177         it line by line.</p>
1178
1179         <div class="SECT3">
1180           <hr>
1181
1182           <h4 class="SECT3"><a name="ABOUT-INITSCR" id=
1183           "ABOUT-INITSCR">2.2.1. About initscr()</a></h4>
1184
1185           <p>The function initscr() initializes the terminal in
1186           curses mode. In some implementations, it clears the
1187           screen and presents a blank screen. To do any screen
1188           manipulation using curses package this has to be called
1189           first. This function initializes the curses system and
1190           allocates memory for our present window (called
1191           <tt class="LITERAL">stdscr</tt>) and some other
1192           data-structures. Under extreme cases this function might
1193           fail due to insufficient memory to allocate memory for
1194           curses library's data structures.</p>
1195
1196           <p>After this is done, we can do a variety of
1197           initializations to customize our curses settings. These
1198           details will be explained <a href="#INIT">later</a> .</p>
1199         </div>
1200
1201         <div class="SECT3">
1202           <hr>
1203
1204           <h4 class="SECT3"><a name="MYST-REFRESH" id=
1205           "MYST-REFRESH">2.2.2. The mysterious refresh()</a></h4>
1206
1207           <p>The next line printw prints the string "Hello World
1208           !!!" on to the screen. This function is analogous to
1209           normal printf in all respects except that it prints the
1210           data on a window called stdscr at the current (y,x)
1211           co-ordinates. Since our present co-ordinates are at 0,0
1212           the string is printed at the left hand corner of the
1213           window.</p>
1214
1215           <p>This brings us to that mysterious refresh(). Well,
1216           when we called printw the data is actually written to an
1217           imaginary window, which is not updated on the screen yet.
1218           The job of printw is to update a few flags and data
1219           structures and write the data to a buffer corresponding
1220           to stdscr. In order to show it on the screen, we need to
1221           call refresh() and tell the curses system to dump the
1222           contents on the screen.</p>
1223
1224           <p>The philosophy behind all this is to allow the
1225           programmer to do multiple updates on the imaginary screen
1226           or windows and do a refresh once all his screen update is
1227           done. refresh() checks the window and updates only the
1228           portion which has been changed. This improves performance
1229           and offers greater flexibility too. But, it is sometimes
1230           frustrating to beginners. A common mistake committed by
1231           beginners is to forget to call refresh() after they did
1232           some update through printw() class of functions. I still
1233           forget to add it sometimes :-)</p>
1234         </div>
1235
1236         <div class="SECT3">
1237           <hr>
1238
1239           <h4 class="SECT3"><a name="ABOUT-ENDWIN" id=
1240           "ABOUT-ENDWIN">2.2.3. About endwin()</a></h4>
1241
1242           <p>And finally don't forget to end the curses mode.
1243           Otherwise your terminal might behave strangely after the
1244           program quits. endwin() frees the memory taken by curses
1245           sub-system and its data structures and puts the terminal
1246           in normal mode. This function must be called after you
1247           are done with the curses mode.</p>
1248         </div>
1249       </div>
1250     </div>
1251
1252     <div class="SECT1">
1253       <hr>
1254
1255       <h2 class="SECT1"><a name="GORY" id="GORY">3. The Gory
1256       Details</a></h2>
1257
1258       <p>Now that we have seen how to write a simple curses program
1259       let's get into the details. There are many functions that
1260       help customize what you see on screen and many features which
1261       can be put to full use.</p>
1262
1263       <p>Here we go...</p>
1264     </div>
1265
1266     <div class="SECT1">
1267       <hr>
1268
1269       <h2 class="SECT1"><a name="INIT" id="INIT">4.
1270       Initialization</a></h2>
1271
1272       <p>We now know that to initialize curses system the function
1273       initscr() has to be called. There are functions which can be
1274       called after this initialization to customize our curses
1275       session. We may ask the curses system to set the terminal in
1276       raw mode or initialize color or initialize the mouse etc..
1277       Let's discuss some of the functions that are normally called
1278       immediately after initscr();</p>
1279
1280       <div class="SECT2">
1281         <hr>
1282
1283         <h3 class="SECT2"><a name="ABOUTINIT" id="ABOUTINIT">4.1.
1284         Initialization functions</a></h3>
1285       </div>
1286
1287       <div class="SECT2">
1288         <hr>
1289
1290         <h3 class="SECT2"><a name="RAWCBREAK" id="RAWCBREAK">4.2.
1291         raw() and cbreak()</a></h3>
1292
1293         <p>Normally the terminal driver buffers the characters a
1294         user types until a new line or carriage return is
1295         encountered. But most programs require that the characters
1296         be available as soon as the user types them. The above two
1297         functions are used to disable line buffering. The
1298         difference between these two functions is in the way
1299         control characters like suspend (CTRL-Z), interrupt and
1300         quit (CTRL-C) are passed to the program. In the raw() mode
1301         these characters are directly passed to the program without
1302         generating a signal. In the <tt class=
1303         "LITERAL">cbreak()</tt> mode these control characters are
1304         interpreted as any other character by the terminal driver.
1305         I personally prefer to use raw() as I can exercise greater
1306         control over what the user does.</p>
1307       </div>
1308
1309       <div class="SECT2">
1310         <hr>
1311
1312         <h3 class="SECT2"><a name="ECHONOECHO" id="ECHONOECHO">4.3.
1313         echo() and noecho()</a></h3>
1314
1315         <p>These functions control the echoing of characters typed
1316         by the user to the terminal. <tt class=
1317         "LITERAL">noecho()</tt> switches off echoing. The reason
1318         you might want to do this is to gain more control over
1319         echoing or to suppress unnecessary echoing while taking
1320         input from the user through the getch() etc. functions.
1321         Most of the interactive programs call <tt class=
1322         "LITERAL">noecho()</tt> at initialization and do the
1323         echoing of characters in a controlled manner. It gives the
1324         programmer the flexibility of echoing characters at any
1325         place in the window without updating current (y,x)
1326         co-ordinates.</p>
1327       </div>
1328
1329       <div class="SECT2">
1330         <hr>
1331
1332         <h3 class="SECT2"><a name="KEYPAD" id="KEYPAD">4.4.
1333         keypad()</a></h3>
1334
1335         <p>This is my favorite initialization function. It enables
1336         the reading of function keys like F1, F2, arrow keys etc.
1337         Almost every interactive program enables this, as arrow
1338         keys are a major part of any User Interface. Do <tt class=
1339         "LITERAL">keypad(stdscr, TRUE)</tt> to enable this feature
1340         for the regular screen (stdscr). You will learn more about
1341         key management in later sections of this document.</p>
1342       </div>
1343
1344       <div class="SECT2">
1345         <hr>
1346
1347         <h3 class="SECT2"><a name="HALFDELAY" id="HALFDELAY">4.5.
1348         halfdelay()</a></h3>
1349
1350         <p>This function, though not used very often, is a useful
1351         one at times. halfdelay()is called to enable the half-delay
1352         mode, which is similar to the cbreak() mode in that
1353         characters typed are immediately available to program.
1354         However, it waits for 'X' tenths of a second for input and
1355         then returns ERR, if no input is available. 'X' is the
1356         timeout value passed to the function halfdelay(). This
1357         function is useful when you want to ask the user for input,
1358         and if he doesn't respond with in certain time, we can do
1359         some thing else. One possible example is a timeout at the
1360         password prompt.</p>
1361       </div>
1362
1363       <div class="SECT2">
1364         <hr>
1365
1366         <h3 class="SECT2"><a name="MISCINIT" id="MISCINIT">4.6.
1367         Miscellaneous Initialization functions</a></h3>
1368
1369         <p>There are few more functions which are called at
1370         initialization to customize curses behavior. They are not
1371         used as extensively as those mentioned above. Some of them
1372         are explained where appropriate.</p>
1373       </div>
1374
1375       <div class="SECT2">
1376         <hr>
1377
1378         <h3 class="SECT2"><a name="INITEX" id="INITEX">4.7. An
1379         Example</a></h3>
1380
1381         <p>Let's write a program which will clarify the usage of
1382         these functions.</p>
1383
1384         <div class="EXAMPLE">
1385           <a name="BINFU" id="BINFU"></a>
1386           <p><b>Example 2. Initialization Function Usage
1387           example</b>
1388           </p>
1389
1390           <pre class="PROGRAMLISTING">
1391 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
1392
1393 int main()
1394 {       int ch;
1395
1396         initscr();                      /* Start curses mode            */
1397         raw();                          /* Line buffering disabled      */
1398         keypad(stdscr, TRUE);           /* We get F1, F2 etc..          */
1399         noecho();                       /* Don't echo() while we do getch */
1400
1401         printw("Type any character to see it in bold\n");
1402         ch = getch();                   /* If raw() hadn't been called
1403                                          * we have to press enter before it
1404                                          * gets to the program          */
1405         if(ch == KEY_F(1))              /* Without keypad enabled this will */
1406                 printw("F1 Key pressed");/*  not get to us either       */
1407                                         /* Without noecho() some ugly escape
1408                                          * charachters might have been printed
1409                                          * on screen                    */
1410         else
1411         {       printw("The pressed key is ");
1412                 attron(A_BOLD);
1413                 printw("%c", ch);
1414                 attroff(A_BOLD);
1415         }
1416         refresh();                      /* Print it on to the real screen */
1417         getch();                        /* Wait for user input */
1418         endwin();                       /* End curses mode                */
1419
1420         return 0;
1421 }</span>
1422 </pre>
1423         </div>
1424
1425         <p>This program is self-explanatory. But I used functions
1426         which aren't explained yet. The function <tt class=
1427         "LITERAL">getch()</tt> is used to get a character from
1428         user. It is equivalent to normal <tt class=
1429         "LITERAL">getchar()</tt> except that we can disable the
1430         line buffering to avoid &lt;enter&gt; after input. Look for
1431         more about <tt class="LITERAL">getch()</tt>and reading keys
1432         in the <a href="#KEYS">key management section</a> . The
1433         functions attron and attroff are used to switch some
1434         attributes on and off respectively. In the example I used
1435         them to print the character in bold. These functions are
1436         explained in detail later.</p>
1437       </div>
1438     </div>
1439
1440     <div class="SECT1">
1441       <hr>
1442
1443       <h2 class="SECT1"><a name="AWORDWINDOWS" id="AWORDWINDOWS">5.
1444       A Word about Windows</a></h2>
1445
1446       <p>Before we plunge into the myriad ncurses functions, let me
1447       clear few things about windows. Windows are explained in
1448       detail in following <a href="#WINDOWS">sections</a></p>
1449
1450       <p>A Window is an imaginary screen defined by curses system.
1451       A window does not mean a bordered window which you usually
1452       see on Win9X platforms. When curses is initialized, it
1453       creates a default window named <tt class=
1454       "LITERAL">stdscr</tt> which represents your 80x25 (or the
1455       size of window in which you are running) screen. If you are
1456       doing simple tasks like printing few strings, reading input
1457       etc., you can safely use this single window for all of your
1458       purposes. You can also create windows and call functions
1459       which explicitly work on the specified window.</p>
1460
1461       <p>For example, if you call</p>
1462
1463       <pre class="PROGRAMLISTING">
1464     printw("Hi There !!!");
1465     refresh();
1466 </pre>
1467       <p>It prints the string on stdscr at the present cursor
1468       position. Similarly the call to refresh(), works on stdscr
1469       only.</p>
1470
1471       <p>Say you have created <a href="#WINDOWS">windows</a> then
1472       you have to call a function with a 'w' added to the usual
1473       function.</p>
1474
1475       <pre class="PROGRAMLISTING">
1476     wprintw(win, "Hi There !!!");
1477     wrefresh(win);
1478 </pre>
1479       <p>As you will see in the rest of the document, naming of
1480       functions follow the same convention. For each function there
1481       usually are three more functions.</p>
1482
1483       <pre class="PROGRAMLISTING">
1484     printw(string);        /* Print on stdscr at present cursor position */
1485     mvprintw(y, x, string);/* Move to (y, x) then print string     */
1486     wprintw(win, string);  /* Print on window win at present cursor position */
1487                            /* in the window */
1488     mvwprintw(win, y, x, string);   /* Move to (y, x) relative to window */
1489                                     /* co-ordinates and then print         */
1490 </pre>
1491       <p>Usually the w-less functions are macros which expand to
1492       corresponding w-function with stdscr as the window
1493       parameter.</p>
1494     </div>
1495
1496     <div class="SECT1">
1497       <hr>
1498
1499       <h2 class="SECT1"><a name="PRINTW" id="PRINTW">6. Output
1500       functions</a></h2>
1501
1502       <p>I guess you can't wait any more to see some action. Back
1503       to our odyssey of curses functions. Now that curses is
1504       initialized, let's interact with world.</p>
1505
1506       <p>There are three classes of functions which you can use to
1507       do output on screen.</p>
1508
1509       <ol type="1">
1510         <li>
1511           <p>addch() class: Print single character with
1512           attributes</p>
1513         </li>
1514
1515         <li>
1516           <p>printw() class: Print formatted output similar to
1517           printf()</p>
1518         </li>
1519
1520         <li>
1521           <p>addstr() class: Print strings</p>
1522         </li>
1523       </ol>
1524
1525       <p>These functions can be used interchangeably and it is a
1526       matter of style as to which class is used. Let's see each one
1527       in detail.</p>
1528
1529       <div class="SECT2">
1530         <hr>
1531
1532         <h3 class="SECT2"><a name="ADDCHCLASS" id="ADDCHCLASS">6.1.
1533         addch() class of functions</a></h3>
1534
1535         <p>These functions put a single character into the current
1536         cursor location and advance the position of the cursor. You
1537         can give the character to be printed but they usually are
1538         used to print a character with some attributes. Attributes
1539         are explained in detail in later <a href=
1540         "#ATTRIB">sections</a> of the document. If a character is
1541         associated with an attribute(bold, reverse video etc.),
1542         when curses prints the character, it is printed in that
1543         attribute.</p>
1544
1545         <p>In order to combine a character with some attributes,
1546         you have two options:</p>
1547
1548         <ul>
1549           <li>
1550             <p>By OR'ing a single character with the desired
1551             attribute macros. These attribute macros could be found
1552             in the header file <tt class="LITERAL">ncurses.h</tt>.
1553             For example, you want to print a character ch(of type
1554             char) bold and underlined, you would call addch() as
1555             below.</p>
1556
1557             <pre class="PROGRAMLISTING">
1558     addch(ch | A_BOLD | A_UNDERLINE);
1559 </pre>
1560           </li>
1561
1562           <li>
1563             <p>By using functions like <tt class=
1564             "LITERAL">attrset(),attron(),attroff()</tt>. These
1565             functions are explained in the <a href=
1566             "#ATTRIB">Attributes</a> section. Briefly, they
1567             manipulate the current attributes of the given window.
1568             Once set, the character printed in the window are
1569             associated with the attributes until it is turned
1570             off.</p>
1571           </li>
1572         </ul>
1573
1574         <p>Additionally, <tt class="LITERAL">curses</tt> provides
1575         some special characters for character-based graphics. You
1576         can draw tables, horizontal or vertical lines, etc. You can
1577         find all avaliable characters in the header file <tt class=
1578         "LITERAL">ncurses.h</tt>. Try looking for macros beginning
1579         with <tt class="LITERAL">ACS_</tt> in this file.</p>
1580       </div>
1581
1582       <div class="SECT2">
1583         <hr>
1584
1585         <h3 class="SECT2"><a name="AEN298" id="AEN298">6.2.
1586         mvaddch(), waddch() and mvwaddch()</a></h3>
1587
1588         <p><tt class="LITERAL">mvaddch()</tt> is used to move the
1589         cursor to a given point, and then print. Thus, the
1590         calls:</p>
1591
1592         <pre class="PROGRAMLISTING">
1593     move(row,col);    /* moves the cursor to row<span class=
1594 "emphasis"><i class=
1595 "EMPHASIS">th</i></span> row and col<span class="emphasis"><i class="EMPHASIS">th</i></span> column */
1596     addch(ch);
1597 </pre>can be replaced by
1598
1599         <pre class="PROGRAMLISTING">
1600     mvaddch(row,col,ch);
1601 </pre>
1602         <p><tt class="LITERAL">waddch()</tt> is similar to
1603         <tt class="LITERAL">addch()</tt>, except that it adds a
1604         character into the given window. (Note that <tt class=
1605         "LITERAL">addch()</tt> adds a character into the window
1606         <tt class="LITERAL">stdscr</tt>.)</p>
1607
1608         <p>In a similar fashion <tt class="LITERAL">mvwaddch()</tt>
1609         function is used to add a character into the given window
1610         at the given coordinates.</p>
1611
1612         <p>Now, we are familiar with the basic output function
1613         <tt class="LITERAL">addch()</tt>. But, if we want to print
1614         a string, it would be very annoying to print it character
1615         by character. Fortunately, <tt class="LITERAL">ncurses</tt>
1616         provides <tt class="LITERAL">printf</tt><span class=
1617         "emphasis"><i class="EMPHASIS">-like</i></span> or
1618         <tt class="LITERAL">puts</tt><span class=
1619         "emphasis"><i class="EMPHASIS">-like</i></span>
1620         functions.</p>
1621       </div>
1622
1623       <div class="SECT2">
1624         <hr>
1625
1626         <h3 class="SECT2"><a name="PRINTWCLASS" id=
1627         "PRINTWCLASS">6.3. printw() class of functions</a></h3>
1628
1629         <p>These functions are similar to <tt class=
1630         "LITERAL">printf()</tt> with the added capability of
1631         printing at any position on the screen.</p>
1632
1633         <div class="SECT3">
1634           <hr>
1635
1636           <h4 class="SECT3"><a name="PRINTWMVPRINTW" id=
1637           "PRINTWMVPRINTW">6.3.1. printw() and mvprintw</a></h4>
1638
1639           <p>These two functions work much like <tt class=
1640           "LITERAL">printf()</tt>. <tt class=
1641           "LITERAL">mvprintw()</tt> can be used to move the cursor
1642           to a position and then print. If you want to move the
1643           cursor first and then print using <tt class=
1644           "LITERAL">printw()</tt> function, use <tt class=
1645           "LITERAL">move()</tt> first and then use <tt class=
1646           "LITERAL">printw()</tt> though I see no point why one
1647           should avoid using <tt class="LITERAL">mvprintw()</tt>,
1648           you have the flexibility to manipulate.</p>
1649         </div>
1650
1651         <div class="SECT3">
1652           <hr>
1653
1654           <h4 class="SECT3"><a name="WPRINTWMVWPRINTW" id=
1655           "WPRINTWMVWPRINTW">6.3.2. wprintw() and mvwprintw</a></h4>
1656
1657           <p>These two functions are similar to above two except
1658           that they print in the corresponding window given as
1659           argument.</p>
1660         </div>
1661
1662         <div class="SECT3">
1663           <hr>
1664
1665           <h4 class="SECT3"><a name="VWPRINTW" id="VWPRINTW">6.3.3.
1666           vw_printw()</a></h4>
1667
1668           <p>This function is similar to <tt class=
1669           "LITERAL">vprintf()</tt>. This can be used when variable
1670           number of arguments are to be printed.</p>
1671         </div>
1672
1673         <div class="SECT3">
1674           <hr>
1675
1676           <h4 class="SECT3"><a name="SIMPLEPRINTWEX" id=
1677           "SIMPLEPRINTWEX">6.3.4. A Simple printw example</a></h4>
1678
1679           <div class="EXAMPLE">
1680             <a name="BPREX" id="BPREX"></a>
1681             <p><b>Example 3. A Simple printw example</b>
1682             </p>
1683
1684             <pre class="PROGRAMLISTING">
1685 <span class=
1686 "INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;                   /* ncurses.h includes stdio.h */  
1687 #include &lt;string.h&gt; 
1688  
1689 int main()
1690 {
1691  char mesg[]="Just a string";           /* message to be appeared on the screen */
1692  int row,col;                           /* to store the number of rows and *
1693                                          * the number of colums of the screen */
1694  initscr();                             /* start the curses mode */
1695  getmaxyx(stdscr,row,col);              /* get the number of rows and columns */
1696  mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
1697                                         /* print the message at the center of the screen */
1698  mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col);
1699  printw("Try resizing your window(if possible) and then run this program again");
1700  refresh();
1701  getch();
1702  endwin();
1703
1704  return 0;
1705 }</span>
1706 </pre>
1707           </div>
1708
1709           <p>Above program demonstrates how easy it is to use
1710           <tt class="LITERAL">printw</tt>. You just feed the
1711           coordinates and the message to be appeared on the screen,
1712           then it does what you want.</p>
1713
1714           <p>The above program introduces us to a new function
1715           <tt class="LITERAL">getmaxyx()</tt>, a macro defined in
1716           <tt class="LITERAL">ncurses.h</tt>. It gives the number
1717           of columns and the number of rows in a given window.
1718           <tt class="LITERAL">getmaxyx()</tt> does this by updating
1719           the variables given to it. Since <tt class=
1720           "LITERAL">getmaxyx()</tt> is not a function we don't pass
1721           pointers to it, we just give two integer variables.</p>
1722         </div>
1723       </div>
1724
1725       <div class="SECT2">
1726         <hr>
1727
1728         <h3 class="SECT2"><a name="ADDSTRCLASS" id=
1729         "ADDSTRCLASS">6.4. addstr() class of functions</a></h3>
1730
1731         <p><tt class="LITERAL">addstr()</tt> is used to put a
1732         character string into a given window. This function is
1733         similar to calling <tt class="LITERAL">addch()</tt> once
1734         for each character in a given string. This is true for all
1735         output functions. There are other functions from this
1736         family such as <tt class=
1737         "LITERAL">mvaddstr(),mvwaddstr()</tt> and <tt class=
1738         "LITERAL">waddstr()</tt>, which obey the naming convention
1739         of curses.(e.g. mvaddstr() is similar to the respective
1740         calls move() and then addstr().) Another function of this
1741         family is addnstr(), which takes an integer parameter(say
1742         n) additionally. This function puts at most n characters
1743         into the screen. If n is negative, then the entire string
1744         will be added.</p>
1745       </div>
1746
1747       <div class="SECT2">
1748         <hr>
1749
1750         <h3 class="SECT2"><a name="ACAUTION" id="ACAUTION">6.5. A
1751         word of caution</a></h3>
1752
1753         <p>All these functions take y co-ordinate first and then x
1754         in their arguments. A common mistake by beginners is to
1755         pass x,y in that order. If you are doing too many
1756         manipulations of (y,x) co-ordinates, think of dividing the
1757         screen into windows and manipulate each one separately.
1758         Windows are explained in the <a href="#WINDOWS">windows</a>
1759         section.</p>
1760       </div>
1761     </div>
1762
1763     <div class="SECT1">
1764       <hr>
1765
1766       <h2 class="SECT1"><a name="SCANW" id="SCANW">7. Input
1767       functions</a></h2>
1768
1769       <p>Well, printing without taking input, is boring. Let's see
1770       functions which allow us to get input from user. These
1771       functions also can be divided into three categories.</p>
1772
1773       <ol type="1">
1774         <li>
1775           <p>getch() class: Get a character</p>
1776         </li>
1777
1778         <li>
1779           <p>scanw() class: Get formatted input</p>
1780         </li>
1781
1782         <li>
1783           <p>getstr() class: Get strings</p>
1784         </li>
1785       </ol>
1786
1787       <div class="SECT2">
1788         <hr>
1789
1790         <h3 class="SECT2"><a name="GETCHCLASS" id="GETCHCLASS">7.1.
1791         getch() class of functions</a></h3>
1792
1793         <p>These functions read a single character from the
1794         terminal. But there are several subtle facts to consider.
1795         For example if you don't use the function cbreak(), curses
1796         will not read your input characters contiguously but will
1797         begin read them only after a new line or an EOF is
1798         encountered. In order to avoid this, the cbreak() function
1799         must used so that characters are immediately available to
1800         your program. Another widely used function is noecho(). As
1801         the name suggests, when this function is set (used), the
1802         characters that are keyed in by the user will not show up
1803         on the screen. The two functions cbreak() and noecho() are
1804         typical examples of key management. Functions of this genre
1805         are explained in the <a href="#KEYS">key management
1806         section</a> .</p>
1807       </div>
1808
1809       <div class="SECT2">
1810         <hr>
1811
1812         <h3 class="SECT2"><a name="SCANWCLASS" id="SCANWCLASS">7.2.
1813         scanw() class of functions</a></h3>
1814
1815         <p>These functions are similar to <tt class=
1816         "LITERAL">scanf()</tt> with the added capability of getting
1817         the input from any location on the screen.</p>
1818
1819         <div class="SECT3">
1820           <hr>
1821
1822           <h4 class="SECT3"><a name="SCANWMVSCANW" id=
1823           "SCANWMVSCANW">7.2.1. scanw() and mvscanw</a></h4>
1824
1825           <p>The usage of these functions is similar to that of
1826           <tt class="LITERAL">sscanf()</tt>, where the line to be
1827           scanned is provided by <tt class="LITERAL">wgetstr()</tt>
1828           function. That is, these functions call to <tt class=
1829           "LITERAL">wgetstr()</tt> function(explained below) and
1830           uses the resulting line for a scan.</p>
1831         </div>
1832
1833         <div class="SECT3">
1834           <hr>
1835
1836           <h4 class="SECT3"><a name="WSCANWMVWSCANW" id=
1837           "WSCANWMVWSCANW">7.2.2. wscanw() and mvwscanw()</a></h4>
1838
1839           <p>These are similar to above two functions except that
1840           they read from a window, which is supplied as one of the
1841           arguments to these functions.</p>
1842         </div>
1843
1844         <div class="SECT3">
1845           <hr>
1846
1847           <h4 class="SECT3"><a name="VWSCANW" id="VWSCANW">7.2.3.
1848           vw_scanw()</a></h4>
1849
1850           <p>This function is similar to <tt class=
1851           "LITERAL">vscanf()</tt>. This can be used when a variable
1852           number of arguments are to be scanned.</p>
1853         </div>
1854       </div>
1855
1856       <div class="SECT2">
1857         <hr>
1858
1859         <h3 class="SECT2"><a name="GETSTRCLASS" id=
1860         "GETSTRCLASS">7.3. getstr() class of functions</a></h3>
1861
1862         <p>These functions are used to get strings from the
1863         terminal. In essence, this function performs the same task
1864         as would be achieved by a series of calls to <tt class=
1865         "LITERAL">getch()</tt> until a newline, carriage return, or
1866         end-of-file is received. The resulting string of characters
1867         are pointed to by <tt class="LITERAL">str</tt>, which is a
1868         character pointer provided by the user.</p>
1869       </div>
1870
1871       <div class="SECT2">
1872         <hr>
1873
1874         <h3 class="SECT2"><a name="GETSTREX" id="GETSTREX">7.4.
1875         Some examples</a></h3>
1876
1877         <div class="EXAMPLE">
1878           <a name="BSCEX" id="BSCEX"></a>
1879           <p><b>Example 4. A Simple scanw example</b>
1880           </p>
1881
1882           <pre class="PROGRAMLISTING">
1883 <span class=
1884 "INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;                   /* ncurses.h includes stdio.h */  
1885 #include &lt;string.h&gt; 
1886  
1887 int main()
1888 {
1889  char mesg[]="Enter a string: ";                /* message to be appeared on the screen */
1890  char str[80];
1891  int row,col;                           /* to store the number of rows and *
1892                                          * the number of colums of the screen */
1893  initscr();                             /* start the curses mode */
1894  getmaxyx(stdscr,row,col);              /* get the number of rows and columns */
1895  mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
1896                                 /* print the message at the center of the screen */
1897  getstr(str);
1898  mvprintw(LINES - 2, 0, "You Entered: %s", str);
1899  getch();
1900  endwin();
1901
1902  return 0;
1903 }</span>
1904 </pre>
1905         </div>
1906       </div>
1907     </div>
1908
1909     <div class="SECT1">
1910       <hr>
1911
1912       <h2 class="SECT1"><a name="ATTRIB" id="ATTRIB">8.
1913       Attributes</a></h2>
1914
1915       <p>We have seen an example of how attributes can be used to
1916       print characters with some special effects. Attributes, when
1917       set prudently, can present information in an easy,
1918       understandable manner. The following program takes a C file
1919       as input and prints the file with comments in bold. Scan
1920       through the code.</p>
1921
1922       <div class="EXAMPLE">
1923         <a name="BSIAT" id="BSIAT"></a>
1924         <p><b>Example 5. A Simple Attributes example</b>
1925         </p>
1926
1927         <pre class="PROGRAMLISTING">
1928 <span class=
1929 "INLINEMEDIAOBJECT">/* pager functionality by Joseph Spainhour" &lt;spainhou@bellsouth.net&gt; */
1930 #include &lt;ncurses.h&gt;
1931 #include &lt;stdlib.h&gt;
1932
1933 int main(int argc, char *argv[])
1934
1935   int ch, prev, row, col;
1936   prev = EOF;
1937   FILE *fp;
1938   int y, x;
1939
1940   if(argc != 2)
1941   {
1942     printf("Usage: %s &lt;a c file name&gt;\n", argv[0]);
1943     exit(1);
1944   }
1945   fp = fopen(argv[1], "r");
1946   if(fp == NULL)
1947   {
1948     perror("Cannot open input file");
1949     exit(1);
1950   }
1951   initscr();                            /* Start curses mode */
1952   getmaxyx(stdscr, row, col);           /* find the boundaries of the screeen */
1953   while((ch = fgetc(fp)) != EOF)        /* read the file till we reach the end */
1954   {
1955     getyx(stdscr, y, x);                /* get the current curser position */
1956     if(y == (row - 1))                  /* are we are at the end of the screen */
1957     {
1958       printw("&lt;-Press Any Key-&gt;");      /* tell the user to press a key */
1959       getch();
1960       clear();                          /* clear the screen */
1961       move(0, 0);                       /* start at the beginning of the screen */
1962     }
1963     if(prev == '/' &amp;&amp; ch == '*')        /* If it is / and * then only
1964                                          * switch bold on */    
1965     {
1966       attron(A_BOLD);                   /* cut bold on */
1967       getyx(stdscr, y, x);              /* get the current curser position */
1968       move(y, x - 1);                   /* back up one space */
1969       printw("%c%c", '/', ch);          /* The actual printing is done here */
1970     }
1971     else
1972       printw("%c", ch);
1973     refresh();
1974     if(prev == '*' &amp;&amp; ch == '/')
1975       attroff(A_BOLD);                  /* Switch it off once we got *
1976                                          * and then / */
1977     prev = ch;
1978   }
1979   endwin();                             /* End curses mode */
1980   fclose(fp);
1981   return 0;
1982 }</span>
1983 </pre>
1984       </div>
1985
1986       <p>Don't worry about all those initialization and other crap.
1987       Concentrate on the while loop. It reads each character in the
1988       file and searches for the pattern /*. Once it spots the
1989       pattern, it switches the BOLD attribute on with <tt class=
1990       "LITERAL">attron()</tt> . When we get the pattern */ it is
1991       switched off by <tt class="LITERAL">attroff()</tt> .</p>
1992
1993       <p>The above program also introduces us to two useful
1994       functions <tt class="LITERAL">getyx()</tt> and <tt class=
1995       "LITERAL">move()</tt>. The first function gets the
1996       co-ordinates of the present cursor into the variables y, x.
1997       Since getyx() is a macro we don't have to pass pointers to
1998       variables. The function <tt class="LITERAL">move()</tt> moves
1999       the cursor to the co-ordinates given to it.</p>
2000
2001       <p>The above program is really a simple one which doesn't do
2002       much. On these lines one could write a more useful program
2003       which reads a C file, parses it and prints it in different
2004       colors. One could even extend it to other languages as
2005       well.</p>
2006
2007       <div class="SECT2">
2008         <hr>
2009
2010         <h3 class="SECT2"><a name="ATTRIBDETAILS" id=
2011         "ATTRIBDETAILS">8.1. The details</a></h3>
2012
2013         <p>Let's get into more details of attributes. The functions
2014         <tt class="LITERAL">attron(), attroff(), attrset()</tt> ,
2015         and their sister functions <tt class=
2016         "LITERAL">attr_get()</tt> etc.. can be used to switch
2017         attributes on/off , get attributes and produce a colorful
2018         display.</p>
2019
2020         <p>The functions attron and attroff take a bit-mask of
2021         attributes and switch them on or off, respectively. The
2022         following video attributes, which are defined in
2023         &lt;curses.h&gt; can be passed to these functions.</p>
2024
2025         <pre class="PROGRAMLISTING">
2026     
2027     A_NORMAL        Normal display (no highlight)
2028     A_STANDOUT      Best highlighting mode of the terminal.
2029     A_UNDERLINE     Underlining
2030     A_REVERSE       Reverse video
2031     A_BLINK         Blinking
2032     A_DIM           Half bright
2033     A_BOLD          Extra bright or bold
2034     A_PROTECT       Protected mode
2035     A_INVIS         Invisible or blank mode
2036     A_ALTCHARSET    Alternate character set
2037     A_CHARTEXT      Bit-mask to extract a character
2038     COLOR_PAIR(n)   Color-pair number n 
2039     
2040 </pre>
2041         <p>The last one is the most colorful one :-) Colors are
2042         explained in the <a href="#color" target="_top">next
2043         sections</a>.</p>
2044
2045         <p>We can OR(|) any number of above attributes to get a
2046         combined effect. If you wanted reverse video with blinking
2047         characters you can use</p>
2048
2049         <pre class="PROGRAMLISTING">
2050     attron(A_REVERSE | A_BLINK);
2051 </pre>
2052       </div>
2053
2054       <div class="SECT2">
2055         <hr>
2056
2057         <h3 class="SECT2"><a name="ATTRONVSATTRSET" id=
2058         "ATTRONVSATTRSET">8.2. attron() vs attrset()</a></h3>
2059
2060         <p>Then what is the difference between attron() and
2061         attrset()? attrset sets the attributes of window whereas
2062         attron just switches on the attribute given to it. So
2063         attrset() fully overrides whatever attributes the window
2064         previously had and sets it to the new attribute(s).
2065         Similarly attroff() just switches off the attribute(s)
2066         given to it as an argument. This gives us the flexibility
2067         of managing attributes easily.But if you use them
2068         carelessly you may loose track of what attributes the
2069         window has and garble the display. This is especially true
2070         while managing menus with colors and highlighting. So
2071         decide on a consistent policy and stick to it. You can
2072         always use <tt class="LITERAL">standend()</tt> which is
2073         equivalent to <tt class="LITERAL">attrset(A_NORMAL)</tt>
2074         which turns off all attributes and brings you to normal
2075         mode.</p>
2076       </div>
2077
2078       <div class="SECT2">
2079         <hr>
2080
2081         <h3 class="SECT2"><a name="ATTRGET" id="ATTRGET">8.3.
2082         attr_get()</a></h3>
2083
2084         <p>The function attr_get() gets the current attributes and
2085         color pair of the window. Though we might not use this as
2086         often as the above functions, this is useful in scanning
2087         areas of screen. Say we wanted to do some complex update on
2088         screen and we are not sure what attribute each character is
2089         associated with. Then this function can be used with either
2090         attrset or attron to produce the desired effect.</p>
2091       </div>
2092
2093       <div class="SECT2">
2094         <hr>
2095
2096         <h3 class="SECT2"><a name="ATTRFUNCS" id="ATTRFUNCS">8.4.
2097         attr_ functions</a></h3>
2098
2099         <p>There are series of functions like attr_set(), attr_on
2100         etc.. These are similar to above functions except that they
2101         take parameters of type <tt class=
2102         "LITERAL">attr_t</tt>.</p>
2103       </div>
2104
2105       <div class="SECT2">
2106         <hr>
2107
2108         <h3 class="SECT2"><a name="WATTRFUNCS" id="WATTRFUNCS">8.5.
2109         wattr functions</a></h3>
2110
2111         <p>For each of the above functions we have a corresponding
2112         function with 'w' which operates on a particular window.
2113         The above functions operate on stdscr.</p>
2114       </div>
2115
2116       <div class="SECT2">
2117         <hr>
2118
2119         <h3 class="SECT2"><a name="CHGAT" id="CHGAT">8.6. chgat()
2120         functions</a></h3>
2121
2122         <p>The function chgat() is listed in the end of the man
2123         page curs_attr. It actually is a useful one. This function
2124         can be used to set attributes for a group of characters
2125         without moving. I mean it !!! without moving the cursor :-)
2126         It changes the attributes of a given number of characters
2127         starting at the current cursor location.</p>
2128
2129         <p>We can give -1 as the character count to update till end
2130         of line. If you want to change attributes of characters
2131         from current position to end of line, just use this.</p>
2132
2133         <pre class="PROGRAMLISTING">
2134     chgat(-1, A_REVERSE, 0, NULL);
2135 </pre>
2136         <p>This function is useful when changing attributes for
2137         characters that are already on the screen. Move to the
2138         character from which you want to change and change the
2139         attribute.</p>
2140
2141         <p>Other functions wchgat(), mvchgat(), wchgat() behave
2142         similarly except that the w functions operate on the
2143         particular window. The mv functions first move the cursor
2144         then perform the work given to them. Actually chgat is a
2145         macro which is replaced by a wchgat() with stdscr as the
2146         window. Most of the "w-less" functions are macros.</p>
2147
2148         <div class="EXAMPLE">
2149           <a name="BWICH" id="BWICH"></a>
2150           <p><b>Example 6. Chgat() Usage example</b>
2151           </p>
2152
2153           <pre class="PROGRAMLISTING">
2154 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2155
2156 int main(int argc, char *argv[])
2157 {       initscr();                      /* Start curses mode            */
2158         start_color();                  /* Start color functionality    */
2159         
2160         init_pair(1, COLOR_CYAN, COLOR_BLACK);
2161         printw("A Big string which i didn't care to type fully ");
2162         mvchgat(0, 0, -1, A_BLINK, 1, NULL);    
2163         /* 
2164          * First two parameters specify the position at which to start 
2165          * Third parameter number of characters to update. -1 means till 
2166          * end of line
2167          * Forth parameter is the normal attribute you wanted to give 
2168          * to the charcter
2169          * Fifth is the color index. It is the index given during init_pair()
2170          * use 0 if you didn't want color
2171          * Sixth one is always NULL 
2172          */
2173         refresh();
2174         getch();
2175         endwin();                       /* End curses mode                */
2176         return 0;
2177 }</span>
2178 </pre>
2179         </div>
2180
2181         <p>This example also introduces us to the color world of
2182         curses. Colors will be explained in detail later. Use 0 for
2183         no color.</p>
2184       </div>
2185     </div>
2186
2187     <div class="SECT1">
2188       <hr>
2189
2190       <h2 class="SECT1"><a name="WINDOWS" id="WINDOWS">9.
2191       Windows</a></h2>
2192
2193       <p>Windows form the most important concept in curses. You
2194       have seen the standard window stdscr above where all the
2195       functions implicitly operated on this window. Now to make
2196       design even a simplest GUI, you need to resort to windows.
2197       The main reason you may want to use windows is to manipulate
2198       parts of the screen separately, for better efficiency, by
2199       updating only the windows that need to be changed and for a
2200       better design. I would say the last reason is the most
2201       important in going for windows. You should always strive for
2202       a better and easy-to-manage design in your programs. If you
2203       are writing big, complex GUIs this is of pivotal importance
2204       before you start doing anything.</p>
2205
2206       <div class="SECT2">
2207         <hr>
2208
2209         <h3 class="SECT2"><a name="WINDOWBASICS" id=
2210         "WINDOWBASICS">9.1. The basics</a></h3>
2211
2212         <p>A Window can be created by calling the function
2213         <tt class="LITERAL">newwin()</tt>. It doesn't create any
2214         thing on the screen actually. It allocates memory for a
2215         structure to manipulate the window and updates the
2216         structure with data regarding the window such as its size,
2217         beginy, beginx etc. Hence in curses, a window is just an
2218         abstraction of an imaginary window, which can be
2219         manipulated independent of other parts of screen. The
2220         function newwin() returns a pointer to structure WINDOW,
2221         which can be passed to window related functions like
2222         wprintw() etc.. Finally the window can be destroyed with
2223         delwin(). It will deallocate the memory associated with the
2224         window structure.</p>
2225       </div>
2226
2227       <div class="SECT2">
2228         <hr>
2229
2230         <h3 class="SECT2"><a name="LETBEWINDOW" id=
2231         "LETBEWINDOW">9.2. Let there be a Window !!!</a></h3>
2232
2233         <p>What fun is it, if a window is created and we can't see
2234         it. So the fun part begins by displaying the window. The
2235         function <tt class="LITERAL">box()</tt> can be used to draw
2236         a border around the window. Let's explore these functions
2237         in more detail in this example.</p>
2238
2239         <div class="EXAMPLE">
2240           <a name="BWIBO" id="BWIBO"></a>
2241           <p><b>Example 7. Window Border example</b>
2242           </p>
2243
2244           <pre class="PROGRAMLISTING">
2245 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2246
2247 WINDOW *create_newwin(int height, int width, int starty, int startx);
2248 void destroy_win(WINDOW *local_win);
2249
2250 int main(int argc, char *argv[])
2251 {       WINDOW *my_win;
2252         int startx, starty, width, height;
2253         int ch;
2254
2255         initscr();                      /* Start curses mode            */
2256         cbreak();                       /* Line buffering disabled, Pass on
2257                                          * everty thing to me           */
2258         keypad(stdscr, TRUE);           /* I need that nifty F1         */
2259
2260         height = 3;
2261         width = 10;
2262         starty = (LINES - height) / 2;  /* Calculating for a center placement */
2263         startx = (COLS - width) / 2;    /* of the window                */
2264         printw("Press F1 to exit");
2265         refresh();
2266         my_win = create_newwin(height, width, starty, startx);
2267
2268         while((ch = getch()) != KEY_F(1))
2269         {       switch(ch)
2270                 {       case KEY_LEFT:
2271                                 destroy_win(my_win);
2272                                 my_win = create_newwin(height, width, starty,--startx);
2273                                 break;
2274                         case KEY_RIGHT:
2275                                 destroy_win(my_win);
2276                                 my_win = create_newwin(height, width, starty,++startx);
2277                                 break;
2278                         case KEY_UP:
2279                                 destroy_win(my_win);
2280                                 my_win = create_newwin(height, width, --starty,startx);
2281                                 break;
2282                         case KEY_DOWN:
2283                                 destroy_win(my_win);
2284                                 my_win = create_newwin(height, width, ++starty,startx);
2285                                 break;  
2286                 }
2287         }
2288                 
2289         endwin();                       /* End curses mode                */
2290         return 0;
2291 }
2292
2293 WINDOW *create_newwin(int height, int width, int starty, int startx)
2294 {       WINDOW *local_win;
2295
2296         local_win = newwin(height, width, starty, startx);
2297         box(local_win, 0 , 0);          /* 0, 0 gives default characters 
2298                                          * for the vertical and horizontal
2299                                          * lines                        */
2300         wrefresh(local_win);            /* Show that box                */
2301
2302         return local_win;
2303 }
2304
2305 void destroy_win(WINDOW *local_win)
2306 {       
2307         /* box(local_win, ' ', ' '); : This won't produce the desired
2308          * result of erasing the window. It will leave its four corners 
2309          * and so an ugly remnant of window. 
2310          */
2311         wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
2312         /* The parameters taken are 
2313          * 1. win: the window on which to operate
2314          * 2. ls: character to be used for the left side of the window 
2315          * 3. rs: character to be used for the right side of the window 
2316          * 4. ts: character to be used for the top side of the window 
2317          * 5. bs: character to be used for the bottom side of the window 
2318          * 6. tl: character to be used for the top left corner of the window 
2319          * 7. tr: character to be used for the top right corner of the window 
2320          * 8. bl: character to be used for the bottom left corner of the window 
2321          * 9. br: character to be used for the bottom right corner of the window
2322          */
2323         wrefresh(local_win);
2324         delwin(local_win);
2325 }</span>
2326 </pre>
2327         </div>
2328       </div>
2329
2330       <div class="SECT2">
2331         <hr>
2332
2333         <h3 class="SECT2"><a name="BORDEREXEXPL" id=
2334         "BORDEREXEXPL">9.3. Explanation</a></h3>
2335
2336         <p>Don't scream. I know it is a big example. But I have to
2337         explain some important things here :-). This program
2338         creates a rectangular window that can be moved with left,
2339         right, up, down arrow keys. It repeatedly creates and
2340         destroys windows as user press a key. Don't go beyond the
2341         screen limits. Checking for those limits is left as an
2342         exercise for the reader. Let's dissect it by line by
2343         line.</p>
2344
2345         <p>The <tt class="LITERAL">create_newwin()</tt> function
2346         creates a window with <tt class="LITERAL">newwin()</tt> and
2347         displays a border around it with box. The function
2348         <tt class="LITERAL">destroy_win()</tt> first erases the
2349         window from screen by painting a border with ' ' character
2350         and then calling <tt class="LITERAL">delwin()</tt> to
2351         deallocate memory related to it. Depending on the key the
2352         user presses, starty or startx is changed and a new window
2353         is created.</p>
2354
2355         <p>In the destroy_win, as you can see, I used wborder
2356         instead of box. The reason is written in the comments (You
2357         missed it. I know. Read the code :-)). wborder draws a
2358         border around the window with the characters given to it as
2359         the 4 corner points and the 4 lines. To put it clearly, if
2360         you have called wborder as below:</p>
2361
2362         <pre class="PROGRAMLISTING">
2363     wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
2364 </pre>
2365         <p>it produces some thing like</p>
2366
2367         <pre class="PROGRAMLISTING">
2368     +------------+
2369     |            |
2370     |            |
2371     |            |
2372     |            |
2373     |            |
2374     |            |
2375     +------------+
2376 </pre>
2377       </div>
2378
2379       <div class="SECT2">
2380         <hr>
2381
2382         <h3 class="SECT2"><a name="OTHERSTUFF" id="OTHERSTUFF">9.4.
2383         The other stuff in the example</a></h3>
2384
2385         <p>You can also see in the above examples, that I have used
2386         the variables COLS, LINES which are initialized to the
2387         screen sizes after initscr(). They can be useful in finding
2388         screen dimensions and finding the center co-ordinate of the
2389         screen as above. The function <tt class=
2390         "LITERAL">getch()</tt> as usual gets the key from keyboard
2391         and according to the key it does the corresponding work.
2392         This type of switch- case is very common in any GUI based
2393         programs.</p>
2394       </div>
2395
2396       <div class="SECT2">
2397         <hr>
2398
2399         <h3 class="SECT2"><a name="OTHERBORDERFUNCS" id=
2400         "OTHERBORDERFUNCS">9.5. Other Border functions</a></h3>
2401
2402         <p>Above program is grossly inefficient in that with each
2403         press of a key, a window is destroyed and another is
2404         created. So let's write a more efficient program which uses
2405         other border related functions.</p>
2406
2407         <p>The following program uses <tt class=
2408         "LITERAL">mvhline()</tt> and <tt class=
2409         "LITERAL">mvvline()</tt> to achieve similar effect. These
2410         two functions are simple. They create a horizontal or
2411         vertical line of the specified length at the specified
2412         position.</p>
2413
2414         <div class="EXAMPLE">
2415           <a name="BOTBO" id="BOTBO"></a>
2416           <p><b>Example 8. More border functions</b>
2417           </p>
2418
2419           <pre class="PROGRAMLISTING">
2420 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2421
2422 typedef struct _win_border_struct {
2423         chtype  ls, rs, ts, bs, 
2424                 tl, tr, bl, br;
2425 }WIN_BORDER;
2426
2427 typedef struct _WIN_struct {
2428
2429         int startx, starty;
2430         int height, width;
2431         WIN_BORDER border;
2432 }WIN;
2433
2434 void init_win_params(WIN *p_win);
2435 void print_win_params(WIN *p_win);
2436 void create_box(WIN *win, bool flag);
2437
2438 int main(int argc, char *argv[])
2439 {       WIN win;
2440         int ch;
2441
2442         initscr();                      /* Start curses mode            */
2443         start_color();                  /* Start the color functionality */
2444         cbreak();                       /* Line buffering disabled, Pass on
2445                                          * everty thing to me           */
2446         keypad(stdscr, TRUE);           /* I need that nifty F1         */
2447         noecho();
2448         init_pair(1, COLOR_CYAN, COLOR_BLACK);
2449
2450         /* Initialize the window parameters */
2451         init_win_params(&amp;win);
2452         print_win_params(&amp;win);
2453
2454         attron(COLOR_PAIR(1));
2455         printw("Press F1 to exit");
2456         refresh();
2457         attroff(COLOR_PAIR(1));
2458         
2459         create_box(&amp;win, TRUE);
2460         while((ch = getch()) != KEY_F(1))
2461         {       switch(ch)
2462                 {       case KEY_LEFT:
2463                                 create_box(&amp;win, FALSE);
2464                                 --win.startx;
2465                                 create_box(&amp;win, TRUE);
2466                                 break;
2467                         case KEY_RIGHT:
2468                                 create_box(&amp;win, FALSE);
2469                                 ++win.startx;
2470                                 create_box(&amp;win, TRUE);
2471                                 break;
2472                         case KEY_UP:
2473                                 create_box(&amp;win, FALSE);
2474                                 --win.starty;
2475                                 create_box(&amp;win, TRUE);
2476                                 break;
2477                         case KEY_DOWN:
2478                                 create_box(&amp;win, FALSE);
2479                                 ++win.starty;
2480                                 create_box(&amp;win, TRUE);
2481                                 break;  
2482                 }
2483         }
2484         endwin();                       /* End curses mode                */
2485         return 0;
2486 }
2487 void init_win_params(WIN *p_win)
2488 {
2489         p_win-&gt;height = 3;
2490         p_win-&gt;width = 10;
2491         p_win-&gt;starty = (LINES - p_win-&gt;height)/2;      
2492         p_win-&gt;startx = (COLS - p_win-&gt;width)/2;
2493
2494         p_win-&gt;border.ls = '|';
2495         p_win-&gt;border.rs = '|';
2496         p_win-&gt;border.ts = '-';
2497         p_win-&gt;border.bs = '-';
2498         p_win-&gt;border.tl = '+';
2499         p_win-&gt;border.tr = '+';
2500         p_win-&gt;border.bl = '+';
2501         p_win-&gt;border.br = '+';
2502
2503 }
2504 void print_win_params(WIN *p_win)
2505 {
2506 #ifdef _DEBUG
2507         mvprintw(25, 0, "%d %d %d %d", p_win-&gt;startx, p_win-&gt;starty, 
2508                                 p_win-&gt;width, p_win-&gt;height);
2509         refresh();
2510 #endif
2511 }
2512 void create_box(WIN *p_win, bool flag)
2513 {       int i, j;
2514         int x, y, w, h;
2515
2516         x = p_win-&gt;startx;
2517         y = p_win-&gt;starty;
2518         w = p_win-&gt;width;
2519         h = p_win-&gt;height;
2520
2521         if(flag == TRUE)
2522         {       mvaddch(y, x, p_win-&gt;border.tl);
2523                 mvaddch(y, x + w, p_win-&gt;border.tr);
2524                 mvaddch(y + h, x, p_win-&gt;border.bl);
2525                 mvaddch(y + h, x + w, p_win-&gt;border.br);
2526                 mvhline(y, x + 1, p_win-&gt;border.ts, w - 1);
2527                 mvhline(y + h, x + 1, p_win-&gt;border.bs, w - 1);
2528                 mvvline(y + 1, x, p_win-&gt;border.ls, h - 1);
2529                 mvvline(y + 1, x + w, p_win-&gt;border.rs, h - 1);
2530
2531         }
2532         else
2533                 for(j = y; j &lt;= y + h; ++j)
2534                         for(i = x; i &lt;= x + w; ++i)
2535                                 mvaddch(j, i, ' ');
2536                                 
2537         refresh();
2538
2539 }</span>
2540 </pre>
2541         </div>
2542       </div>
2543     </div>
2544
2545     <div class="SECT1">
2546       <hr>
2547
2548       <h2 class="SECT1"><a name="COLOR" id="COLOR">10. Colors</a></h2>
2549
2550       <div class="SECT2">
2551         <h3 class="SECT2"><a name="COLORBASICS" id=
2552         "COLORBASICS">10.1. The basics</a></h3>
2553
2554         <p>Life seems dull with no colors. Curses has a nice
2555         mechanism to handle colors. Let's get into the thick of the
2556         things with a small program.</p>
2557
2558         <div class="EXAMPLE">
2559           <a name="BSICO" id="BSICO"></a>
2560           <p><b>Example 9. A Simple Color example</b>
2561           </p>
2562
2563           <pre class="PROGRAMLISTING">
2564 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2565
2566 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
2567 int main(int argc, char *argv[])
2568 {       initscr();                      /* Start curses mode            */
2569         if(has_colors() == FALSE)
2570         {       endwin();
2571                 printf("Your terminal does not support color\n");
2572                 exit(1);
2573         }
2574         start_color();                  /* Start color                  */
2575         init_pair(1, COLOR_RED, COLOR_BLACK);
2576
2577         attron(COLOR_PAIR(1));
2578         print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ...");
2579         attroff(COLOR_PAIR(1));
2580         getch();
2581         endwin();
2582 }
2583 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string)
2584 {       int length, x, y;
2585         float temp;
2586
2587         if(win == NULL)
2588                 win = stdscr;
2589         getyx(win, y, x);
2590         if(startx != 0)
2591                 x = startx;
2592         if(starty != 0)
2593                 y = starty;
2594         if(width == 0)
2595                 width = 80;
2596
2597         length = strlen(string);
2598         temp = (width - length)/ 2;
2599         x = startx + (int)temp;
2600         mvwprintw(win, y, x, "%s", string);
2601         refresh();
2602 }
2603 </span>
2604 </pre>
2605         </div>
2606
2607         <p>As you can see, to start using color, you should first
2608         call the function <tt class="LITERAL">start_color()</tt>.
2609         After that, you can use color capabilities of your
2610         terminals using various functions. To find out whether a
2611         terminal has color capabilities or not, you can use
2612         <tt class="LITERAL">has_colors()</tt> function, which
2613         returns FALSE if the terminal does not support color.</p>
2614
2615         <p>Curses initializes all the colors supported by terminal
2616         when start_color() is called. These can be accessed by the
2617         define constants like <tt class="LITERAL">COLOR_BLACK</tt>
2618         etc. Now to actually start using colors, you have to define
2619         pairs. Colors are always used in pairs. That means you have
2620         to use the function <tt class="LITERAL">init_pair()</tt> to
2621         define the foreground and background for the pair number
2622         you give. After that that pair number can be used as a
2623         normal attribute with <tt class=
2624         "LITERAL">COLOR_PAIR()</tt>function. This may seem to be
2625         cumbersome at first. But this elegant solution allows us to
2626         manage color pairs very easily. To appreciate it, you have
2627         to look into the the source code of "dialog", a utility for
2628         displaying dialog boxes from shell scripts. The developers
2629         have defined foreground and background combinations for all
2630         the colors they might need and initialized at the
2631         beginning. This makes it very easy to set attributes just
2632         by accessing a pair which we already have defined as a
2633         constant.</p>
2634
2635         <p>The following colors are defined in <tt class=
2636         "LITERAL">curses.h</tt>. You can use these as parameters
2637         for various color functions.</p>
2638
2639         <pre class="PROGRAMLISTING">
2640         COLOR_BLACK   0
2641         COLOR_RED     1
2642         COLOR_GREEN   2
2643         COLOR_YELLOW  3
2644         COLOR_BLUE    4
2645         COLOR_MAGENTA 5
2646         COLOR_CYAN    6
2647         COLOR_WHITE   7
2648 </pre>
2649       </div>
2650
2651       <div class="SECT2">
2652         <hr>
2653
2654         <h3 class="SECT2"><a name="CHANGECOLORDEFS" id=
2655         "CHANGECOLORDEFS">10.2. Changing Color Definitions</a></h3>
2656
2657         <p>The function <tt class="LITERAL">init_color()</tt>can be
2658         used to change the rgb values for the colors defined by
2659         curses initially. Say you wanted to lighten the intensity
2660         of red color by a minuscule. Then you can use this function
2661         as</p>
2662
2663         <pre class="PROGRAMLISTING">
2664     init_color(COLOR_RED, 700, 0, 0);
2665     /* param 1     : color name
2666      * param 2, 3, 4 : rgb content min = 0, max = 1000 */
2667 </pre>
2668         <p>If your terminal cannot change the color definitions,
2669         the function returns ERR. The function <tt class=
2670         "LITERAL">can_change_color()</tt> can be used to find out
2671         whether the terminal has the capability of changing color
2672         content or not. The rgb content is scaled from 0 to 1000.
2673         Initially RED color is defined with content 1000(r), 0(g),
2674         0(b).</p>
2675       </div>
2676
2677       <div class="SECT2">
2678         <hr>
2679
2680         <h3 class="SECT2"><a name="COLORCONTENT" id=
2681         "COLORCONTENT">10.3. Color Content</a></h3>
2682
2683         <p>The functions <tt class="LITERAL">color_content()</tt>
2684         and <tt class="LITERAL">pair_content()</tt> can be used to
2685         find the color content and foreground, background
2686         combination for the pair.</p>
2687       </div>
2688     </div>
2689
2690     <div class="SECT1">
2691       <hr>
2692
2693       <h2 class="SECT1"><a name="KEYS" id="KEYS">11. Interfacing
2694       with the key board</a></h2>
2695
2696       <div class="SECT2">
2697         <h3 class="SECT2"><a name="KEYSBASICS" id=
2698         "KEYSBASICS">11.1. The Basics</a></h3>
2699
2700         <p>No GUI is complete without a strong user interface and
2701         to interact with the user, a curses program should be
2702         sensitive to key presses or the mouse actions done by the
2703         user. Let's deal with the keys first.</p>
2704
2705         <p>As you have seen in almost all of the above examples, it
2706         is very easy to get key input from the user. A simple way
2707         of getting key presses is to use <tt class=
2708         "LITERAL">getch()</tt> function. The cbreak mode should be
2709         enabled to read keys when you are interested in reading
2710         individual key hits rather than complete lines of text
2711         (which usually end with a carriage return). keypad should
2712         be enabled to get the Functions keys, arrow keys etc. See
2713         the initialization section for details.</p>
2714
2715         <p><tt class="LITERAL">getch()</tt> returns an integer
2716         corresponding to the key pressed. If it is a normal
2717         character, the integer value will be equivalent to the
2718         character. Otherwise it returns a number which can be
2719         matched with the constants defined in <tt class=
2720         "LITERAL">curses.h</tt>. For example if the user presses
2721         F1, the integer returned is 265. This can be checked using
2722         the macro KEY_F() defined in curses.h. This makes reading
2723         keys portable and easy to manage.</p>
2724
2725         <p>For example, if you call getch() like this</p>
2726
2727         <pre class="PROGRAMLISTING">
2728     int ch;
2729
2730     ch = getch();
2731 </pre>
2732         <p>getch() will wait for the user to press a key, (unless
2733         you specified a timeout) and when user presses a key, the
2734         corresponding integer is returned. Then you can check the
2735         value returned with the constants defined in curses.h to
2736         match against the keys you want.</p>
2737
2738         <p>The following code piece will do that job.</p>
2739
2740         <pre class="PROGRAMLISTING">
2741     if(ch == KEY_LEFT)
2742         printw("Left arrow is pressed\n");
2743 </pre>
2744         <p>Let's write a small program which creates a menu which
2745         can be navigated by up and down arrows.</p>
2746       </div>
2747
2748       <div class="SECT2">
2749         <hr>
2750
2751         <h3 class="SECT2"><a name="SIMPLEKEYEX" id=
2752         "SIMPLEKEYEX">11.2. A Simple Key Usage example</a></h3>
2753
2754         <div class="EXAMPLE">
2755           <a name="BSIKE" id="BSIKE"></a>
2756           <p><b>Example 10. A Simple Key Usage example</b>
2757           </p>
2758
2759           <pre class="PROGRAMLISTING">
2760 <span class="INLINEMEDIAOBJECT">#include &lt;stdio.h&gt;
2761 #include &lt;ncurses.h&gt;
2762
2763 #define WIDTH 30
2764 #define HEIGHT 10 
2765
2766 int startx = 0;
2767 int starty = 0;
2768
2769 char *choices[] = { 
2770                         "Choice 1",
2771                         "Choice 2",
2772                         "Choice 3",
2773                         "Choice 4",
2774                         "Exit",
2775                   };
2776 int n_choices = sizeof(choices) / sizeof(char *);
2777 void print_menu(WINDOW *menu_win, int highlight);
2778
2779 int main()
2780 {       WINDOW *menu_win;
2781         int highlight = 1;
2782         int choice = 0;
2783         int c;
2784
2785         initscr();
2786         clear();
2787         noecho();
2788         cbreak();       /* Line buffering disabled. pass on everything */
2789         startx = (80 - WIDTH) / 2;
2790         starty = (24 - HEIGHT) / 2;
2791                 
2792         menu_win = newwin(HEIGHT, WIDTH, starty, startx);
2793         keypad(menu_win, TRUE);
2794         mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
2795         refresh();
2796         print_menu(menu_win, highlight);
2797         while(1)
2798         {       c = wgetch(menu_win);
2799                 switch(c)
2800                 {       case KEY_UP:
2801                                 if(highlight == 1)
2802                                         highlight = n_choices;
2803                                 else
2804                                         --highlight;
2805                                 break;
2806                         case KEY_DOWN:
2807                                 if(highlight == n_choices)
2808                                         highlight = 1;
2809                                 else 
2810                                         ++highlight;
2811                                 break;
2812                         case 10:
2813                                 choice = highlight;
2814                                 break;
2815                         default:
2816                                 mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
2817                                 refresh();
2818                                 break;
2819                 }
2820                 print_menu(menu_win, highlight);
2821                 if(choice != 0) /* User did a choice come out of the infinite loop */
2822                         break;
2823         }       
2824         mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]);
2825         clrtoeol();
2826         refresh();
2827         endwin();
2828         return 0;
2829 }
2830
2831 void print_menu(WINDOW *menu_win, int highlight)
2832 {
2833         int x, y, i;    
2834
2835         x = 2;
2836         y = 2;
2837         box(menu_win, 0, 0);
2838         for(i = 0; i &lt; n_choices; ++i)
2839         {       if(highlight == i + 1) /* High light the present choice */
2840                 {       wattron(menu_win, A_REVERSE); 
2841                         mvwprintw(menu_win, y, x, "%s", choices[i]);
2842                         wattroff(menu_win, A_REVERSE);
2843                 }
2844                 else
2845                         mvwprintw(menu_win, y, x, "%s", choices[i]);
2846                 ++y;
2847         }
2848         wrefresh(menu_win);
2849 }
2850 </span>
2851 </pre>
2852         </div>
2853       </div>
2854     </div>
2855
2856     <div class="SECT1">
2857       <hr>
2858
2859       <h2 class="SECT1"><a name="MOUSE" id="MOUSE">12. Interfacing
2860       with the mouse</a></h2>
2861
2862       <p>Now that you have seen how to get keys, lets do the same
2863       thing from mouse. Usually each UI allows the user to interact
2864       with both keyboard and mouse.</p>
2865
2866       <div class="SECT2">
2867         <hr>
2868
2869         <h3 class="SECT2"><a name="MOUSEBASICS" id=
2870         "MOUSEBASICS">12.1. The Basics</a></h3>
2871
2872         <p>Before you do any thing else, the events you want to
2873         receive have to be enabled with <tt class=
2874         "LITERAL">mousemask()</tt>.</p>
2875
2876         <pre class="PROGRAMLISTING">
2877     mousemask(  mmask_t newmask,    /* The events you want to listen to */
2878                 mmask_t *oldmask)    /* The old events mask                */
2879 </pre>
2880         <p>The first parameter to above function is a bit mask of
2881         events you would like to listen. By default, all the events
2882         are turned off. The bit mask <tt class=
2883         "LITERAL">ALL_MOUSE_EVENTS</tt> can be used to get all the
2884         events.</p>
2885
2886         <p>The following are all the event masks:</p>
2887
2888         <pre class="PROGRAMLISTING">
2889     Name            Description
2890        ---------------------------------------------------------------------
2891        BUTTON1_PRESSED          mouse button 1 down
2892        BUTTON1_RELEASED         mouse button 1 up
2893        BUTTON1_CLICKED          mouse button 1 clicked
2894        BUTTON1_DOUBLE_CLICKED   mouse button 1 double clicked
2895        BUTTON1_TRIPLE_CLICKED   mouse button 1 triple clicked
2896        BUTTON2_PRESSED          mouse button 2 down
2897        BUTTON2_RELEASED         mouse button 2 up
2898        BUTTON2_CLICKED          mouse button 2 clicked
2899        BUTTON2_DOUBLE_CLICKED   mouse button 2 double clicked
2900        BUTTON2_TRIPLE_CLICKED   mouse button 2 triple clicked
2901        BUTTON3_PRESSED          mouse button 3 down
2902        BUTTON3_RELEASED         mouse button 3 up
2903        BUTTON3_CLICKED          mouse button 3 clicked
2904        BUTTON3_DOUBLE_CLICKED   mouse button 3 double clicked
2905        BUTTON3_TRIPLE_CLICKED   mouse button 3 triple clicked
2906        BUTTON4_PRESSED          mouse button 4 down
2907        BUTTON4_RELEASED         mouse button 4 up
2908        BUTTON4_CLICKED          mouse button 4 clicked
2909        BUTTON4_DOUBLE_CLICKED   mouse button 4 double clicked
2910        BUTTON4_TRIPLE_CLICKED   mouse button 4 triple clicked
2911        BUTTON_SHIFT             shift was down during button state change
2912        BUTTON_CTRL              control was down during button state change
2913        BUTTON_ALT               alt was down during button state change
2914        ALL_MOUSE_EVENTS         report all button state changes
2915        REPORT_MOUSE_POSITION    report mouse movement
2916 </pre>
2917       </div>
2918
2919       <div class="SECT2">
2920         <hr>
2921
2922         <h3 class="SECT2"><a name="GETTINGEVENTS" id=
2923         "GETTINGEVENTS">12.2. Getting the events</a></h3>
2924
2925         <p>Once a class of mouse events have been enabled, getch()
2926         class of functions return KEY_MOUSE every time some mouse
2927         event happens. Then the mouse event can be retrieved with
2928         <tt class="LITERAL">getmouse()</tt>.</p>
2929
2930         <p>The code approximately looks like this:</p>
2931
2932         <pre class="PROGRAMLISTING">
2933     MEVENT event;
2934
2935     ch = getch();
2936     if(ch == KEY_MOUSE)
2937         if(getmouse(&amp;event) == OK)
2938             .    /* Do some thing with the event */
2939             .
2940             .
2941 </pre>
2942         <p>getmouse() returns the event into the pointer given to
2943         it. It is a structure which contains</p>
2944
2945         <pre class="PROGRAMLISTING">
2946     typedef struct
2947     {
2948         short id;         /* ID to distinguish multiple devices */
2949         int x, y, z;      /* event coordinates */
2950         mmask_t bstate;   /* button state bits */
2951     }    
2952 </pre>
2953         <p>The <tt class="LITERAL">bstate</tt> is the main variable
2954         we are interested in. It tells the button state of the
2955         mouse.</p>
2956
2957         <p>Then with a code snippet like the following, we can find
2958         out what happened.</p>
2959
2960         <pre class="PROGRAMLISTING">
2961     if(event.bstate &amp; BUTTON1_PRESSED)
2962         printw("Left Button Pressed");
2963 </pre>
2964       </div>
2965
2966       <div class="SECT2">
2967         <hr>
2968
2969         <h3 class="SECT2"><a name="MOUSETOGETHER" id=
2970         "MOUSETOGETHER">12.3. Putting it all Together</a></h3>
2971
2972         <p>That's pretty much interfacing with mouse. Let's create
2973         the same menu and enable mouse interaction. To make things
2974         simpler, key handling is removed.</p>
2975
2976         <div class="EXAMPLE">
2977           <a name="BMOME" id="BMOME"></a>
2978           <p><b>Example 11. Access the menu with mouse !!!</b>
2979           </p>
2980
2981           <pre class="PROGRAMLISTING">
2982 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2983
2984 #define WIDTH 30
2985 #define HEIGHT 10 
2986
2987 int startx = 0;
2988 int starty = 0;
2989
2990 char *choices[] = {     "Choice 1",
2991                         "Choice 2",
2992                         "Choice 3",
2993                         "Choice 4",
2994                         "Exit",
2995                   };
2996
2997 int n_choices = sizeof(choices) / sizeof(char *);
2998
2999 void print_menu(WINDOW *menu_win, int highlight);
3000 void report_choice(int mouse_x, int mouse_y, int *p_choice);
3001
3002 int main()
3003 {       int c, choice = 0;
3004         WINDOW *menu_win;
3005         MEVENT event;
3006
3007         /* Initialize curses */
3008         initscr();
3009         clear();
3010         noecho();
3011         cbreak();       //Line buffering disabled. pass on everything
3012
3013         /* Try to put the window in the middle of screen */
3014         startx = (80 - WIDTH) / 2;
3015         starty = (24 - HEIGHT) / 2;
3016         
3017         attron(A_REVERSE);
3018         mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
3019         refresh();
3020         attroff(A_REVERSE);
3021
3022         /* Print the menu for the first time */
3023         menu_win = newwin(HEIGHT, WIDTH, starty, startx);
3024         print_menu(menu_win, 1);
3025         /* Get all the mouse events */
3026         mousemask(ALL_MOUSE_EVENTS, NULL);
3027         
3028         while(1)
3029         {       c = wgetch(menu_win);
3030                 switch(c)
3031                 {       case KEY_MOUSE:
3032                         if(getmouse(&amp;event) == OK)
3033                         {       /* When the user clicks left mouse button */
3034                                 if(event.bstate &amp; BUTTON1_PRESSED)
3035                                 {       report_choice(event.x + 1, event.y + 1, &amp;choice);
3036                                         if(choice == -1) //Exit chosen
3037                                                 goto end;
3038                                         mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
3039                                         refresh(); 
3040                                 }
3041                         }
3042                         print_menu(menu_win, choice);
3043                         break;
3044                 }
3045         }               
3046 end:
3047         endwin();
3048         return 0;
3049 }
3050
3051 void print_menu(WINDOW *menu_win, int highlight)
3052 {
3053         int x, y, i;    
3054
3055         x = 2;
3056         y = 2;
3057         box(menu_win, 0, 0);
3058         for(i = 0; i &lt; n_choices; ++i)
3059         {       if(highlight == i + 1)
3060                 {       wattron(menu_win, A_REVERSE); 
3061                         mvwprintw(menu_win, y, x, "%s", choices[i]);
3062                         wattroff(menu_win, A_REVERSE);
3063                 }
3064                 else
3065                         mvwprintw(menu_win, y, x, "%s", choices[i]);
3066                 ++y;
3067         }
3068         wrefresh(menu_win);
3069 }
3070
3071 /* Report the choice according to mouse position */
3072 void report_choice(int mouse_x, int mouse_y, int *p_choice)
3073 {       int i,j, choice;
3074
3075         i = startx + 2;
3076         j = starty + 3;
3077         
3078         for(choice = 0; choice &lt; n_choices; ++choice)
3079                 if(mouse_y == j + choice &amp;&amp; mouse_x &gt;= i &amp;&amp; mouse_x &lt;= i + strlen(choices[choice]))
3080                 {       if(choice == n_choices - 1)
3081                                 *p_choice = -1;         
3082                         else
3083                                 *p_choice = choice + 1; 
3084                         break;
3085                 }
3086 }</span>
3087 </pre>
3088         </div>
3089       </div>
3090
3091       <div class="SECT2">
3092         <hr>
3093
3094         <h3 class="SECT2"><a name="MISCMOUSEFUNCS" id=
3095         "MISCMOUSEFUNCS">12.4. Miscellaneous Functions</a></h3>
3096
3097         <p>The functions mouse_trafo() and wmouse_trafo() can be
3098         used to convert to mouse co-ordinates to screen relative
3099         co-ordinates. See curs_mouse(3X) man page for details.</p>
3100
3101         <p>The mouseinterval function sets the maximum time (in
3102         thousands of a second) that can elapse between press and
3103         release events in order for them to be recognized as a
3104         click. This function returns the previous interval value.
3105         The default is one fifth of a second.</p>
3106       </div>
3107     </div>
3108
3109     <div class="SECT1">
3110       <hr>
3111
3112       <h2 class="SECT1"><a name="SCREEN" id="SCREEN">13. Screen
3113       Manipulation</a></h2>
3114
3115       <p>In this section, we will look into some functions, which
3116       allow us to manage the screen efficiently and to write some
3117       fancy programs. This is especially important in writing
3118       games.</p>
3119
3120       <div class="SECT2">
3121         <hr>
3122
3123         <h3 class="SECT2"><a name="GETYX" id="GETYX">13.1. getyx()
3124         functions</a></h3>
3125
3126         <p>The function <tt class="LITERAL">getyx()</tt> can be
3127         used to find out the present cursor co-ordinates. It will
3128         fill the values of x and y co-ordinates in the arguments
3129         given to it. Since getyx() is a macro you don't have to
3130         pass the address of the variables. It can be called as</p>
3131
3132         <pre class="PROGRAMLISTING">
3133     getyx(win, y, x);
3134     /* win: window pointer
3135      *   y, x: y, x co-ordinates will be put into this variables 
3136      */
3137 </pre>
3138         <p>The function getparyx() gets the beginning co-ordinates
3139         of the sub window relative to the main window. This is some
3140         times useful to update a sub window. When designing fancy
3141         stuff like writing multiple menus, it becomes difficult to
3142         store the menu positions, their first option co-ordinates
3143         etc. A simple solution to this problem, is to create menus
3144         in sub windows and later find the starting co-ordinates of
3145         the menus by using getparyx().</p>
3146
3147         <p>The functions getbegyx() and getmaxyx() store current
3148         window's beginning and maximum co-ordinates. These
3149         functions are useful in the same way as above in managing
3150         the windows and sub windows effectively.</p>
3151       </div>
3152
3153       <div class="SECT2">
3154         <hr>
3155
3156         <h3 class="SECT2"><a name="SCREENDUMP" id=
3157         "SCREENDUMP">13.2. Screen Dumping</a></h3>
3158
3159         <p>While writing games, some times it becomes necessary to
3160         store the state of the screen and restore it back to the
3161         same state. The function scr_dump() can be used to dump the
3162         screen contents to a file given as an argument. Later it
3163         can be restored by scr_restore function. These two simple
3164         functions can be used effectively to maintain a fast moving
3165         game with changing scenarios.</p>
3166       </div>
3167
3168       <div class="SECT2">
3169         <hr>
3170
3171         <h3 class="SECT2"><a name="WINDOWDUMP" id=
3172         "WINDOWDUMP">13.3. Window Dumping</a></h3>
3173
3174         <p>To store and restore windows, the functions <tt class=
3175         "LITERAL">putwin()</tt> and <tt class=
3176         "LITERAL">getwin()</tt> can be used. <tt class=
3177         "LITERAL">putwin()</tt> puts the present window state into
3178         a file, which can be later restored by <tt class=
3179         "LITERAL">getwin()</tt>.</p>
3180
3181         <p>The function <tt class="LITERAL">copywin()</tt> can be
3182         used to copy a window completely onto another window. It
3183         takes the source and destination windows as parameters and
3184         according to the rectangle specified, it copies the
3185         rectangular region from source to destination window. Its
3186         last parameter specifies whether to overwrite or just
3187         overlay the contents on to the destination window. If this
3188         argument is true, then the copying is non-destructive.</p>
3189       </div>
3190     </div>
3191
3192     <div class="SECT1">
3193       <hr>
3194
3195       <h2 class="SECT1"><a name="MISC" id="MISC">14. Miscellaneous
3196       features</a></h2>
3197
3198       <p>Now you know enough features to write a good curses
3199       program, with all bells and whistles. There are some
3200       miscellaneous functions which are useful in various cases.
3201       Let's go headlong into some of those.</p>
3202
3203       <div class="SECT2">
3204         <hr>
3205
3206         <h3 class="SECT2"><a name="CURSSET" id="CURSSET">14.1.
3207         curs_set()</a></h3>
3208
3209         <p>This function can be used to make the cursor invisible.
3210         The parameter to this function should be</p>
3211
3212         <pre class="PROGRAMLISTING">
3213     0 : invisible      or
3214     1 : normal    or
3215     2 : very visible.
3216 </pre>
3217       </div>
3218
3219       <div class="SECT2">
3220         <hr>
3221
3222         <h3 class="SECT2"><a name="TEMPLEAVE" id="TEMPLEAVE">14.2.
3223         Temporarily Leaving Curses mode</a></h3>
3224
3225         <p>Some times you may want to get back to cooked mode
3226         (normal line buffering mode) temporarily. In such a case
3227         you will first need to save the tty modes with a call to
3228         <tt class="LITERAL">def_prog_mode()</tt> and then call
3229         <tt class="LITERAL">endwin()</tt> to end the curses mode.
3230         This will leave you in the original tty mode. To get back
3231         to curses once you are done, call <tt class=
3232         "LITERAL">reset_prog_mode()</tt> . This function returns
3233         the tty to the state stored by <tt class=
3234         "LITERAL">def_prog_mode()</tt>. Then do refresh(), and you
3235         are back to the curses mode. Here is an example showing the
3236         sequence of things to be done.</p>
3237
3238         <div class="EXAMPLE">
3239           <a name="BTELE" id="BTELE"></a>
3240           <p><b>Example 12. Temporarily Leaving Curses Mode</b>
3241           </p>
3242
3243           <pre class="PROGRAMLISTING">
3244 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
3245
3246 int main()
3247 {       
3248         initscr();                      /* Start curses mode              */
3249         printw("Hello World !!!\n");    /* Print Hello World              */
3250         refresh();                      /* Print it on to the real screen */
3251         def_prog_mode();                /* Save the tty modes             */
3252         endwin();                       /* End curses mode temporarily    */
3253         system("/bin/sh");              /* Do whatever you like in cooked mode */
3254         reset_prog_mode();              /* Return to the previous tty mode*/
3255                                         /* stored by def_prog_mode()      */
3256         refresh();                      /* Do refresh() to restore the    */
3257                                         /* Screen contents                */
3258         printw("Another String\n");     /* Back to curses use the full    */
3259         refresh();                      /* capabilities of curses         */
3260         endwin();                       /* End curses mode                */
3261
3262         return 0;
3263 }</span>
3264 </pre>
3265         </div>
3266       </div>
3267
3268       <div class="SECT2">
3269         <hr>
3270
3271         <h3 class="SECT2"><a name="ACSVARS" id="ACSVARS">14.3. ACS_
3272         variables</a></h3>
3273
3274         <p>If you have ever programmed in DOS, you know about those
3275         nifty characters in extended character set. They are
3276         printable only on some terminals. NCURSES functions like
3277         <tt class="LITERAL">box()</tt> use these characters. All
3278         these variables start with ACS meaning alternative
3279         character set. You might have noticed me using these
3280         characters in some of the programs above. Here's an example
3281         showing all the characters.</p>
3282
3283         <div class="EXAMPLE">
3284           <a name="BACSVARS" id="BACSVARS"></a>
3285           <p><b>Example 13. ACS Variables Example</b>
3286           </p>
3287
3288           <pre class="PROGRAMLISTING">
3289 <span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
3290
3291 int main()
3292 {
3293         initscr();
3294
3295         printw("Upper left corner           "); addch(ACS_ULCORNER); printw("\n"); 
3296         printw("Lower left corner           "); addch(ACS_LLCORNER); printw("\n");
3297         printw("Lower right corner          "); addch(ACS_LRCORNER); printw("\n");
3298         printw("Tee pointing right          "); addch(ACS_LTEE); printw("\n");
3299         printw("Tee pointing left           "); addch(ACS_RTEE); printw("\n");
3300         printw("Tee pointing up             "); addch(ACS_BTEE); printw("\n");
3301         printw("Tee pointing down           "); addch(ACS_TTEE); printw("\n");
3302         printw("Horizontal line             "); addch(ACS_HLINE); printw("\n");
3303         printw("Vertical line               "); addch(ACS_VLINE); printw("\n");
3304         printw("Large Plus or cross over    "); addch(ACS_PLUS); printw("\n");
3305         printw("Scan Line 1                 "); addch(ACS_S1); printw("\n");
3306         printw("Scan Line 3                 "); addch(ACS_S3); printw("\n");
3307         printw("Scan Line 7                 "); addch(ACS_S7); printw("\n");
3308         printw("Scan Line 9                 "); addch(ACS_S9); printw("\n");
3309         printw("Diamond                     "); addch(ACS_DIAMOND); printw("\n");
3310         printw("Checker board (stipple)     "); addch(ACS_CKBOARD); printw("\n");
3311         printw("Degree Symbol               "); addch(ACS_DEGREE); printw("\n");
3312         printw("Plus/Minus Symbol           "); addch(ACS_PLMINUS); printw("\n");
3313         printw("Bullet                      "); addch(ACS_BULLET); printw("\n");
3314         printw("Arrow Pointing Left         "); addch(ACS_LARROW); printw("\n");
3315         printw("Arrow Pointing Right        "); addch(ACS_RARROW); printw("\n");
3316         printw("Arrow Pointing Down         "); addch(ACS_DARROW); printw("\n");
3317         printw("Arrow Pointing Up           "); addch(ACS_UARROW); printw("\n");
3318         printw("Board of squares            "); addch(ACS_BOARD); printw("\n");
3319         printw("Lantern Symbol              "); addch(ACS_LANTERN); printw("\n");
3320         printw("Solid Square Block          "); addch(ACS_BLOCK); printw("\n");
3321         printw("Less/Equal sign             "); addch(ACS_LEQUAL); printw("\n");
3322         printw("Greater/Equal sign          "); addch(ACS_GEQUAL); printw("\n");
3323         printw("Pi                          "); addch(ACS_PI); printw("\n");
3324         printw("Not equal                   "); addch(ACS_NEQUAL); printw("\n");
3325         printw("UK pound sign               "); addch(ACS_STERLING); printw("\n");
3326
3327         refresh();
3328         getch();
3329         endwin();
3330
3331         return 0;
3332 }</span>
3333 </pre>
3334         </div>
3335       </div>
3336     </div>
3337
3338     <div class="SECT1">
3339       <hr>
3340
3341       <h2 class="SECT1"><a name="OTHERLIB" id="OTHERLIB">15. Other
3342       libraries</a></h2>
3343
3344       <p>Apart from the curses library, there are few text mode
3345       libraries, which provide more functionality and a lot of
3346       features. The following sections explain three standard
3347       libraries which are usually distributed along with
3348       curses.</p>
3349     </div>
3350
3351     <div class="SECT1">
3352       <hr>
3353
3354       <h2 class="SECT1"><a name="PANELS" id="PANELS">16. Panel
3355       Library</a></h2>
3356
3357       <p>Now that you are proficient in curses, you wanted to do
3358       some thing big. You created a lot of overlapping windows to
3359       give a professional windows-type look. Unfortunately, it soon
3360       becomes difficult to manage these. The multiple refreshes,
3361       updates plunge you into a nightmare. The overlapping windows
3362       create blotches, whenever you forget to refresh the windows
3363       in the proper order.</p>
3364
3365       <p>Don't despair. There's an elegant solution provided in
3366       panels library. In the words of developers of ncurses</p>
3367
3368       <p><span class="emphasis"><i class="EMPHASIS">When your
3369       interface design is such that windows may dive deeper into
3370       the visibility stack or pop to the top at runtime, the
3371       resulting book-keeping can be tedious and difficult to get
3372       right. Hence the panels library.</i></span>
3373       </p>
3374
3375       <p>If you have lot of overlapping windows, then panels
3376       library is the way to go. It obviates the need of doing
3377       series of wnoutrefresh(), doupdate() and relieves the burden
3378       of doing it correctly(bottom up). The library maintains
3379       information about the order of windows, their overlapping and
3380       update the screen properly. So why wait? Let's take a close
3381       peek into panels.</p>
3382
3383       <div class="SECT2">
3384         <hr>
3385
3386         <h3 class="SECT2"><a name="PANELBASICS" id=
3387         "PANELBASICS">16.1. The Basics</a></h3>
3388
3389         <p>Panel object is a window that is implicitly treated as
3390         part of a deck including all other panel objects. The deck
3391         is treated as a stack with the top panel being completely
3392         visible and the other panels may or may not be obscured
3393         according to their positions. So the basic idea is to
3394         create a stack of overlapping panels and use panels library
3395         to display them correctly. There is a function similar to
3396         refresh() which, when called , displays panels in the
3397         correct order. Functions are provided to hide or show
3398         panels, move panels, change its size etc.. The overlapping
3399         problem is managed by the panels library during all the
3400         calls to these functions.</p>
3401
3402         <p>The general flow of a panel program goes like this:</p>
3403
3404         <ol type="1">
3405           <li>
3406             <p>Create the windows (with newwin()) to be attached to
3407             the panels.</p>
3408           </li>
3409
3410           <li>
3411             <p>Create panels with the chosen visibility order.
3412             Stack them up according to the desired visibility. The
3413             function new_panel() is used to created panels.</p>
3414           </li>
3415
3416           <li>
3417             <p>Call update_panels() to write the panels to the
3418             virtual screen in correct visibility order. Do a
3419             doupdate() to show it on the screen.</p>
3420           </li>
3421
3422           <li>
3423             <p>Mainpulate the panels with show_panel(),
3424             hide_panel(), move_panel() etc. Make use of helper
3425             functions like panel_hidden() and panel_window(). Make
3426             use of user pointer to store custom data for a panel.
3427             Use the functions set_panel_userptr() and
3428             panel_userptr() to set and get the user pointer for a
3429             panel.</p>
3430           </li>
3431
3432           <li>
3433             <p>When you are done with the panel use del_panel() to
3434             delete the panel.</p>
3435           </li>
3436         </ol>
3437
3438         <p>Let's make the concepts clear, with some programs. The
3439         following is a simple program which creates 3 overlapping
3440         panels and shows them on the screen.</p>
3441       </div>
3442
3443       <div class="SECT2">
3444         <hr>
3445
3446         <h3 class="SECT2"><a name="COMPILEPANELS" id=
3447         "COMPILEPANELS">16.2. Compiling With the Panels Library</a></h3>
3448
3449         <p>To use panels library functions, you have to include
3450         panel.h and to link the program with panels library the
3451         flag -lpanel should be added along with -lncurses in that
3452         order.</p>
3453
3454         <pre class="PROGRAMLISTING">
3455     #include &lt;panel.h&gt;
3456     .
3457     .
3458     .
3459
3460     compile and link: gcc &lt;program file&gt; -lpanel -lncurses
3461 </pre>
3462         <div class="EXAMPLE">
3463           <a name="PPASI" id="PPASI"></a>
3464           <p><b>Example 14. Panel basics</b>
3465           </p>
3466
3467           <pre class="PROGRAMLISTING">
3468 <span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3469
3470 int main()
3471 {       WINDOW *my_wins[3];
3472         PANEL  *my_panels[3];
3473         int lines = 10, cols = 40, y = 2, x = 4, i;
3474
3475         initscr();
3476         cbreak();
3477         noecho();
3478
3479         /* Create windows for the panels */
3480         my_wins[0] = newwin(lines, cols, y, x);
3481         my_wins[1] = newwin(lines, cols, y + 1, x + 5);
3482         my_wins[2] = newwin(lines, cols, y + 2, x + 10);
3483
3484         /* 
3485          * Create borders around the windows so that you can see the effect
3486          * of panels
3487          */
3488         for(i = 0; i &lt; 3; ++i)
3489                 box(my_wins[i], 0, 0);
3490
3491         /* Attach a panel to each window */     /* Order is bottom up */
3492         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3493         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3494         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3495
3496         /* Update the stacking order. 2nd panel will be on top */
3497         update_panels();
3498
3499         /* Show it on the screen */
3500         doupdate();
3501         
3502         getch();
3503         endwin();
3504 }
3505 </span>
3506 </pre>
3507         </div>
3508
3509         <p>As you can see, above program follows a simple flow as
3510         explained. The windows are created with newwin() and then
3511         they are attached to panels with new_panel(). As we attach
3512         one panel after another, the stack of panels gets updated.
3513         To put them on screen update_panels() and doupdate() are
3514         called.</p>
3515       </div>
3516
3517       <div class="SECT2">
3518         <hr>
3519
3520         <h3 class="SECT2"><a name="PANELBROWSING" id=
3521         "PANELBROWSING">16.3. Panel Window Browsing</a></h3>
3522
3523         <p>A slightly complicated example is given below. This
3524         program creates 3 windows which can be cycled through using
3525         tab. Have a look at the code.</p>
3526
3527         <div class="EXAMPLE">
3528           <a name="PPABR" id="PPABR"></a>
3529           <p><b>Example 15. Panel Window Browsing Example</b>
3530           </p>
3531
3532           <pre class="PROGRAMLISTING">
3533 <span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3534
3535 #define NLINES 10
3536 #define NCOLS 40
3537
3538 void init_wins(WINDOW **wins, int n);
3539 void win_show(WINDOW *win, char *label, int label_color);
3540 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3541
3542 int main()
3543 {       WINDOW *my_wins[3];
3544         PANEL  *my_panels[3];
3545         PANEL  *top;
3546         int ch;
3547
3548         /* Initialize curses */
3549         initscr();
3550         start_color();
3551         cbreak();
3552         noecho();
3553         keypad(stdscr, TRUE);
3554
3555         /* Initialize all the colors */
3556         init_pair(1, COLOR_RED, COLOR_BLACK);
3557         init_pair(2, COLOR_GREEN, COLOR_BLACK);
3558         init_pair(3, COLOR_BLUE, COLOR_BLACK);
3559         init_pair(4, COLOR_CYAN, COLOR_BLACK);
3560
3561         init_wins(my_wins, 3);
3562         
3563         /* Attach a panel to each window */     /* Order is bottom up */
3564         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3565         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3566         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3567
3568         /* Set up the user pointers to the next panel */
3569         set_panel_userptr(my_panels[0], my_panels[1]);
3570         set_panel_userptr(my_panels[1], my_panels[2]);
3571         set_panel_userptr(my_panels[2], my_panels[0]);
3572
3573         /* Update the stacking order. 2nd panel will be on top */
3574         update_panels();
3575
3576         /* Show it on the screen */
3577         attron(COLOR_PAIR(4));
3578         mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3579         attroff(COLOR_PAIR(4));
3580         doupdate();
3581
3582         top = my_panels[2];
3583         while((ch = getch()) != KEY_F(1))
3584         {       switch(ch)
3585                 {       case 9:
3586                                 top = (PANEL *)panel_userptr(top);
3587                                 top_panel(top);
3588                                 break;
3589                 }
3590                 update_panels();
3591                 doupdate();
3592         }
3593         endwin();
3594         return 0;
3595 }
3596
3597 /* Put all the windows */
3598 void init_wins(WINDOW **wins, int n)
3599 {       int x, y, i;
3600         char label[80];
3601
3602         y = 2;
3603         x = 10;
3604         for(i = 0; i &lt; n; ++i)
3605         {       wins[i] = newwin(NLINES, NCOLS, y, x);
3606                 sprintf(label, "Window Number %d", i + 1);
3607                 win_show(wins[i], label, i + 1);
3608                 y += 3;
3609                 x += 7;
3610         }
3611 }
3612
3613 /* Show the window with a border and a label */
3614 void win_show(WINDOW *win, char *label, int label_color)
3615 {       int startx, starty, height, width;
3616
3617         getbegyx(win, starty, startx);
3618         getmaxyx(win, height, width);
3619
3620         box(win, 0, 0);
3621         mvwaddch(win, 2, 0, ACS_LTEE); 
3622         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
3623         mvwaddch(win, 2, width - 1, ACS_RTEE); 
3624         
3625         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3626 }
3627
3628 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3629 {       int length, x, y;
3630         float temp;
3631
3632         if(win == NULL)
3633                 win = stdscr;
3634         getyx(win, y, x);
3635         if(startx != 0)
3636                 x = startx;
3637         if(starty != 0)
3638                 y = starty;
3639         if(width == 0)
3640                 width = 80;
3641
3642         length = strlen(string);
3643         temp = (width - length)/ 2;
3644         x = startx + (int)temp;
3645         wattron(win, color);
3646         mvwprintw(win, y, x, "%s", string);
3647         wattroff(win, color);
3648         refresh();
3649 }</span>
3650 </pre>
3651         </div>
3652       </div>
3653
3654       <div class="SECT2">
3655         <hr>
3656
3657         <h3 class="SECT2"><a name="USERPTRUSING" id=
3658         "USERPTRUSING">16.4. Using User Pointers</a></h3>
3659
3660         <p>In the above example I used user pointers to find out
3661         the next window in the cycle. We can attach custom
3662         information to the panel by specifying a user pointer,
3663         which can point to any information you want to store. In
3664         this case I stored the pointer to the next panel in the
3665         cycle. User pointer for a panel can be set with the
3666         function <tt class="LITERAL">set_panel_userptr()</tt>. It
3667         can be accessed using the function <tt class=
3668         "LITERAL">panel_userptr()</tt> which will return the user
3669         pointer for the panel given as argument. After finding the
3670         next panel in the cycle It is brought to the top by the
3671         function top_panel(). This function brings the panel given
3672         as argument to the top of the panel stack.</p>
3673       </div>
3674
3675       <div class="SECT2">
3676         <hr>
3677
3678         <h3 class="SECT2"><a name="PANELMOVERESIZE" id=
3679         "PANELMOVERESIZE">16.5. Moving and Resizing Panels</a></h3>
3680
3681         <p>The function <tt class="LITERAL">move_panel()</tt> can
3682         be used to move a panel to the desired location. It does
3683         not change the position of the panel in the stack. Make
3684         sure that you use move_panel() instead mvwin() on the
3685         window associated with the panel.</p>
3686
3687         <p>Resizing a panel is slightly complex. There is no
3688         straight forward function just to resize the window
3689         associated with a panel. A solution to resize a panel is to
3690         create a new window with the desired sizes, change the
3691         window associated with the panel using replace_panel().
3692         Don't forget to delete the old window. The window
3693         associated with a panel can be found by using the function
3694         panel_window().</p>
3695
3696         <p>The following program shows these concepts, in
3697         supposedly simple program. You can cycle through the window
3698         with &lt;TAB&gt; as usual. To resize or move the active
3699         panel press 'r' for resize 'm' for moving. Then use arrow
3700         keys to resize or move it to the desired way and press
3701         enter to end your resizing or moving. This example makes
3702         use of user data to get the required data to do the
3703         operations.</p>
3704
3705         <div class="EXAMPLE">
3706           <a name="PPARE" id="PPARE"></a>
3707           <p><b>Example 16. Panel Moving and Resizing example</b>
3708           </p>
3709
3710           <pre class="PROGRAMLISTING">
3711 <span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3712
3713 typedef struct _PANEL_DATA {
3714         int x, y, w, h;
3715         char label[80]; 
3716         int label_color;
3717         PANEL *next;
3718 }PANEL_DATA;
3719
3720 #define NLINES 10
3721 #define NCOLS 40
3722
3723 void init_wins(WINDOW **wins, int n);
3724 void win_show(WINDOW *win, char *label, int label_color);
3725 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3726 void set_user_ptrs(PANEL **panels, int n);
3727
3728 int main()
3729 {       WINDOW *my_wins[3];
3730         PANEL  *my_panels[3];
3731         PANEL_DATA  *top;
3732         PANEL *stack_top;
3733         WINDOW *temp_win, *old_win;
3734         int ch;
3735         int newx, newy, neww, newh;
3736         int size = FALSE, move = FALSE;
3737
3738         /* Initialize curses */
3739         initscr();
3740         start_color();
3741         cbreak();
3742         noecho();
3743         keypad(stdscr, TRUE);
3744
3745         /* Initialize all the colors */
3746         init_pair(1, COLOR_RED, COLOR_BLACK);
3747         init_pair(2, COLOR_GREEN, COLOR_BLACK);
3748         init_pair(3, COLOR_BLUE, COLOR_BLACK);
3749         init_pair(4, COLOR_CYAN, COLOR_BLACK);
3750
3751         init_wins(my_wins, 3);
3752         
3753         /* Attach a panel to each window */     /* Order is bottom up */
3754         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3755         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3756         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3757
3758         set_user_ptrs(my_panels, 3);
3759         /* Update the stacking order. 2nd panel will be on top */
3760         update_panels();
3761
3762         /* Show it on the screen */
3763         attron(COLOR_PAIR(4));
3764         mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3765         mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3766         attroff(COLOR_PAIR(4));
3767         doupdate();
3768
3769         stack_top = my_panels[2];
3770         top = (PANEL_DATA *)panel_userptr(stack_top);
3771         newx = top-&gt;x;
3772         newy = top-&gt;y;
3773         neww = top-&gt;w;
3774         newh = top-&gt;h;
3775         while((ch = getch()) != KEY_F(1))
3776         {       switch(ch)
3777                 {       case 9:         /* Tab */
3778                                 top = (PANEL_DATA *)panel_userptr(stack_top);
3779                                 top_panel(top-&gt;next);
3780                                 stack_top = top-&gt;next;
3781                                 top = (PANEL_DATA *)panel_userptr(stack_top);
3782                                 newx = top-&gt;x;
3783                                 newy = top-&gt;y;
3784                                 neww = top-&gt;w;
3785                                 newh = top-&gt;h;
3786                                 break;
3787                         case 'r':       /* Re-Size*/
3788                                 size = TRUE;
3789                                 attron(COLOR_PAIR(4));
3790                                 mvprintw(LINES - 4, 0, "Entered Resizing :Use Arrow Keys to resize and press &lt;ENTER&gt; to end resizing");
3791                                 refresh();
3792                                 attroff(COLOR_PAIR(4));
3793                                 break;
3794                         case 'm':       /* Move */
3795                                 attron(COLOR_PAIR(4));
3796                                 mvprintw(LINES - 4, 0, "Entered Moving: Use Arrow Keys to Move and press &lt;ENTER&gt; to end moving");
3797                                 refresh();
3798                                 attroff(COLOR_PAIR(4));
3799                                 move = TRUE;
3800                                 break;
3801                         case KEY_LEFT:
3802                                 if(size == TRUE)
3803                                 {       --newx;
3804                                         ++neww;
3805                                 }
3806                                 if(move == TRUE)
3807                                         --newx;
3808                                 break;
3809                         case KEY_RIGHT:
3810                                 if(size == TRUE)
3811                                 {       ++newx;
3812                                         --neww;
3813                                 }
3814                                 if(move == TRUE)
3815                                         ++newx;
3816                                 break;
3817                         case KEY_UP:
3818                                 if(size == TRUE)
3819                                 {       --newy;
3820                                         ++newh;
3821                                 }
3822                                 if(move == TRUE)
3823                                         --newy;
3824                                 break;
3825                         case KEY_DOWN:
3826                                 if(size == TRUE)
3827                                 {       ++newy;
3828                                         --newh;
3829                                 }
3830                                 if(move == TRUE)
3831                                         ++newy;
3832                                 break;
3833                         case 10:        /* Enter */
3834                                 move(LINES - 4, 0);
3835                                 clrtoeol();
3836                                 refresh();
3837                                 if(size == TRUE)
3838                                 {       old_win = panel_window(stack_top);
3839                                         temp_win = newwin(newh, neww, newy, newx);
3840                                         replace_panel(stack_top, temp_win);
3841                                         win_show(temp_win, top-&gt;label, top-&gt;label_color); 
3842                                         delwin(old_win);
3843                                         size = FALSE;
3844                                 }
3845                                 if(move == TRUE)
3846                                 {       move_panel(stack_top, newy, newx);
3847                                         move = FALSE;
3848                                 }
3849                                 break;
3850                         
3851                 }
3852                 attron(COLOR_PAIR(4));
3853                 mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3854                 mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3855                 attroff(COLOR_PAIR(4));
3856                 refresh();      
3857                 update_panels();
3858                 doupdate();
3859         }
3860         endwin();
3861         return 0;
3862 }
3863
3864 /* Put all the windows */
3865 void init_wins(WINDOW **wins, int n)
3866 {       int x, y, i;
3867         char label[80];
3868
3869         y = 2;
3870         x = 10;
3871         for(i = 0; i &lt; n; ++i)
3872         {       wins[i] = newwin(NLINES, NCOLS, y, x);
3873                 sprintf(label, "Window Number %d", i + 1);
3874                 win_show(wins[i], label, i + 1);
3875                 y += 3;
3876                 x += 7;
3877         }
3878 }
3879
3880 /* Set the PANEL_DATA structures for individual panels */
3881 void set_user_ptrs(PANEL **panels, int n)
3882 {       PANEL_DATA *ptrs;
3883         WINDOW *win;
3884         int x, y, w, h, i;
3885         char temp[80];
3886         
3887         ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA));
3888
3889         for(i = 0;i &lt; n; ++i)
3890         {       win = panel_window(panels[i]);
3891                 getbegyx(win, y, x);
3892                 getmaxyx(win, h, w);
3893                 ptrs[i].x = x;
3894                 ptrs[i].y = y;
3895                 ptrs[i].w = w;
3896                 ptrs[i].h = h;
3897                 sprintf(temp, "Window Number %d", i + 1);
3898                 strcpy(ptrs[i].label, temp);
3899                 ptrs[i].label_color = i + 1;
3900                 if(i + 1 == n)
3901                         ptrs[i].next = panels[0];
3902                 else
3903                         ptrs[i].next = panels[i + 1];
3904                 set_panel_userptr(panels[i], &amp;ptrs[i]);
3905         }
3906 }
3907
3908 /* Show the window with a border and a label */
3909 void win_show(WINDOW *win, char *label, int label_color)
3910 {       int startx, starty, height, width;
3911
3912         getbegyx(win, starty, startx);
3913         getmaxyx(win, height, width);
3914
3915         box(win, 0, 0);
3916         mvwaddch(win, 2, 0, ACS_LTEE); 
3917         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
3918         mvwaddch(win, 2, width - 1, ACS_RTEE); 
3919         
3920         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3921 }
3922
3923 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3924 {       int length, x, y;
3925         float temp;
3926
3927         if(win == NULL)
3928                 win = stdscr;
3929         getyx(win, y, x);
3930         if(startx != 0)
3931                 x = startx;
3932         if(starty != 0)
3933                 y = starty;
3934         if(width == 0)
3935                 width = 80;
3936
3937         length = strlen(string);
3938         temp = (width - length)/ 2;
3939         x = startx + (int)temp;
3940         wattron(win, color);
3941         mvwprintw(win, y, x, "%s", string);
3942         wattroff(win, color);
3943         refresh();
3944 }</span>
3945 </pre>
3946         </div>
3947
3948         <p>Concentrate on the main while loop. Once it finds out
3949         the type of key pressed, it takes appropriate action. If
3950         'r' is pressed resizing mode is started. After this the new
3951         sizes are updated as the user presses the arrow keys. When
3952         the user presses &lt;ENTER&gt; present selection ends and
3953         panel is resized by using the concept explained. While in
3954         resizing mode the program doesn't show how the window is
3955         getting resized. It is left as an exercise to the reader to
3956         print a dotted border while it gets resized to a new
3957         position.</p>
3958
3959         <p>When the user presses 'm' the move mode starts. This is
3960         a bit simpler than resizing. As the arrow keys are pressed
3961         the new position is updated and pressing of &lt;ENTER&gt;
3962         causes the panel to be moved by calling the function
3963         move_panel().</p>
3964
3965         <p>In this program the user data which is represented as
3966         PANEL_DATA, plays very important role in finding the
3967         associated information with a panel. As written in the
3968         comments, the PANEL_DATA stores the panel sizes, label,
3969         label color and a pointer to the next panel in the
3970         cycle.</p>
3971       </div>
3972
3973       <div class="SECT2">
3974         <hr>
3975
3976         <h3 class="SECT2"><a name="PANELSHOWHIDE" id=
3977         "PANELSHOWHIDE">16.6. Hiding and Showing Panels</a></h3>
3978
3979         <p>A Panel can be hidden by using the function
3980         hide_panel(). This function merely removes it form the
3981         stack of panels, thus hiding it on the screen once you do
3982         update_panels() and doupdate(). It doesn't destroy the
3983         PANEL structure associated with the hidden panel. It can be
3984         shown again by using the show_panel() function.</p>
3985
3986         <p>The following program shows the hiding of panels. Press
3987         'a' or 'b' or 'c' to show or hide first, second and third
3988         windows respectively. It uses a user data with a small
3989         variable hide, which keeps track of whether the window is
3990         hidden or not. For some reason the function <tt class=
3991         "LITERAL">panel_hidden()</tt> which tells whether a panel
3992         is hidden or not is not working. A bug report was also
3993         presented by Michael Andres <a href=
3994         "http://www.geocrawler.com/archives/3/344/1999/9/0/2643549/"
3995         target="_top">here</a></p>
3996
3997         <div class="EXAMPLE">
3998           <a name="PPAHI" id="PPAHI"></a>
3999           <p><b>Example 17. Panel Hiding and Showing example</b>
4000           </p>
4001
4002           <pre class="PROGRAMLISTING">
4003 <span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
4004
4005 typedef struct _PANEL_DATA {
4006         int hide;       /* TRUE if panel is hidden */
4007 }PANEL_DATA;
4008
4009 #define NLINES 10
4010 #define NCOLS 40
4011
4012 void init_wins(WINDOW **wins, int n);
4013 void win_show(WINDOW *win, char *label, int label_color);
4014 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4015
4016 int main()
4017 {       WINDOW *my_wins[3];
4018         PANEL  *my_panels[3];
4019         PANEL_DATA panel_datas[3];
4020         PANEL_DATA *temp;
4021         int ch;
4022
4023         /* Initialize curses */
4024         initscr();
4025         start_color();
4026         cbreak();
4027         noecho();
4028         keypad(stdscr, TRUE);
4029
4030         /* Initialize all the colors */
4031         init_pair(1, COLOR_RED, COLOR_BLACK);
4032         init_pair(2, COLOR_GREEN, COLOR_BLACK);
4033         init_pair(3, COLOR_BLUE, COLOR_BLACK);
4034         init_pair(4, COLOR_CYAN, COLOR_BLACK);
4035
4036         init_wins(my_wins, 3);
4037         
4038         /* Attach a panel to each window */     /* Order is bottom up */
4039         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
4040         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
4041         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
4042
4043         /* Initialize panel datas saying that nothing is hidden */
4044         panel_datas[0].hide = FALSE;
4045         panel_datas[1].hide = FALSE;
4046         panel_datas[2].hide = FALSE;
4047
4048         set_panel_userptr(my_panels[0], &amp;panel_datas[0]);
4049         set_panel_userptr(my_panels[1], &amp;panel_datas[1]);
4050         set_panel_userptr(my_panels[2], &amp;panel_datas[2]);
4051
4052         /* Update the stacking order. 2nd panel will be on top */
4053         update_panels();
4054
4055         /* Show it on the screen */
4056         attron(COLOR_PAIR(4));
4057         mvprintw(LINES - 3, 0, "Show or Hide a window with 'a'(first window)  'b'(Second Window)  'c'(Third Window)");
4058         mvprintw(LINES - 2, 0, "F1 to Exit");
4059
4060         attroff(COLOR_PAIR(4));
4061         doupdate();
4062         
4063         while((ch = getch()) != KEY_F(1))
4064         {       switch(ch)
4065                 {       case 'a':                       
4066                                 temp = (PANEL_DATA *)panel_userptr(my_panels[0]);
4067                                 if(temp-&gt;hide == FALSE)
4068                                 {       hide_panel(my_panels[0]);
4069                                         temp-&gt;hide = TRUE;
4070                                 }
4071                                 else
4072                                 {       show_panel(my_panels[0]);
4073                                         temp-&gt;hide = FALSE;
4074                                 }
4075                                 break;
4076                         case 'b':
4077                                 temp = (PANEL_DATA *)panel_userptr(my_panels[1]);
4078                                 if(temp-&gt;hide == FALSE)
4079                                 {       hide_panel(my_panels[1]);
4080                                         temp-&gt;hide = TRUE;
4081                                 }
4082                                 else
4083                                 {       show_panel(my_panels[1]);
4084                                         temp-&gt;hide = FALSE;
4085                                 }
4086                                 break;
4087                         case 'c':
4088                                 temp = (PANEL_DATA *)panel_userptr(my_panels[2]);
4089                                 if(temp-&gt;hide == FALSE)
4090                                 {       hide_panel(my_panels[2]);
4091                                         temp-&gt;hide = TRUE;
4092                                 }
4093                                 else
4094                                 {       show_panel(my_panels[2]);
4095                                         temp-&gt;hide = FALSE;
4096                                 }
4097                                 break;
4098                 }
4099                 update_panels();
4100                 doupdate();
4101         }
4102         endwin();
4103         return 0;
4104 }
4105
4106 /* Put all the windows */
4107 void init_wins(WINDOW **wins, int n)
4108 {       int x, y, i;
4109         char label[80];
4110
4111         y = 2;
4112         x = 10;
4113         for(i = 0; i &lt; n; ++i)
4114         {       wins[i] = newwin(NLINES, NCOLS, y, x);
4115                 sprintf(label, "Window Number %d", i + 1);
4116                 win_show(wins[i], label, i + 1);
4117                 y += 3;
4118                 x += 7;
4119         }
4120 }
4121
4122 /* Show the window with a border and a label */
4123 void win_show(WINDOW *win, char *label, int label_color)
4124 {       int startx, starty, height, width;
4125
4126         getbegyx(win, starty, startx);
4127         getmaxyx(win, height, width);
4128
4129         box(win, 0, 0);
4130         mvwaddch(win, 2, 0, ACS_LTEE); 
4131         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
4132         mvwaddch(win, 2, width - 1, ACS_RTEE); 
4133         
4134         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
4135 }
4136
4137 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4138 {       int length, x, y;
4139         float temp;
4140
4141         if(win == NULL)
4142                 win = stdscr;
4143         getyx(win, y, x);
4144         if(startx != 0)
4145                 x = startx;
4146         if(starty != 0)
4147                 y = starty;
4148         if(width == 0)
4149                 width = 80;
4150
4151         length = strlen(string);
4152         temp = (width - length)/ 2;
4153         x = startx + (int)temp;
4154         wattron(win, color);
4155         mvwprintw(win, y, x, "%s", string);
4156         wattroff(win, color);
4157         refresh();
4158 }</span>
4159 </pre>
4160         </div>
4161       </div>
4162
4163       <div class="SECT2">
4164         <hr>
4165
4166         <h3 class="SECT2"><a name="PANELABOVE" id=
4167         "PANELABOVE">16.7. panel_above() and panel_below()
4168         Functions</a></h3>
4169
4170         <p>The functions <tt class="LITERAL">panel_above()</tt> and
4171         <tt class="LITERAL">panel_below()</tt> can be used to find
4172         out the panel above and below a panel. If the argument to
4173         these functions is NULL, then they return a pointer to
4174         bottom panel and top panel respectively.</p>
4175       </div>
4176     </div>
4177
4178     <div class="SECT1">
4179       <hr>
4180
4181       <h2 class="SECT1"><a name="MENUS" id="MENUS">17. Menus
4182       Library</a></h2>
4183
4184       <p>The menus library provides a nice extension to basic
4185       curses, through which you can create menus. It provides a set
4186       of functions to create menus. But they have to be customized
4187       to give a nicer look, with colors etc. Let's get into the
4188       details.</p>
4189
4190       <p>A menu is a screen display that assists the user to choose
4191       some subset of a given set of items. To put it simple, a menu
4192       is a collection of items from which one or more items can be
4193       chosen. Some readers might not be aware of multiple item
4194       selection capability. Menu library provides functionality to
4195       write menus from which the user can chose more than one item
4196       as the preferred choice. This is dealt with in a later
4197       section. Now it is time for some rudiments.</p>
4198
4199       <div class="SECT2">
4200         <hr>
4201
4202         <h3 class="SECT2"><a name="MENUBASICS" id=
4203         "MENUBASICS">17.1. The Basics</a></h3>
4204
4205         <p>To create menus, you first create items, and then post
4206         the menu to the display. After that, all the processing of
4207         user responses is done in an elegant function menu_driver()
4208         which is the work horse of any menu program.</p>
4209
4210         <p>The general flow of control of a menu program looks like
4211         this.</p>
4212
4213         <ol type="1">
4214           <li>
4215             <p>Initialize curses</p>
4216           </li>
4217
4218           <li>
4219             <p>Create items using new_item(). You can specify a
4220             name and description for the items.</p>
4221           </li>
4222
4223           <li>
4224             <p>Create the menu with new_menu() by specifying the
4225             items to be attached with.</p>
4226           </li>
4227
4228           <li>
4229             <p>Post the menu with menu_post() and refresh the
4230             screen.</p>
4231           </li>
4232
4233           <li>
4234             <p>Process the user requests with a loop and do
4235             necessary updates to menu with menu_driver.</p>
4236           </li>
4237
4238           <li>
4239             <p>Unpost the menu with menu_unpost()</p>
4240           </li>
4241
4242           <li>
4243             <p>Free the memory allocated to menu by free_menu()</p>
4244           </li>
4245
4246           <li>
4247             <p>Free the memory allocated to the items with
4248             free_item()</p>
4249           </li>
4250
4251           <li>
4252             <p>End curses</p>
4253           </li>
4254         </ol>
4255
4256         <p>Let's see a program which prints a simple menu and
4257         updates the current selection with up, down arrows.</p>
4258       </div>
4259
4260       <div class="SECT2">
4261         <hr>
4262
4263         <h3 class="SECT2"><a name="COMPILEMENUS" id=
4264         "COMPILEMENUS">17.2. Compiling With the Menu Library</a></h3>
4265
4266         <p>To use menu library functions, you have to include
4267         menu.h and to link the program with menu library the flag
4268         -lmenu should be added along with -lncurses in that
4269         order.</p>
4270
4271         <pre class="PROGRAMLISTING">
4272     #include &lt;menu.h&gt;
4273     .
4274     .
4275     .
4276
4277     compile and link: gcc &lt;program file&gt; -lmenu -lncurses
4278 </pre>
4279         <div class="EXAMPLE">
4280           <a name="MMESI" id="MMESI"></a>
4281           <p><b>Example 18. Menu Basics</b>
4282           </p>
4283
4284           <pre class="PROGRAMLISTING">
4285 <span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4286 #include &lt;menu.h&gt;
4287
4288 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4289 #define CTRLD   4
4290
4291 char *choices[] = {
4292                         "Choice 1",
4293                         "Choice 2",
4294                         "Choice 3",
4295                         "Choice 4",
4296                         "Exit",
4297                   };
4298
4299 int main()
4300 {       ITEM **my_items;
4301         int c;                          
4302         MENU *my_menu;
4303         int n_choices, i;
4304         ITEM *cur_item;
4305         
4306         
4307         initscr();
4308         cbreak();
4309         noecho();
4310         keypad(stdscr, TRUE);
4311         
4312         n_choices = ARRAY_SIZE(choices);
4313         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
4314
4315         for(i = 0; i &lt; n_choices; ++i)
4316                 my_items[i] = new_item(choices[i], choices[i]);
4317         my_items[n_choices] = (ITEM *)NULL;
4318
4319         my_menu = new_menu((ITEM **)my_items);
4320         mvprintw(LINES - 2, 0, "F1 to Exit");
4321         post_menu(my_menu);
4322         refresh();
4323
4324         while((c = getch()) != KEY_F(1))
4325         {   switch(c)
4326             {   case KEY_DOWN:
4327                         menu_driver(my_menu, REQ_DOWN_ITEM);
4328                                 break;
4329                         case KEY_UP:
4330                                 menu_driver(my_menu, REQ_UP_ITEM);
4331                                 break;
4332                 }
4333         }       
4334
4335         free_item(my_items[0]);
4336         free_item(my_items[1]);
4337         free_menu(my_menu);
4338         endwin();
4339 }
4340         </span>
4341 </pre>
4342         </div>
4343
4344         <p>This program demonstrates the basic concepts involved in
4345         creating a menu using menus library. First we create the
4346         items using new_item() and then attach them to the menu
4347         with new_menu() function. After posting the menu and
4348         refreshing the screen, the main processing loop starts. It
4349         reads user input and takes corresponding action. The
4350         function menu_driver() is the main work horse of the menu
4351         system. The second parameter to this function tells what's
4352         to be done with the menu. According to the parameter,
4353         menu_driver() does the corresponding task. The value can be
4354         either a menu navigational request, an ascii character, or
4355         a KEY_MOUSE special key associated with a mouse event.</p>
4356
4357         <p>The menu_driver accepts following navigational
4358         requests.</p>
4359
4360         <pre class="PROGRAMLISTING">
4361 &#13;     REQ_LEFT_ITEM         Move left to an item.
4362      REQ_RIGHT_ITEM      Move right to an item.
4363      REQ_UP_ITEM         Move up to an item.
4364      REQ_DOWN_ITEM       Move down to an item.
4365      REQ_SCR_ULINE       Scroll up a line.
4366      REQ_SCR_DLINE          Scroll down a line.
4367      REQ_SCR_DPAGE          Scroll down a page.
4368      REQ_SCR_UPAGE         Scroll up a page.
4369      REQ_FIRST_ITEM     Move to the first item.
4370      REQ_LAST_ITEM         Move to the last item.
4371      REQ_NEXT_ITEM         Move to the next item.
4372      REQ_PREV_ITEM         Move to the previous item. 
4373      REQ_TOGGLE_ITEM     Select/deselect an item.
4374      REQ_CLEAR_PATTERN     Clear the menu pattern buffer.
4375      REQ_BACK_PATTERN      Delete the previous character from the pattern buffer.
4376      REQ_NEXT_MATCH     Move to the next item matching the pattern match.
4377      REQ_PREV_MATCH     Move to the previous item matching the pattern match.&#13;
4378 </pre>
4379         <p>Don't get overwhelmed by the number of options. We will
4380         see them slowly one after another. The options of interest
4381         in this example are REQ_UP_ITEM and REQ_DOWN_ITEM. These
4382         two options when passed to menu_driver, menu driver updates
4383         the current item to one item up or down respectively.</p>
4384       </div>
4385
4386       <div class="SECT2">
4387         <hr>
4388
4389         <h3 class="SECT2"><a name="MENUDRIVER" id=
4390         "MENUDRIVER">17.3. Menu Driver: The work horse of the menu
4391         system</a></h3>
4392
4393         <p>As you have seen in the above example, menu_driver plays
4394         an important role in updating the menu. It is very
4395         important to understand various options it takes and what
4396         they do. As explained above, the second parameter to
4397         menu_driver() can be either a navigational request, a
4398         printable character or a KEY_MOUSE key. Let's dissect the
4399         different navigational requests.</p>
4400
4401         <ul>
4402           <li>
4403             <p><span class="emphasis"><i class=
4404             "EMPHASIS">REQ_LEFT_ITEM and REQ_RIGHT_ITEM</i></span>
4405             </p>
4406
4407             <p>A Menu can be displayed with multiple columns for
4408             more than one item. This can be done by using the
4409             <tt class="LITERAL">menu_format()</tt>function. When a
4410             multi columnar menu is displayed these requests cause
4411             the menu driver to move the current selection to left
4412             or right.</p>
4413           </li>
4414
4415           <li>
4416             <p><span class="emphasis"><i class=
4417             "EMPHASIS">REQ_UP_ITEM and REQ_DOWN_ITEM</i></span>
4418             </p>
4419
4420             <p>These two options you have seen in the above
4421             example. These options when given, makes the
4422             menu_driver to move the current selection to an item up
4423             or down.</p>
4424           </li>
4425
4426           <li>
4427             <p><span class="emphasis"><i class="EMPHASIS">REQ_SCR_*
4428             options</i></span>
4429             </p>
4430
4431             <p>The four options REQ_SCR_ULINE, REQ_SCR_DLINE,
4432             REQ_SCR_DPAGE, REQ_SCR_UPAGE are related to scrolling.
4433             If all the items in the menu cannot be displayed in the
4434             menu sub window, then the menu is scrollable. These
4435             requests can be given to the menu_driver to do the
4436             scrolling either one line up, down or one page down or
4437             up respectively.</p>
4438           </li>
4439
4440           <li>
4441             <p><span class="emphasis"><i class=
4442             "EMPHASIS">REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_NEXT_ITEM
4443             and REQ_PREV_ITEM</i></span>
4444             </p>
4445
4446             <p>These requests are self explanatory.</p>
4447           </li>
4448
4449           <li>
4450             <p><span class="emphasis"><i class=
4451             "EMPHASIS">REQ_TOGGLE_ITEM</i></span>
4452             </p>
4453
4454             <p>This request when given, toggles the present
4455             selection. This option is to be used only in a multi
4456             valued menu. So to use this request the option
4457             O_ONEVALUE must be off. This option can be made off or
4458             on with set_menu_opts().</p>
4459           </li>
4460
4461           <li>
4462             <p><span class="emphasis"><i class="EMPHASIS">Pattern
4463             Requests</i></span>
4464             </p>
4465
4466             <p>Every menu has an associated pattern buffer, which
4467             is used to find the nearest match to the ascii
4468             characters entered by the user. Whenever ascii
4469             characters are given to menu_driver, it puts in to the
4470             pattern buffer. It also tries to find the nearest match
4471             to the pattern in the items list and moves current
4472             selection to that item. The request REQ_CLEAR_PATTERN
4473             clears the pattern buffer. The request REQ_BACK_PATTERN
4474             deletes the previous character in the pattern buffer.
4475             In case the pattern matches more than one item then the
4476             matched items can be cycled through REQ_NEXT_MATCH and
4477             REQ_PREV_MATCH which move the current selection to the
4478             next and previous matches respectively.</p>
4479           </li>
4480
4481           <li>
4482             <p><span class="emphasis"><i class="EMPHASIS">Mouse
4483             Requests</i></span>
4484             </p>
4485
4486             <p>In case of KEY_MOUSE requests, according to the
4487             mouse position an action is taken accordingly. The
4488             action to be taken is explained in the man page as,</p>
4489
4490             <pre class="PROGRAMLISTING">
4491 <span class="emphasis"><i class=
4492 "EMPHASIS">       If  the  second argument is the KEY_MOUSE special key, the
4493        associated mouse event is translated into one of the above
4494        pre-defined  requests.   Currently only clicks in the user
4495        window (e.g. inside the menu display area or  the  decora&shy;
4496        tion  window)  are handled. If you click above the display
4497        region of the menu, a REQ_SCR_ULINE is generated,  if  you
4498        doubleclick  a  REQ_SCR_UPAGE  is  generated  and  if  you
4499        tripleclick a REQ_FIRST_ITEM is generated.  If  you  click
4500        below  the  display region of the menu, a REQ_SCR_DLINE is
4501        generated, if you doubleclick a REQ_SCR_DPAGE is generated
4502        and  if  you  tripleclick a REQ_LAST_ITEM is generated. If
4503        you click at an item inside the display area of the  menu,
4504        the menu cursor is positioned to that item.</i></span>
4505 </pre>
4506           </li>
4507         </ul>
4508
4509         <p>Each of the above requests will be explained in the
4510         following lines with several examples whenever
4511         appropriate.</p>
4512       </div>
4513
4514       <div class="SECT2">
4515         <hr>
4516
4517         <h3 class="SECT2"><a name="MENUWINDOWS" id=
4518         "MENUWINDOWS">17.4. Menu Windows</a></h3>
4519
4520         <p>Every menu created is associated with a window and a sub
4521         window. The menu window displays any title or border
4522         associated with the menu. The menu sub window displays the
4523         menu items currently available for selection. But we didn't
4524         specify any window or sub window in the simple example.
4525         When a window is not specified, stdscr is taken as the main
4526         window, and then menu system calculates the sub window size
4527         required for the display of items. Then items are displayed
4528         in the calculated sub window. So let's play with these
4529         windows and display a menu with a border and a title.</p>
4530
4531         <div class="EXAMPLE">
4532           <a name="MMEWI" id="MMEWI"></a>
4533           <p><b>Example 19. Menu Windows Usage example</b>
4534           </p>
4535
4536           <pre class="PROGRAMLISTING">
4537 <span class="INLINEMEDIAOBJECT">#include &lt;menu.h&gt;
4538
4539 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4540 #define CTRLD   4
4541
4542 char *choices[] = {
4543                         "Choice 1",
4544                         "Choice 2",
4545                         "Choice 3",
4546                         "Choice 4",
4547                         "Exit",
4548                         (char *)NULL,
4549                   };
4550 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4551
4552 int main()
4553 {       ITEM **my_items;
4554         int c;                          
4555         MENU *my_menu;
4556         WINDOW *my_menu_win;
4557         int n_choices, i;
4558         
4559         /* Initialize curses */
4560         initscr();
4561         start_color();
4562         cbreak();
4563         noecho();
4564         keypad(stdscr, TRUE);
4565         init_pair(1, COLOR_RED, COLOR_BLACK);
4566
4567         /* Create items */
4568         n_choices = ARRAY_SIZE(choices);
4569         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4570         for(i = 0; i &lt; n_choices; ++i)
4571                 my_items[i] = new_item(choices[i], choices[i]);
4572
4573         /* Crate menu */
4574         my_menu = new_menu((ITEM **)my_items);
4575
4576         /* Create the window to be associated with the menu */
4577         my_menu_win = newwin(10, 40, 4, 4);
4578         keypad(my_menu_win, TRUE);
4579      
4580         /* Set main window and sub window */
4581         set_menu_win(my_menu, my_menu_win);
4582         set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4583
4584         /* Set menu mark to the string " * " */
4585         set_menu_mark(my_menu, " * ");
4586
4587         /* Print a border around the main window and print a title */
4588         box(my_menu_win, 0, 0);
4589         print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4590         mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4591         mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4592         mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4593         mvprintw(LINES - 2, 0, "F1 to exit");
4594         refresh();
4595         
4596         /* Post the menu */
4597         post_menu(my_menu);
4598         wrefresh(my_menu_win);
4599
4600         while((c = wgetch(my_menu_win)) != KEY_F(1))
4601         {       switch(c)
4602                 {       case KEY_DOWN:
4603                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4604                                 break;
4605                         case KEY_UP:
4606                                 menu_driver(my_menu, REQ_UP_ITEM);
4607                                 break;
4608                 }
4609                 wrefresh(my_menu_win);
4610         }       
4611
4612         /* Unpost and free all the memory taken up */
4613         unpost_menu(my_menu);
4614         free_menu(my_menu);
4615         for(i = 0; i &lt; n_choices; ++i)
4616                 free_item(my_items[i]);
4617         endwin();
4618 }
4619
4620 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4621 {       int length, x, y;
4622         float temp;
4623
4624         if(win == NULL)
4625                 win = stdscr;
4626         getyx(win, y, x);
4627         if(startx != 0)
4628                 x = startx;
4629         if(starty != 0)
4630                 y = starty;
4631         if(width == 0)
4632                 width = 80;
4633
4634         length = strlen(string);
4635         temp = (width - length)/ 2;
4636         x = startx + (int)temp;
4637         wattron(win, color);
4638         mvwprintw(win, y, x, "%s", string);
4639         wattroff(win, color);
4640         refresh();
4641 }</span>
4642 </pre>
4643         </div>
4644
4645         <p>This example creates a menu with a title, border, a
4646         fancy line separating title and the items. As you can see,
4647         in order to attach a window to a menu the function
4648         set_menu_win() has to be used. Then we attach the sub
4649         window also. This displays the items in the sub window. You
4650         can also set the mark string which gets displayed to the
4651         left of the selected item with set_menu_mark().</p>
4652       </div>
4653
4654       <div class="SECT2">
4655         <hr>
4656
4657         <h3 class="SECT2"><a name="SCROLLMENUS" id=
4658         "SCROLLMENUS">17.5. Scrolling Menus</a></h3>
4659
4660         <p>If the sub window given for a window is not big enough
4661         to show all the items, then the menu will be scrollable.
4662         When you are on the last item in the present list, if you
4663         send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE
4664         and the menu scrolls by one item. You can manually give
4665         REQ_SCR_ operations to do scrolling. Let's see how it can
4666         be done.</p>
4667
4668         <div class="EXAMPLE">
4669           <a name="MMESC" id="MMESC"></a>
4670           <p><b>Example 20. Scrolling Menus example</b>
4671           </p>
4672
4673           <pre class="PROGRAMLISTING">
4674 <span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4675 #include &lt;menu.h&gt;
4676
4677 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4678 #define CTRLD   4
4679
4680 char *choices[] = {
4681                         "Choice 1",
4682                         "Choice 2",
4683                         "Choice 3",
4684                         "Choice 4",
4685                         "Choice 5",
4686                         "Choice 6",
4687                         "Choice 7",
4688                         "Choice 8",
4689                         "Choice 9",
4690                         "Choice 10",
4691                         "Exit",
4692                         (char *)NULL,
4693                   };
4694 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4695
4696 int main()
4697 {       ITEM **my_items;
4698         int c;                          
4699         MENU *my_menu;
4700         WINDOW *my_menu_win;
4701         int n_choices, i;
4702         
4703         /* Initialize curses */
4704         initscr();
4705         start_color();
4706         cbreak();
4707         noecho();
4708         keypad(stdscr, TRUE);
4709         init_pair(1, COLOR_RED, COLOR_BLACK);
4710         init_pair(2, COLOR_CYAN, COLOR_BLACK);
4711
4712         /* Create items */
4713         n_choices = ARRAY_SIZE(choices);
4714         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4715         for(i = 0; i &lt; n_choices; ++i)
4716                 my_items[i] = new_item(choices[i], choices[i]);
4717
4718         /* Crate menu */
4719         my_menu = new_menu((ITEM **)my_items);
4720
4721         /* Create the window to be associated with the menu */
4722         my_menu_win = newwin(10, 40, 4, 4);
4723         keypad(my_menu_win, TRUE);
4724      
4725         /* Set main window and sub window */
4726         set_menu_win(my_menu, my_menu_win);
4727         set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4728         set_menu_format(my_menu, 5, 1);
4729                         
4730         /* Set menu mark to the string " * " */
4731         set_menu_mark(my_menu, " * ");
4732
4733         /* Print a border around the main window and print a title */
4734         box(my_menu_win, 0, 0);
4735         print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4736         mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4737         mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4738         mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4739         
4740         /* Post the menu */
4741         post_menu(my_menu);
4742         wrefresh(my_menu_win);
4743         
4744         attron(COLOR_PAIR(2));
4745         mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scoll down or up a page of items");
4746         mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)");
4747         attroff(COLOR_PAIR(2));
4748         refresh();
4749
4750         while((c = wgetch(my_menu_win)) != KEY_F(1))
4751         {       switch(c)
4752                 {       case KEY_DOWN:
4753                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4754                                 break;
4755                         case KEY_UP:
4756                                 menu_driver(my_menu, REQ_UP_ITEM);
4757                                 break;
4758                         case KEY_NPAGE:
4759                                 menu_driver(my_menu, REQ_SCR_DPAGE);
4760                                 break;
4761                         case KEY_PPAGE:
4762                                 menu_driver(my_menu, REQ_SCR_UPAGE);
4763                                 break;
4764                 }
4765                 wrefresh(my_menu_win);
4766         }       
4767
4768         /* Unpost and free all the memory taken up */
4769         unpost_menu(my_menu);
4770         free_menu(my_menu);
4771         for(i = 0; i &lt; n_choices; ++i)
4772                 free_item(my_items[i]);
4773         endwin();
4774 }
4775
4776 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4777 {       int length, x, y;
4778         float temp;
4779
4780         if(win == NULL)
4781                 win = stdscr;
4782         getyx(win, y, x);
4783         if(startx != 0)
4784                 x = startx;
4785         if(starty != 0)
4786                 y = starty;
4787         if(width == 0)
4788                 width = 80;
4789
4790         length = strlen(string);
4791         temp = (width - length)/ 2;
4792         x = startx + (int)temp;
4793         wattron(win, color);
4794         mvwprintw(win, y, x, "%s", string);
4795         wattroff(win, color);
4796         refresh();
4797 }</span>
4798 </pre>
4799         </div>
4800
4801         <p>This program is self-explanatory. In this example the
4802         number of choices has been increased to ten, which is
4803         larger than our sub window size which can hold 6 items.
4804         This message has to be explicitly conveyed to the menu
4805         system with the function set_menu_format(). In here we
4806         specify the number of rows and columns we want to be
4807         displayed for a single page. We can specify any number of
4808         items to be shown, in the rows variables, if it is less
4809         than the height of the sub window. If the key pressed by
4810         the user is a PAGE UP or PAGE DOWN, the menu is scrolled a
4811         page due to the requests (REQ_SCR_DPAGE and REQ_SCR_UPAGE)
4812         given to menu_driver().</p>
4813       </div>
4814
4815       <div class="SECT2">
4816         <hr>
4817
4818         <h3 class="SECT2"><a name="MULTICOLUMN" id=
4819         "MULTICOLUMN">17.6. Multi Columnar Menus</a></h3>
4820
4821         <p>In the above example you have seen how to use the
4822         function set_menu_format(). I didn't mention what the cols
4823         variable (third parameter) does. Well, If your sub window
4824         is wide enough, you can opt to display more than one item
4825         per row. This can be specified in the cols variable. To
4826         make things simpler, the following example doesn't show
4827         descriptions for the items.</p>
4828
4829         <div class="EXAMPLE">
4830           <a name="MMEMUCO" id="MMEMUCO"></a>
4831           <p><b>Example 21. Milt Columnar Menus Example</b>
4832           </p>
4833
4834           <pre class="PROGRAMLISTING">
4835 <span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4836 #include &lt;menu.h&gt;
4837
4838 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4839 #define CTRLD   4
4840
4841 char *choices[] = {
4842                         "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5",
4843                         "Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10",
4844                         "Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15",
4845                         "Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20",
4846                         "Exit",
4847                         (char *)NULL,
4848                   };
4849
4850 int main()
4851 {       ITEM **my_items;
4852         int c;                          
4853         MENU *my_menu;
4854         WINDOW *my_menu_win;
4855         int n_choices, i;
4856         
4857         /* Initialize curses */
4858         initscr();
4859         start_color();
4860         cbreak();
4861         noecho();
4862         keypad(stdscr, TRUE);
4863         init_pair(1, COLOR_RED, COLOR_BLACK);
4864         init_pair(2, COLOR_CYAN, COLOR_BLACK);
4865
4866         /* Create items */
4867         n_choices = ARRAY_SIZE(choices);
4868         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4869         for(i = 0; i &lt; n_choices; ++i)
4870                 my_items[i] = new_item(choices[i], choices[i]);
4871
4872         /* Crate menu */
4873         my_menu = new_menu((ITEM **)my_items);
4874
4875         /* Set menu option not to show the description */
4876         menu_opts_off(my_menu, O_SHOWDESC);
4877
4878         /* Create the window to be associated with the menu */
4879         my_menu_win = newwin(10, 70, 4, 4);
4880         keypad(my_menu_win, TRUE);
4881      
4882         /* Set main window and sub window */
4883         set_menu_win(my_menu, my_menu_win);
4884         set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1));
4885         set_menu_format(my_menu, 5, 3);
4886         set_menu_mark(my_menu, " * ");
4887
4888         /* Print a border around the main window and print a title */
4889         box(my_menu_win, 0, 0);
4890         
4891         attron(COLOR_PAIR(2));
4892         mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll");
4893         mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)");
4894         attroff(COLOR_PAIR(2));
4895         refresh();
4896
4897         /* Post the menu */
4898         post_menu(my_menu);
4899         wrefresh(my_menu_win);
4900         
4901         while((c = wgetch(my_menu_win)) != KEY_F(1))
4902         {       switch(c)
4903                 {       case KEY_DOWN:
4904                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4905                                 break;
4906                         case KEY_UP:
4907                                 menu_driver(my_menu, REQ_UP_ITEM);
4908                                 break;
4909                         case KEY_LEFT:
4910                                 menu_driver(my_menu, REQ_LEFT_ITEM);
4911                                 break;
4912                         case KEY_RIGHT:
4913                                 menu_driver(my_menu, REQ_RIGHT_ITEM);
4914                                 break;
4915                         case KEY_NPAGE:
4916                                 menu_driver(my_menu, REQ_SCR_DPAGE);
4917                                 break;
4918                         case KEY_PPAGE:
4919                                 menu_driver(my_menu, REQ_SCR_UPAGE);
4920                                 break;
4921                 }
4922                 wrefresh(my_menu_win);
4923         }       
4924
4925         /* Unpost and free all the memory taken up */
4926         unpost_menu(my_menu);
4927         free_menu(my_menu);
4928         for(i = 0; i &lt; n_choices; ++i)
4929                 free_item(my_items[i]);
4930         endwin();
4931 }</span>
4932 </pre>
4933         </div>
4934
4935         <p>Watch the function call to set_menu_format(). It
4936         specifies the number of columns to be 3, thus displaying 3
4937         items per row. We have also switched off the showing
4938         descriptions with the function menu_opts_off(). There are
4939         couple of functions set_menu_opts(), menu_opts_on() and
4940         menu_opts() which can be used to manipulate menu options.
4941         The following menu options can be specified.</p>
4942
4943         <pre class="PROGRAMLISTING">
4944        O_ONEVALUE
4945             Only one item can be selected for this menu.
4946
4947        O_SHOWDESC
4948             Display  the  item  descriptions  when  the  menu  is
4949             posted.
4950
4951        O_ROWMAJOR
4952             Display the menu in row-major order.
4953
4954        O_IGNORECASE
4955             Ignore the case when pattern-matching.
4956
4957        O_SHOWMATCH
4958             Move the cursor to within the item  name  while  pat&shy;
4959             tern-matching.
4960
4961        O_NONCYCLIC
4962             Don't   wrap   around  next-item  and  previous-item,
4963             requests to the other end of the menu.
4964 </pre>
4965         <p>All options are on by default. You can switch specific
4966         attributes on or off with menu_opts_on() and
4967         menu_opts_off() functions. You can also use set_menu_opts()
4968         to directly specify the options. The argument to this
4969         function should be a OR ed value of some of those above
4970         constants. The function menu_opts() can be used to find out
4971         a menu's present options.</p>
4972       </div>
4973
4974       <div class="SECT2">
4975         <hr>
4976
4977         <h3 class="SECT2"><a name="MULTIVALUEMENUS" id=
4978         "MULTIVALUEMENUS">17.7. Multi Valued Menus</a></h3>
4979
4980         <p>You might be wondering what if you switch off the option
4981         O_ONEVALUE. Then the menu becomes multi-valued. That means
4982         you can select more than one item. This brings us to the
4983         request REQ_TOGGLE_ITEM. Let's see it in action.</p>
4984
4985         <div class="EXAMPLE">
4986           <a name="MMETO" id="MMETO"></a>
4987           <p><b>Example 22. Multi Valued Menus example</b>
4988           </p>
4989
4990           <pre class="PROGRAMLISTING">
4991 <span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4992 #include &lt;menu.h&gt;
4993
4994 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4995 #define CTRLD   4
4996
4997 char *choices[] = {
4998                         "Choice 1",
4999                         "Choice 2",
5000                         "Choice 3",
5001                         "Choice 4",
5002                         "Choice 5",
5003                         "Choice 6",
5004                         "Choice 7",
5005                         "Exit",
5006                   };
5007
5008 int main()
5009 {       ITEM **my_items;
5010         int c;                          
5011         MENU *my_menu;
5012         int n_choices, i;
5013         ITEM *cur_item;
5014         
5015         /* Initialize curses */ 
5016         initscr();
5017         cbreak();
5018         noecho();
5019         keypad(stdscr, TRUE);
5020
5021         /* Initialize items */
5022         n_choices = ARRAY_SIZE(choices);
5023         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5024         for(i = 0; i &lt; n_choices; ++i)
5025                 my_items[i] = new_item(choices[i], choices[i]);
5026         my_items[n_choices] = (ITEM *)NULL;
5027
5028         my_menu = new_menu((ITEM **)my_items);
5029
5030         /* Make the menu multi valued */
5031         menu_opts_off(my_menu, O_ONEVALUE);
5032
5033         mvprintw(LINES - 3, 0, "Use &lt;SPACE&gt; to select or unselect an item.");
5034         mvprintw(LINES - 2, 0, "&lt;ENTER&gt; to see presently selected items(F1 to Exit)");
5035         post_menu(my_menu);
5036         refresh();
5037
5038         while((c = getch()) != KEY_F(1))
5039         {       switch(c)
5040                 {       case KEY_DOWN:
5041                                 menu_driver(my_menu, REQ_DOWN_ITEM);
5042                                 break;
5043                         case KEY_UP:
5044                                 menu_driver(my_menu, REQ_UP_ITEM);
5045                                 break;
5046                         case ' ':
5047                                 menu_driver(my_menu, REQ_TOGGLE_ITEM);
5048                                 break;
5049                         case 10:        /* Enter */
5050                         {       char temp[200];
5051                                 ITEM **items;
5052
5053                                 items = menu_items(my_menu);
5054                                 temp[0] = '\0';
5055                                 for(i = 0; i &lt; item_count(my_menu); ++i)
5056                                         if(item_value(items[i]) == TRUE)
5057                                         {       strcat(temp, item_name(items[i]));
5058                                                 strcat(temp, " ");
5059                                         }
5060                                 move(20, 0);
5061                                 clrtoeol();
5062                                 mvprintw(20, 0, temp);
5063                                 refresh();
5064                         }
5065                         break;
5066                 }
5067         }       
5068
5069         free_item(my_items[0]);
5070         free_item(my_items[1]);
5071         free_menu(my_menu);
5072         endwin();
5073 }
5074         </span>
5075 </pre>
5076         </div>
5077
5078         <p>Whew, A lot of new functions. Let's take them one after
5079         another. Firstly, the REQ_TOGGLE_ITEM. In a multi-valued
5080         menu, the user should be allowed to select or un select
5081         more than one item. The request REQ_TOGGLE_ITEM toggles the
5082         present selection. In this case when space is pressed
5083         REQ_TOGGLE_ITEM request is sent to menu_driver to achieve
5084         the result.</p>
5085
5086         <p>Now when the user presses &lt;ENTER&gt; we show the
5087         items he presently selected. First we find out the items
5088         associated with the menu using the function menu_items().
5089         Then we loop through the items to find out if the item is
5090         selected or not. The function item_value() returns TRUE if
5091         an item is selected. The function item_count() returns the
5092         number of items in the menu. The item name can be found
5093         with item_name(). You can also find the description
5094         associated with an item using item_description().</p>
5095       </div>
5096
5097       <div class="SECT2">
5098         <hr>
5099
5100         <h3 class="SECT2"><a name="MENUOPT" id="MENUOPT">17.8. Menu
5101         Options</a></h3>
5102
5103         <p>Well, by this time you must be itching for some
5104         difference in your menu, with lots of functionality. I
5105         know. You want Colors !!!. You want to create nice menus
5106         similar to those text mode <a href=
5107         "http://www.jersey.net/~debinjoe/games/" target="_top">dos
5108         games</a>. The functions set_menu_fore() and
5109         set_menu_back() can be used to change the attribute of the
5110         selected item and unselected item. The names are
5111         misleading. They don't change menu's foreground or
5112         background which would have been useless.</p>
5113
5114         <p>The function set_menu_grey() can be used to set the
5115         display attribute for the non-selectable items in the menu.
5116         This brings us to the interesting option for an item the
5117         one and only O_SELECTABLE. We can turn it off by the
5118         function item_opts_off() and after that that item is not
5119         selectable. It is like a grayed item in those fancy windows
5120         menus. Let's put these concepts in practice with this
5121         example</p>
5122
5123         <div class="EXAMPLE">
5124           <a name="MMEAT" id="MMEAT"></a>
5125           <p><b>Example 23. Menu Options example</b>
5126           </p>
5127
5128           <pre class="PROGRAMLISTING">
5129 <span class="INLINEMEDIAOBJECT">#include &lt;menu.h&gt;
5130
5131 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5132 #define CTRLD   4
5133
5134 char *choices[] = {
5135                         "Choice 1",
5136                         "Choice 2",
5137                         "Choice 3",
5138                         "Choice 4",
5139                         "Choice 5",
5140                         "Choice 6",
5141                         "Choice 7",
5142                         "Exit",
5143                   };
5144
5145 int main()
5146 {       ITEM **my_items;
5147         int c;                          
5148         MENU *my_menu;
5149         int n_choices, i;
5150         ITEM *cur_item;
5151         
5152         /* Initialize curses */ 
5153         initscr();
5154         start_color();
5155         cbreak();
5156         noecho();
5157         keypad(stdscr, TRUE);
5158         init_pair(1, COLOR_RED, COLOR_BLACK);
5159         init_pair(2, COLOR_GREEN, COLOR_BLACK);
5160         init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5161
5162         /* Initialize items */
5163         n_choices = ARRAY_SIZE(choices);
5164         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5165         for(i = 0; i &lt; n_choices; ++i)
5166                 my_items[i] = new_item(choices[i], choices[i]);
5167         my_items[n_choices] = (ITEM *)NULL;
5168         item_opts_off(my_items[3], O_SELECTABLE);
5169         item_opts_off(my_items[6], O_SELECTABLE);
5170
5171         /* Create menu */
5172         my_menu = new_menu((ITEM **)my_items);
5173
5174         /* Set fore ground and back ground of the menu */
5175         set_menu_fore(my_menu, COLOR_PAIR(1) | A_REVERSE);
5176         set_menu_back(my_menu, COLOR_PAIR(2));
5177         set_menu_grey(my_menu, COLOR_PAIR(3));
5178
5179         /* Post the menu */
5180         mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5181         mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5182         post_menu(my_menu);
5183         refresh();
5184
5185         while((c = getch()) != KEY_F(1))
5186         {       switch(c)
5187                 {       case KEY_DOWN:
5188                                 menu_driver(my_menu, REQ_DOWN_ITEM);
5189                                 break;
5190                         case KEY_UP:
5191                                 menu_driver(my_menu, REQ_UP_ITEM);
5192                                 break;
5193                         case 10: /* Enter */
5194                                 move(20, 0);
5195                                 clrtoeol();
5196                                 mvprintw(20, 0, "Item selected is : %s", 
5197                                                 item_name(current_item(my_menu)));
5198                                 pos_menu_cursor(my_menu);
5199                                 break;
5200                 }
5201         }       
5202         unpost_menu(my_menu);
5203         for(i = 0; i &lt; n_choices; ++i)
5204                 free_item(my_items[i]);
5205         free_menu(my_menu);
5206         endwin();
5207 }
5208         </span>
5209 </pre>
5210         </div>
5211       </div>
5212
5213       <div class="SECT2">
5214         <hr>
5215
5216         <h3 class="SECT2"><a name="MENUUSERPTR" id=
5217         "MENUUSERPTR">17.9. The useful User Pointer</a></h3>
5218
5219         <p>We can associate a user pointer with each item in the
5220         menu. It works the same way as user pointer in panels. It
5221         is not touched by menu system. You can store any thing you
5222         like in that. I usually use it to store the function to be
5223         executed when the menu option is chosen (It is selected and
5224         may be the user pressed &lt;ENTER&gt;);</p>
5225
5226         <div class="EXAMPLE">
5227           <a name="MMEUS" id="MMEUS"></a>
5228           <p><b>Example 24. Menu User Pointer Usage</b>
5229           </p>
5230
5231           <pre class="PROGRAMLISTING">
5232 <span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
5233 #include &lt;menu.h&gt;
5234
5235 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5236 #define CTRLD   4
5237
5238 char *choices[] = {
5239                         "Choice 1",
5240                         "Choice 2",
5241                         "Choice 3",
5242                         "Choice 4",
5243                         "Choice 5",
5244                         "Choice 6",
5245                         "Choice 7",
5246                         "Exit",
5247                   };
5248 void func(char *name);
5249
5250 int main()
5251 {       ITEM **my_items;
5252         int c;                          
5253         MENU *my_menu;
5254         int n_choices, i;
5255         ITEM *cur_item;
5256         
5257         /* Initialize curses */ 
5258         initscr();
5259         start_color();
5260         cbreak();
5261         noecho();
5262         keypad(stdscr, TRUE);
5263         init_pair(1, COLOR_RED, COLOR_BLACK);
5264         init_pair(2, COLOR_GREEN, COLOR_BLACK);
5265         init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5266
5267         /* Initialize items */
5268         n_choices = ARRAY_SIZE(choices);
5269         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5270         for(i = 0; i &lt; n_choices; ++i)
5271         {       my_items[i] = new_item(choices[i], choices[i]);
5272                 /* Set the user pointer */
5273                 set_item_userptr(my_items[i], func);
5274         }
5275         my_items[n_choices] = (ITEM *)NULL;
5276
5277         /* Create menu */
5278         my_menu = new_menu((ITEM **)my_items);
5279
5280         /* Post the menu */
5281         mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5282         mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5283         post_menu(my_menu);
5284         refresh();
5285
5286         while((c = getch()) != KEY_F(1))
5287         {       switch(c)
5288                 {       case KEY_DOWN:
5289                                 menu_driver(my_menu, REQ_DOWN_ITEM);
5290                                 break;
5291                         case KEY_UP:
5292                                 menu_driver(my_menu, REQ_UP_ITEM);
5293                                 break;
5294                         case 10: /* Enter */
5295                         {       ITEM *cur;
5296                                 void (*p)(char *);
5297
5298                                 cur = current_item(my_menu);
5299                                 p = item_userptr(cur);
5300                                 p((char *)item_name(cur));
5301                                 pos_menu_cursor(my_menu);
5302                                 break;
5303                         }
5304                         break;
5305                 }
5306         }       
5307         unpost_menu(my_menu);
5308         for(i = 0; i &lt; n_choices; ++i)
5309                 free_item(my_items[i]);
5310         free_menu(my_menu);
5311         endwin();
5312 }
5313
5314 void func(char *name)
5315 {       move(20, 0);
5316         clrtoeol();
5317         mvprintw(20, 0, "Item selected is : %s", name);
5318 }       </span>
5319 </pre>
5320         </div>
5321       </div>
5322     </div>
5323
5324     <div class="SECT1">
5325       <hr>
5326
5327       <h2 class="SECT1"><a name="FORMS" id="FORMS">18. Forms
5328       Library</a></h2>
5329
5330       <p>Well. If you have seen those forms on web pages which take
5331       input from users and do various kinds of things, you might be
5332       wondering how would any one create such forms in text mode
5333       display. It is quite difficult to write those nifty forms in
5334       plain ncurses. Forms library tries to provide a basic frame
5335       work to build and maintain forms with ease. It has lot of
5336       features(functions) which manage validation, dynamic
5337       expansion of fields etc.. Let's see it in full flow.</p>
5338
5339       <p>A form is a collection of fields; each field can be either
5340       a label(static text) or a data-entry location. The forms also
5341       library provides functions to divide forms into multiple
5342       pages.</p>
5343
5344       <div class="SECT2">
5345         <hr>
5346
5347         <h3 class="SECT2"><a name="FORMBASICS" id=
5348         "FORMBASICS">18.1. The Basics</a></h3>
5349
5350         <p>Forms are created in much the same way as menus. First
5351         the fields related to the form are created with
5352         new_field(). You can set options for the fields, so that
5353         they can be displayed with some fancy attributes, validated
5354         before the field looses focus etc.. Then the fields are
5355         attached to form. After this, the form can be posted to
5356         display and is ready to receive inputs. On the similar
5357         lines to menu_driver(), the form is manipulated with
5358         form_driver(). We can send requests to form_driver to move
5359         focus to a certain field, move cursor to end of the field
5360         etc.. After the user enters values in the fields and
5361         validation done, form can be unposted and memory allocated
5362         can be freed.</p>
5363
5364         <p>The general flow of control of a forms program looks
5365         like this.</p>
5366
5367         <ol type="1">
5368           <li>
5369             <p>Initialize curses</p>
5370           </li>
5371
5372           <li>
5373             <p>Create fields using new_field(). You can specify the
5374             height and width of the field, and its position on the
5375             form.</p>
5376           </li>
5377
5378           <li>
5379             <p>Create the forms with new_form() by specifying the
5380             fields to be attached with.</p>
5381           </li>
5382
5383           <li>
5384             <p>Post the form with form_post() and refresh the
5385             screen.</p>
5386           </li>
5387
5388           <li>
5389             <p>Process the user requests with a loop and do
5390             necessary updates to form with form_driver.</p>
5391           </li>
5392
5393           <li>
5394             <p>Unpost the menu with form_unpost()</p>
5395           </li>
5396
5397           <li>
5398             <p>Free the memory allocated to menu by free_form()</p>
5399           </li>
5400
5401           <li>
5402             <p>Free the memory allocated to the items with
5403             free_field()</p>
5404           </li>
5405
5406           <li>
5407             <p>End curses</p>
5408           </li>
5409         </ol>
5410
5411         <p>As you can see, working with forms library is much
5412         similar to handling menu library. The following examples
5413         will explore various aspects of form processing. Let's
5414         start the journey with a simple example. first.</p>
5415       </div>
5416
5417       <div class="SECT2">
5418         <hr>
5419
5420         <h3 class="SECT2"><a name="COMPILEFORMS" id=
5421         "COMPILEFORMS">18.2. Compiling With the Forms Library</a></h3>
5422
5423         <p>To use forms library functions, you have to include
5424         form.h and to link the program with forms library the flag
5425         -lform should be added along with -lncurses in that
5426         order.</p>
5427
5428         <pre class="PROGRAMLISTING">
5429     #include &lt;form.h&gt;
5430     .
5431     .
5432     .
5433
5434     compile and link: gcc &lt;program file&gt; -lform -lncurses
5435 </pre>
5436         <div class="EXAMPLE">
5437           <a name="FFOSI" id="FFOSI"></a>
5438           <p><b>Example 25. Forms Basics</b>
5439           </p>
5440
5441           <pre class="PROGRAMLISTING">
5442 <span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5443
5444 int main()
5445 {       FIELD *field[3];
5446         FORM  *my_form;
5447         int ch;
5448         
5449         /* Initialize curses */
5450         initscr();
5451         cbreak();
5452         noecho();
5453         keypad(stdscr, TRUE);
5454
5455         /* Initialize the fields */
5456         field[0] = new_field(1, 10, 4, 18, 0, 0);
5457         field[1] = new_field(1, 10, 6, 18, 0, 0);
5458         field[2] = NULL;
5459
5460         /* Set field options */
5461         set_field_back(field[0], A_UNDERLINE);  /* Print a line for the option  */
5462         field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5463                                                 /* Field is filled up           */
5464         set_field_back(field[1], A_UNDERLINE); 
5465         field_opts_off(field[1], O_AUTOSKIP);
5466
5467         /* Create the form and post it */
5468         my_form = new_form(field);
5469         post_form(my_form);
5470         refresh();
5471         
5472         mvprintw(4, 10, "Value 1:");
5473         mvprintw(6, 10, "Value 2:");
5474         refresh();
5475
5476         /* Loop through to get user requests */
5477         while((ch = getch()) != KEY_F(1))
5478         {       switch(ch)
5479                 {       case KEY_DOWN:
5480                                 /* Go to next field */
5481                                 form_driver(my_form, REQ_NEXT_FIELD);
5482                                 /* Go to the end of the present buffer */
5483                                 /* Leaves nicely at the last character */
5484                                 form_driver(my_form, REQ_END_LINE);
5485                                 break;
5486                         case KEY_UP:
5487                                 /* Go to previous field */
5488                                 form_driver(my_form, REQ_PREV_FIELD);
5489                                 form_driver(my_form, REQ_END_LINE);
5490                                 break;
5491                         default:
5492                                 /* If this is a normal character, it gets */
5493                                 /* Printed                                */    
5494                                 form_driver(my_form, ch);
5495                                 break;
5496                 }
5497         }
5498
5499         /* Un post form and free the memory */
5500         unpost_form(my_form);
5501         free_form(my_form);
5502         free_field(field[0]);
5503         free_field(field[1]); 
5504
5505         endwin();
5506         return 0;
5507 }</span>
5508 </pre>
5509         </div>
5510
5511         <p>Above example is pretty straight forward. It creates two
5512         fields with <tt class="LITERAL">new_field()</tt>.
5513         new_field() takes height, width, starty, startx, number of
5514         offscreen rows and number of additional working buffers.
5515         The fifth argument number of offscreen rows specifies how
5516         much of the field to be shown. If it is zero, the entire
5517         field is always displayed otherwise the form will be
5518         scrollable when the user accesses not displayed parts of
5519         the field. The forms library allocates one buffer per field
5520         to store the data user enters. Using the last parameter to
5521         new_field() we can specify it to allocate some additional
5522         buffers. These can be used for any purpose you like.</p>
5523
5524         <p>After creating the fields, back ground attribute of both
5525         of them is set to an underscore with set_field_back(). The
5526         AUTOSKIP option is turned off using field_opts_off(). If
5527         this option is turned on, focus will move to the next field
5528         in the form once the active field is filled up
5529         completely.</p>
5530
5531         <p>After attaching the fields to the form, it is posted.
5532         Here on, user inputs are processed in the while loop, by
5533         making corresponding requests to form_driver. The details
5534         of all the requests to the form_driver() are explained
5535         later.</p>
5536       </div>
5537
5538       <div class="SECT2">
5539         <hr>
5540
5541         <h3 class="SECT2"><a name="PLAYFIELDS" id=
5542         "PLAYFIELDS">18.3. Playing with Fields</a></h3>
5543
5544         <p>Each form field is associated with a lot of attributes.
5545         They can be manipulated to get the required effect and to
5546         have fun !!!. So why wait?</p>
5547
5548         <div class="SECT3">
5549           <hr>
5550
5551           <h4 class="SECT3"><a name="FETCHINFO" id=
5552           "FETCHINFO">18.3.1. Fetching Size and Location of
5553           Field</a></h4>
5554
5555           <p>The parameters we have given at the time of creation
5556           of a field can be retrieved with field_info(). It returns
5557           height, width, starty, startx, number of offscreen rows,
5558           and number of additional buffers into the parameters
5559           given to it. It is a sort of inverse of new_field().</p>
5560
5561           <pre class="PROGRAMLISTING">
5562 int field_info(     FIELD *field,              /* field from which to fetch */
5563                     int *height, *int width,   /* field size */ 
5564                     int *top, int *left,       /* upper left corner */
5565                     int *offscreen,            /* number of offscreen rows */
5566                     int *nbuf);                /* number of working buffers */
5567 </pre>
5568         </div>
5569
5570         <div class="SECT3">
5571           <hr>
5572
5573           <h4 class="SECT3"><a name="MOVEFIELD" id=
5574           "MOVEFIELD">18.3.2. Moving the field</a></h4>
5575
5576           <p>The location of the field can be moved to a different
5577           position with move_field().</p>
5578
5579           <pre class="PROGRAMLISTING">
5580 int move_field(    FIELD *field,              /* field to alter */
5581                    int top, int left);        /* new upper-left corner */
5582 </pre>
5583           <p>As usual, the changed position can be queried with
5584           field_infor().</p>
5585         </div>
5586
5587         <div class="SECT3">
5588           <hr>
5589
5590           <h4 class="SECT3"><a name="JUSTIFYFIELD" id=
5591           "JUSTIFYFIELD">18.3.3. Field Justification</a></h4>
5592
5593           <p>The justification to be done for the field can be
5594           fixed using the function set_field_just().</p>
5595
5596           <pre class="PROGRAMLISTING">
5597     int set_field_just(FIELD *field,          /* field to alter */
5598                int justmode);         /* mode to set */
5599     int field_just(FIELD *field);          /* fetch justify mode of field */
5600 </pre>
5601           <p>The justification mode valued accepted and returned by
5602           these functions are NO_JUSTIFICATION, JUSTIFY_RIGHT,
5603           JUSTIFY_LEFT, or JUSTIFY_CENTER.</p>
5604         </div>
5605
5606         <div class="SECT3">
5607           <hr>
5608
5609           <h4 class="SECT3"><a name="FIELDDISPATTRIB" id=
5610           "FIELDDISPATTRIB">18.3.4. Field Display Attributes</a></h4>
5611
5612           <p>As you have seen, in the above example, display
5613           attribute for the fields can be set with set_field_fore()
5614           and setfield_back(). These functions set foreground and
5615           background attribute of the fields. You can also specify
5616           a pad character which will be filled in the unfilled
5617           portion of the field. The pad character is set with a
5618           call to set_field_pad(). Default pad value is a space.
5619           The functions field_fore(), field_back, field_pad() can
5620           be used to query the present foreground, background
5621           attributes and pad character for the field. The following
5622           list gives the usage of functions.</p>
5623
5624           <pre class="PROGRAMLISTING">
5625 &#13;int set_field_fore(FIELD *field,        /* field to alter */
5626                    chtype attr);        /* attribute to set */ 
5627
5628 chtype field_fore(FIELD *field);        /* field to query */
5629                                         /* returns foreground attribute */
5630
5631 int set_field_back(FIELD *field,        /* field to alter */
5632                    chtype attr);        /* attribute to set */ 
5633
5634 chtype field_back(FIELD *field);        /* field to query */
5635                                         /* returns background attribute */
5636
5637 int set_field_pad(FIELD *field,         /* field to alter */
5638                   int pad);             /* pad character to set */ 
5639
5640 chtype field_pad(FIELD *field);         /* field to query */  
5641                                         /* returns present pad character */&#13;
5642 </pre>
5643           <p>Though above functions seem quite simple, using colors
5644           with set_field_fore() may be frustrating in the
5645           beginning. Let me first explain about foreground and
5646           background attributes of a field. The foreground
5647           attribute is associated with the character. That means a
5648           character in the field is printed with the attribute you
5649           have set with set_field_fore(). Background attribute is
5650           the attribute used to fill background of field, whether
5651           any character is there or not. So what about colors?
5652           Since colors are always defined in pairs, what is the
5653           right way to display colored fields? Here's an example
5654           clarifying color attributes.</p>
5655
5656           <div class="EXAMPLE">
5657             <a name="FFOAT" id="FFOAT"></a>
5658             <p><b>Example 26. Form Attributes example</b>
5659             </p>
5660
5661             <pre class="PROGRAMLISTING">
5662 <span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5663
5664 int main()
5665 {       FIELD *field[3];
5666         FORM  *my_form;
5667         int ch;
5668         
5669         /* Initialize curses */
5670         initscr();
5671         start_color();
5672         cbreak();
5673         noecho();
5674         keypad(stdscr, TRUE);
5675
5676         /* Initialize few color pairs */
5677         init_pair(1, COLOR_WHITE, COLOR_BLUE);
5678         init_pair(2, COLOR_WHITE, COLOR_BLUE);
5679
5680         /* Initialize the fields */
5681         field[0] = new_field(1, 10, 4, 18, 0, 0);
5682         field[1] = new_field(1, 10, 6, 18, 0, 0);
5683         field[2] = NULL;
5684
5685         /* Set field options */
5686         set_field_fore(field[0], COLOR_PAIR(1));/* Put the field with blue background */
5687         set_field_back(field[0], COLOR_PAIR(2));/* and white foreground (characters */
5688                                                 /* are printed in white         */
5689         field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5690                                                 /* Field is filled up           */
5691         set_field_back(field[1], A_UNDERLINE); 
5692         field_opts_off(field[1], O_AUTOSKIP);
5693
5694         /* Create the form and post it */
5695         my_form = new_form(field);
5696         post_form(my_form);
5697         refresh();
5698         
5699         set_current_field(my_form, field[0]); /* Set focus to the colored field */
5700         mvprintw(4, 10, "Value 1:");
5701         mvprintw(6, 10, "Value 2:");
5702         mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
5703         refresh();
5704
5705         /* Loop through to get user requests */
5706         while((ch = getch()) != KEY_F(1))
5707         {       switch(ch)
5708                 {       case KEY_DOWN:
5709                                 /* Go to next field */
5710                                 form_driver(my_form, REQ_NEXT_FIELD);
5711                                 /* Go to the end of the present buffer */
5712                                 /* Leaves nicely at the last character */
5713                                 form_driver(my_form, REQ_END_LINE);
5714                                 break;
5715                         case KEY_UP:
5716                                 /* Go to previous field */
5717                                 form_driver(my_form, REQ_PREV_FIELD);
5718                                 form_driver(my_form, REQ_END_LINE);
5719                                 break;
5720                         default:
5721                                 /* If this is a normal character, it gets */
5722                                 /* Printed                                */    
5723                                 form_driver(my_form, ch);
5724                                 break;
5725                 }
5726         }
5727
5728         /* Un post form and free the memory */
5729         unpost_form(my_form);
5730         free_form(my_form);
5731         free_field(field[0]);
5732         free_field(field[1]); 
5733
5734         endwin();
5735         return 0;
5736 }</span>
5737 </pre>
5738           </div>
5739
5740           <p>Play with the color pairs and try to understand the
5741           foreground and background attributes. In my programs
5742           using color attributes, I usually set only the background
5743           with set_field_back(). Curses simply doesn't allow
5744           defining individual color attributes.</p>
5745         </div>
5746
5747         <div class="SECT3">
5748           <hr>
5749
5750           <h4 class="SECT3"><a name="FIELDOPTIONBITS" id=
5751           "FIELDOPTIONBITS">18.3.5. Field Option Bits</a></h4>
5752
5753           <p>There is also a large collection of field option bits
5754           you can set to control various aspects of forms
5755           processing. You can manipulate them with these
5756           functions:</p>
5757
5758           <pre class="PROGRAMLISTING">
5759 int set_field_opts(FIELD *field,          /* field to alter */
5760                    int attr);             /* attribute to set */ 
5761
5762 int field_opts_on(FIELD *field,           /* field to alter */
5763                   int attr);              /* attributes to turn on */ 
5764
5765 int field_opts_off(FIELD *field,          /* field to alter */
5766                   int attr);              /* attributes to turn off */ 
5767
5768 int field_opts(FIELD *field);             /* field to query */ 
5769 </pre>
5770           <p>The function set_field_opts() can be used to directly
5771           set attributes of a field or you can choose to switch a
5772           few attributes on and off with field_opts_on() and
5773           field_opts_off() selectively. Anytime you can query the
5774           attributes of a field with field_opts(). The following is
5775           the list of available options. By default, all options
5776           are on.</p>
5777
5778           <div class="VARIABLELIST">
5779             <dl>
5780               <dt>O_VISIBLE</dt>
5781
5782               <dd>
5783                 <p>Controls whether the field is visible on the
5784                 screen. Can be used during form processing to hide
5785                 or pop up fields depending on the value of parent
5786                 fields.</p>
5787               </dd>
5788
5789               <dt>O_ACTIVE</dt>
5790
5791               <dd>
5792                 <p>Controls whether the field is active during
5793                 forms processing (i.e. visited by form navigation
5794                 keys). Can be used to make labels or derived fields
5795                 with buffer values alterable by the forms
5796                 application, not the user.</p>
5797               </dd>
5798
5799               <dt>O_PUBLIC</dt>
5800
5801               <dd>
5802                 <p>Controls whether data is displayed during field
5803                 entry. If this option is turned off on a field, the
5804                 library will accept and edit data in that field,
5805                 but it will not be displayed and the visible field
5806                 cursor will not move. You can turn off the O_PUBLIC
5807                 bit to define password fields.</p>
5808               </dd>
5809
5810               <dt>O_EDIT</dt>
5811
5812               <dd>
5813                 <p>Controls whether the field's data can be
5814                 modified. When this option is off, all editing
5815                 requests except <tt class=
5816                 "LITERAL">REQ_PREV_CHOICE</tt> and <tt class=
5817                 "LITERAL">REQ_NEXT_CHOICE</tt>will fail. Such
5818                 read-only fields may be useful for help
5819                 messages.</p>
5820               </dd>
5821
5822               <dt>O_WRAP</dt>
5823
5824               <dd>
5825                 <p>Controls word-wrapping in multi-line fields.
5826                 Normally, when any character of a (blank-separated)
5827                 word reaches the end of the current line, the
5828                 entire word is wrapped to the next line (assuming
5829                 there is one). When this option is off, the word
5830                 will be split across the line break.</p>
5831               </dd>
5832
5833               <dt>O_BLANK</dt>
5834
5835               <dd>
5836                 <p>Controls field blanking. When this option is on,
5837                 entering a character at the first field position
5838                 erases the entire field (except for the
5839                 just-entered character).</p>
5840               </dd>
5841
5842               <dt>O_AUTOSKIP</dt>
5843
5844               <dd>
5845                 <p>Controls automatic skip to next field when this
5846                 one fills. Normally, when the forms user tries to
5847                 type more data into a field than will fit, the
5848                 editing location jumps to next field. When this
5849                 option is off, the user's cursor will hang at the
5850                 end of the field. This option is ignored in dynamic
5851                 fields that have not reached their size limit.</p>
5852               </dd>
5853
5854               <dt>O_NULLOK</dt>
5855
5856               <dd>
5857                 <p>Controls whether validation is applied to blank
5858                 fields. Normally, it is not; the user can leave a
5859                 field blank without invoking the usual validation
5860                 check on exit. If this option is off on a field,
5861                 exit from it will invoke a validation check.</p>
5862               </dd>
5863
5864               <dt>O_PASSOK</dt>
5865
5866               <dd>
5867                 <p>Controls whether validation occurs on every
5868                 exit, or only after the field is modified. Normally
5869                 the latter is true. Setting O_PASSOK may be useful
5870                 if your field's validation function may change
5871                 during forms processing.</p>
5872               </dd>
5873
5874               <dt>O_STATIC</dt>
5875
5876               <dd>
5877                 <p>Controls whether the field is fixed to its
5878                 initial dimensions. If you turn this off, the field
5879                 becomes dynamic and will stretch to fit entered
5880                 data.</p>
5881               </dd>
5882             </dl>
5883           </div>
5884
5885           <p>A field's options cannot be changed while the field is
5886           currently selected. However, options may be changed on
5887           posted fields that are not current.</p>
5888
5889           <p>The option values are bit-masks and can be composed
5890           with logical-or in the obvious way. You have seen the
5891           usage of switching off O_AUTOSKIP option. The following
5892           example clarifies usage of some more options. Other
5893           options are explained where appropriate.</p>
5894
5895           <div class="EXAMPLE">
5896             <a name="FFOOP" id="FFOOP"></a>
5897             <p><b>Example 27. Field Options Usage example</b>
5898             </p>
5899
5900             <pre class="PROGRAMLISTING">
5901 <span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5902
5903 #define STARTX 15
5904 #define STARTY 4
5905 #define WIDTH 25
5906
5907 #define N_FIELDS 3
5908
5909 int main()
5910 {       FIELD *field[N_FIELDS];
5911         FORM  *my_form;
5912         int ch, i;
5913         
5914         /* Initialize curses */
5915         initscr();
5916         cbreak();
5917         noecho();
5918         keypad(stdscr, TRUE);
5919
5920         /* Initialize the fields */
5921         for(i = 0; i &lt; N_FIELDS - 1; ++i)
5922                 field[i] = new_field(1, WIDTH, STARTY + i * 2, STARTX, 0, 0);
5923         field[N_FIELDS - 1] = NULL;
5924
5925         /* Set field options */
5926         set_field_back(field[1], A_UNDERLINE);  /* Print a line for the option  */
5927         
5928         field_opts_off(field[0], O_ACTIVE); /* This field is a static label */
5929         field_opts_off(field[1], O_PUBLIC); /* This filed is like a password field*/
5930         field_opts_off(field[1], O_AUTOSKIP); /* To avoid entering the same field */
5931                                               /* after last character is entered */
5932         
5933         /* Create the form and post it */
5934         my_form = new_form(field);
5935         post_form(my_form);
5936         refresh();
5937         
5938         set_field_just(field[0], JUSTIFY_CENTER); /* Center Justification */
5939         set_field_buffer(field[0], 0, "This is a static Field"); 
5940                                                   /* Initialize the field  */
5941         mvprintw(STARTY, STARTX - 10, "Field 1:");
5942         mvprintw(STARTY + 2, STARTX - 10, "Field 2:");
5943         refresh();
5944
5945         /* Loop through to get user requests */
5946         while((ch = getch()) != KEY_F(1))
5947         {       switch(ch)
5948                 {       case KEY_DOWN:
5949                                 /* Go to next field */
5950                                 form_driver(my_form, REQ_NEXT_FIELD);
5951                                 /* Go to the end of the present buffer */
5952                                 /* Leaves nicely at the last character */
5953                                 form_driver(my_form, REQ_END_LINE);
5954                                 break;
5955                         case KEY_UP:
5956                                 /* Go to previous field */
5957                                 form_driver(my_form, REQ_PREV_FIELD);
5958                                 form_driver(my_form, REQ_END_LINE);
5959                                 break;
5960                         default:
5961                                 /* If this is a normal character, it gets */
5962                                 /* Printed                                */    
5963                                 form_driver(my_form, ch);
5964                                 break;
5965                 }
5966         }
5967
5968         /* Un post form and free the memory */
5969         unpost_form(my_form);
5970         free_form(my_form);
5971         free_field(field[0]);
5972         free_field(field[1]); 
5973
5974         endwin();
5975         return 0;
5976 }</span>
5977 </pre>
5978           </div>
5979
5980           <p>This example, though useless, shows the usage of
5981           options. If used properly, they can present information
5982           very effectively in a form. The second field being not
5983           O_PUBLIC, does not show the characters you are
5984           typing.</p>
5985         </div>
5986
5987         <div class="SECT3">
5988           <hr>
5989
5990           <h4 class="SECT3"><a name="FIELDSTATUS" id=
5991           "FIELDSTATUS">18.3.6. Field Status</a></h4>
5992
5993           <p>The field status specifies whether the field has got
5994           edited or not. It is initially set to FALSE and when user
5995           enters something and the data buffer gets modified it
5996           becomes TRUE. So a field's status can be queried to find
5997           out whether it has been modified or not. The following
5998           functions can assist in those operations.</p>
5999
6000           <pre class="PROGRAMLISTING">
6001 int set_field_status(FIELD *field,      /* field to alter */
6002                    int status);         /* status to set */
6003
6004 int field_status(FIELD *field);         /* fetch status of field */
6005 </pre>
6006           <p>It is better to check the field's status only after
6007           after leaving the field, as data buffer might not have
6008           been updated yet as the validation is still due. To
6009           guarantee that right status is returned, call
6010           field_status() either (1) in the field's exit validation
6011           check routine, (2) from the field's or form's
6012           initialization or termination hooks, or (3) just after a
6013           REQ_VALIDATION request has been processed by the forms
6014           driver</p>
6015         </div>
6016
6017         <div class="SECT3">
6018           <hr>
6019
6020           <h4 class="SECT3"><a name="FIELDUSERPTR" id=
6021           "FIELDUSERPTR">18.3.7. Field User Pointer</a></h4>
6022
6023           <p>Every field structure contains one pointer that can be
6024           used by the user for various purposes. It is not touched
6025           by forms library and can be used for any purpose by the
6026           user. The following functions set and fetch user
6027           pointer.</p>
6028
6029           <pre class="PROGRAMLISTING">
6030 int set_field_userptr(FIELD *field,   
6031            char *userptr);      /* the user pointer you wish to associate */
6032                                 /* with the field    */
6033
6034 char *field_userptr(FIELD *field);      /* fetch user pointer of the field */
6035 </pre>
6036         </div>
6037
6038         <div class="SECT3">
6039           <hr>
6040
6041           <h4 class="SECT3"><a name="VARIABLESIZEFIELDS" id=
6042           "VARIABLESIZEFIELDS">18.3.8. Variable-Sized Fields</a></h4>
6043
6044           <p>If you want a dynamically changing field with variable
6045           width, this is the feature you want to put to full use.
6046           This will allow the user to enter more data than the
6047           original size of the field and let the field grow.
6048           According to the field orientation it will scroll
6049           horizontally or vertically to incorporate the new
6050           data.</p>
6051
6052           <p>To make a field dynamically growable, the option
6053           O_STATIC should be turned off. This can be done with
6054           a</p>
6055
6056           <pre class="PROGRAMLISTING">
6057     field_opts_off(field_pointer, O_STATIC);
6058 </pre>
6059           <p>But it is usually not advisable to allow a field to
6060           grow infinitely. You can set a maximum limit to the
6061           growth of the field with</p>
6062
6063           <pre class="PROGRAMLISTING">
6064 int set_max_field(FIELD *field,    /* Field on which to operate */
6065                   int max_growth); /* maximum growth allowed for the field */
6066 </pre>
6067           <p>The field info for a dynamically growable field can be
6068           retrieved by</p>
6069
6070           <pre class="PROGRAMLISTING">
6071 int dynamic_field_info( FIELD *field,     /* Field on which to operate */
6072             int   *prows,     /* number of rows will be filled in this */
6073             int   *pcols,     /* number of columns will be filled in this*/
6074             int   *pmax)      /* maximum allowable growth will be filled */
6075                               /* in this */
6076 </pre>Though field_info work as usual, it is advisable to use this
6077 function to get the proper attributes of a dynamically growable
6078 field.
6079           <p>Recall the library routine new_field; a new field
6080           created with height set to one will be defined to be a
6081           one line field. A new field created with height greater
6082           than one will be defined to be a multi line field.</p>
6083
6084           <p>A one line field with O_STATIC turned off (dynamically
6085           growable field) will contain a single fixed row, but the
6086           number of columns can increase if the user enters more
6087           data than the initial field will hold. The number of
6088           columns displayed will remain fixed and the additional
6089           data will scroll horizontally.</p>
6090
6091           <p>A multi line field with O_STATIC turned off
6092           (dynamically growable field) will contain a fixed number
6093           of columns, but the number of rows can increase if the
6094           user enters more data than the initial field will hold.
6095           The number of rows displayed will remain fixed and the
6096           additional data will scroll vertically.</p>
6097
6098           <p>The above two paragraphs pretty much describe a
6099           dynamically growable field's behavior. The way other
6100           parts of forms library behaves is described below:</p>
6101
6102           <ol type="1">
6103             <li>
6104               <p>The field option O_AUTOSKIP will be ignored if the
6105               option O_STATIC is off and there is no maximum growth
6106               specified for the field. Currently, O_AUTOSKIP
6107               generates an automatic REQ_NEXT_FIELD form driver
6108               request when the user types in the last character
6109               position of a field. On a growable field with no
6110               maximum growth specified, there is no last character
6111               position. If a maximum growth is specified, the
6112               O_AUTOSKIP option will work as normal if the field
6113               has grown to its maximum size.</p>
6114             </li>
6115
6116             <li>
6117               <p>The field justification will be ignored if the
6118               option O_STATIC is off. Currently, set_field_just can
6119               be used to JUSTIFY_LEFT, JUSTIFY_RIGHT,
6120               JUSTIFY_CENTER the contents of a one line field. A
6121               growable one line field will, by definition, grow and
6122               scroll horizontally and may contain more data than
6123               can be justified. The return from field_just will be
6124               unchanged.</p>
6125             </li>
6126
6127             <li>
6128               <p>The overloaded form driver request REQ_NEW_LINE
6129               will operate the same way regardless of the
6130               O_NL_OVERLOAD form option if the field option
6131               O_STATIC is off and there is no maximum growth
6132               specified for the field. Currently, if the form
6133               option O_NL_OVERLOAD is on, REQ_NEW_LINE implicitly
6134               generates a REQ_NEXT_FIELD if called from the last
6135               line of a field. If a field can grow without bound,
6136               there is no last line, so REQ_NEW_LINE will never
6137               implicitly generate a REQ_NEXT_FIELD. If a maximum
6138               growth limit is specified and the O_NL_OVERLOAD form
6139               option is on, REQ_NEW_LINE will only implicitly
6140               generate REQ_NEXT_FIELD if the field has grown to its
6141               maximum size and the user is on the last line.</p>
6142             </li>
6143
6144             <li>
6145               <p>The library call dup_field will work as usual; it
6146               will duplicate the field, including the current
6147               buffer size and contents of the field being
6148               duplicated. Any specified maximum growth will also be
6149               duplicated.</p>
6150             </li>
6151
6152             <li>
6153               <p>The library call link_field will work as usual; it
6154               will duplicate all field attributes and share buffers
6155               with the field being linked. If the O_STATIC field
6156               option is subsequently changed by a field sharing
6157               buffers, how the system reacts to an attempt to enter
6158               more data into the field than the buffer will
6159               currently hold will depend on the setting of the
6160               option in the current field.</p>
6161             </li>
6162
6163             <li>
6164               <p>The library call field_info will work as usual;
6165               the variable nrow will contain the value of the
6166               original call to new_field. The user should use
6167               dynamic_field_info, described above, to query the
6168               current size of the buffer.</p>
6169             </li>
6170           </ol>
6171
6172           <p>Some of the above points make sense only after
6173           explaining form driver. We will be looking into that in
6174           next few sections.</p>
6175         </div>
6176       </div>
6177
6178       <div class="SECT2">
6179         <hr>
6180
6181         <h3 class="SECT2"><a name="FORMWINDOWS" id=
6182         "FORMWINDOWS">18.4. Form Windows</a></h3>
6183
6184         <p>The form windows concept is pretty much similar to menu
6185         windows. Every form is associated with a main window and a
6186         sub window. The form main window displays any title or
6187         border associated or whatever the user wishes. Then the sub
6188         window contains all the fields and displays them according
6189         to their position. This gives the flexibility of
6190         manipulating fancy form displaying very easily.</p>
6191
6192         <p>Since this is pretty much similar to menu windows, I am
6193         providing an example with out much explanation. The
6194         functions are similar and they work the same way.</p>
6195
6196         <div class="EXAMPLE">
6197           <a name="FFOWI" id="FFOWI"></a>
6198           <p><b>Example 28. Form Windows Example</b>
6199           </p>
6200
6201           <pre class="PROGRAMLISTING">
6202 <span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
6203
6204 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
6205
6206 int main()
6207 {
6208         FIELD *field[3];
6209         FORM  *my_form;
6210         WINDOW *my_form_win;
6211         int ch, rows, cols;
6212         
6213         /* Initialize curses */
6214         initscr();
6215         start_color();
6216         cbreak();
6217         noecho();
6218         keypad(stdscr, TRUE);
6219
6220         /* Initialize few color pairs */
6221         init_pair(1, COLOR_RED, COLOR_BLACK);
6222
6223         /* Initialize the fields */
6224         field[0] = new_field(1, 10, 6, 1, 0, 0);
6225         field[1] = new_field(1, 10, 8, 1, 0, 0);
6226         field[2] = NULL;
6227
6228         /* Set field options */
6229         set_field_back(field[0], A_UNDERLINE);
6230         field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */
6231                                               /* Field is filled up             */
6232         set_field_back(field[1], A_UNDERLINE); 
6233         field_opts_off(field[1], O_AUTOSKIP);
6234         
6235         /* Create the form and post it */
6236         my_form = new_form(field);
6237         
6238         /* Calculate the area required for the form */
6239         scale_form(my_form, &amp;rows, &amp;cols);
6240
6241         /* Create the window to be associated with the form */
6242         my_form_win = newwin(rows + 4, cols + 4, 4, 4);
6243         keypad(my_form_win, TRUE);
6244
6245         /* Set main window and sub window */
6246         set_form_win(my_form, my_form_win);
6247         set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2));
6248
6249         /* Print a border around the main window and print a title */
6250         box(my_form_win, 0, 0);
6251         print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1));
6252         
6253         post_form(my_form);
6254         wrefresh(my_form_win);
6255
6256         mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
6257         refresh();
6258
6259         /* Loop through to get user requests */
6260         while((ch = wgetch(my_form_win)) != KEY_F(1))
6261         {       switch(ch)
6262                 {       case KEY_DOWN:
6263                                 /* Go to next field */
6264                                 form_driver(my_form, REQ_NEXT_FIELD);
6265                                 /* Go to the end of the present buffer */
6266                                 /* Leaves nicely at the last character */
6267                                 form_driver(my_form, REQ_END_LINE);
6268                                 break;
6269                         case KEY_UP:
6270                                 /* Go to previous field */
6271                                 form_driver(my_form, REQ_PREV_FIELD);
6272                                 form_driver(my_form, REQ_END_LINE);
6273                                 break;
6274                         default:
6275                                 /* If this is a normal character, it gets */
6276                                 /* Printed                                */    
6277                                 form_driver(my_form, ch);
6278                                 break;
6279                 }
6280         }
6281
6282         /* Un post form and free the memory */
6283         unpost_form(my_form);
6284         free_form(my_form);
6285         free_field(field[0]);
6286         free_field(field[1]); 
6287
6288         endwin();
6289         return 0;
6290 }
6291
6292 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
6293 {       int length, x, y;
6294         float temp;
6295
6296         if(win == NULL)
6297                 win = stdscr;
6298         getyx(win, y, x);
6299         if(startx != 0)
6300                 x = startx;
6301         if(starty != 0)
6302                 y = starty;
6303         if(width == 0)
6304                 width = 80;
6305
6306         length = strlen(string);
6307         temp = (width - length)/ 2;
6308         x = startx + (int)temp;
6309         wattron(win, color);
6310         mvwprintw(win, y, x, "%s", string);
6311         wattroff(win, color);
6312         refresh();
6313 }</span>
6314 </pre>
6315         </div>
6316       </div>
6317
6318       <div class="SECT2">
6319         <hr>
6320
6321         <h3 class="SECT2"><a name="FILEDVALIDATE" id=
6322         "FILEDVALIDATE">18.5. Field Validation</a></h3>
6323
6324         <p>By default, a field will accept any data input by the
6325         user. It is possible to attach validation to the field.
6326         Then any attempt by the user to leave the field, while it
6327         contains data that doesn't match the validation type will
6328         fail. Some validation types also have a character-validity
6329         check for each time a character is entered in the
6330         field.</p>
6331
6332         <p>Validation can be attached to a field with the following
6333         function.</p>
6334
6335         <pre class="PROGRAMLISTING">
6336 int set_field_type(FIELD *field,          /* field to alter */
6337                    FIELDTYPE *ftype,      /* type to associate */
6338                    ...);                  /* additional arguments*/
6339 </pre>Once set, the validation type for a field can be queried with
6340
6341         <pre class="PROGRAMLISTING">
6342 FIELDTYPE *field_type(FIELD *field);      /* field to query */
6343 </pre>
6344         <p>The form driver validates the data in a field only when
6345         data is entered by the end-user. Validation does not occur
6346         when</p>
6347
6348         <ul>
6349           <li>
6350             <p>the application program changes the field value by
6351             calling set_field_buffer.</p>
6352           </li>
6353
6354           <li>
6355             <p>linked field values are changed indirectly -- by
6356             changing the field to which they are linked</p>
6357           </li>
6358         </ul>
6359
6360         <p>The following are the pre-defined validation types. You
6361         can also specify custom validation, though it is a bit
6362         tricky and cumbersome.</p>
6363
6364         <h1 class="BRIDGEHEAD"><a name="AEN1069" id=
6365         "AEN1069"></a>TYPE_ALPHA</h1>
6366
6367         <p>This field type accepts alphabetic data; no blanks, no
6368         digits, no special characters (this is checked at
6369         character-entry time). It is set up with:</p>
6370
6371         <pre class="PROGRAMLISTING">
6372 int set_field_type(FIELD *field,          /* field to alter */
6373                    TYPE_ALPHA,            /* type to associate */
6374                    int width);            /* minimum width of field */
6375 </pre>
6376         <p>The width argument sets a minimum width of data. The
6377         user has to enter at-least width number of characters
6378         before he can leave the field. Typically you'll want to set
6379         this to the field width; if it is greater than the field
6380         width, the validation check will always fail. A minimum
6381         width of zero makes field completion optional.</p>
6382
6383         <h1 class="BRIDGEHEAD"><a name="AEN1073" id=
6384         "AEN1073"></a>TYPE_ALNUM</h1>
6385
6386         <p>This field type accepts alphabetic data and digits; no
6387         blanks, no special characters (this is checked at
6388         character-entry time). It is set up with:</p>
6389
6390         <pre class="PROGRAMLISTING">
6391 int set_field_type(FIELD *field,          /* field to alter */
6392                    TYPE_ALNUM,            /* type to associate */
6393                    int width);            /* minimum width of field */
6394 </pre>
6395         <p>The width argument sets a minimum width of data. As with
6396         TYPE_ALPHA, typically you'll want to set this to the field
6397         width; if it is greater than the field width, the
6398         validation check will always fail. A minimum width of zero
6399         makes field completion optional.</p>
6400
6401         <h1 class="BRIDGEHEAD"><a name="AEN1077" id=
6402         "AEN1077"></a>TYPE_ENUM</h1>
6403
6404         <p>This type allows you to restrict a field's values to be
6405         among a specified set of string values (for example, the
6406         two-letter postal codes for U.S. states). It is set up
6407         with:</p>
6408
6409         <pre class="PROGRAMLISTING">
6410 int set_field_type(FIELD *field,          /* field to alter */
6411                    TYPE_ENUM,             /* type to associate */
6412                    char **valuelist;      /* list of possible values */
6413                    int checkcase;         /* case-sensitive? */
6414                    int checkunique);      /* must specify uniquely? */
6415 </pre>
6416         <p>The valuelist parameter must point at a NULL-terminated
6417         list of valid strings. The checkcase argument, if true,
6418         makes comparison with the string case-sensitive.</p>
6419
6420         <p>When the user exits a TYPE_ENUM field, the validation
6421         procedure tries to complete the data in the buffer to a
6422         valid entry. If a complete choice string has been entered,
6423         it is of course valid. But it is also possible to enter a
6424         prefix of a valid string and have it completed for you.</p>
6425
6426         <p>By default, if you enter such a prefix and it matches
6427         more than one value in the string list, the prefix will be
6428         completed to the first matching value. But the checkunique
6429         argument, if true, requires prefix matches to be unique in
6430         order to be valid.</p>
6431
6432         <p>The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests
6433         can be particularly useful with these fields.</p>
6434
6435         <h1 class="BRIDGEHEAD"><a name="AEN1084" id=
6436         "AEN1084"></a>TYPE_INTEGER</h1>
6437
6438         <p>This field type accepts an integer. It is set up as
6439         follows:</p>
6440
6441         <pre class="PROGRAMLISTING">
6442 int set_field_type(FIELD *field,          /* field to alter */
6443                    TYPE_INTEGER,          /* type to associate */
6444                    int padding,           /* # places to zero-pad to */
6445                    int vmin, int vmax);   /* valid range */
6446 </pre>
6447         <p>Valid characters consist of an optional leading minus
6448         and digits. The range check is performed on exit. If the
6449         range maximum is less than or equal to the minimum, the
6450         range is ignored.</p>
6451
6452         <p>If the value passes its range check, it is padded with
6453         as many leading zero digits as necessary to meet the
6454         padding argument.</p>
6455
6456         <p>A TYPE_INTEGER value buffer can conveniently be
6457         interpreted with the C library function atoi(3).</p>
6458
6459         <h1 class="BRIDGEHEAD"><a name="AEN1090" id=
6460         "AEN1090"></a>TYPE_NUMERIC</h1>
6461
6462         <p>This field type accepts a decimal number. It is set up
6463         as follows:</p>
6464
6465         <pre class="PROGRAMLISTING">
6466 int set_field_type(FIELD *field,          /* field to alter */
6467                    TYPE_NUMERIC,          /* type to associate */
6468                    int padding,           /* # places of precision */
6469                    int vmin, int vmax);   /* valid range */
6470 </pre>
6471         <p>Valid characters consist of an optional leading minus
6472         and digits. possibly including a decimal point. The range
6473         check is performed on exit. If the range maximum is less
6474         than or equal to the minimum, the range is ignored.</p>
6475
6476         <p>If the value passes its range check, it is padded with
6477         as many trailing zero digits as necessary to meet the
6478         padding argument.</p>
6479
6480         <p>A TYPE_NUMERIC value buffer can conveniently be
6481         interpreted with the C library function atof(3).</p>
6482
6483         <h1 class="BRIDGEHEAD"><a name="AEN1096" id=
6484         "AEN1096"></a>TYPE_REGEXP</h1>
6485
6486         <p>This field type accepts data matching a regular
6487         expression. It is set up as follows:</p>
6488
6489         <pre class="PROGRAMLISTING">
6490 int set_field_type(FIELD *field,          /* field to alter */
6491                    TYPE_REGEXP,           /* type to associate */
6492                    char *regexp);         /* expression to match */
6493 </pre>
6494         <p>The syntax for regular expressions is that of
6495         regcomp(3). The check for regular-expression match is
6496         performed on exit.</p>
6497       </div>
6498
6499       <div class="SECT2">
6500         <hr>
6501
6502         <h3 class="SECT2"><a name="FORMDRIVER" id=
6503         "FORMDRIVER">18.6. Form Driver: The work horse of the forms
6504         system</a></h3>
6505
6506         <p>As in the menu system, form_driver() plays a very
6507         important role in forms system. All types of requests to
6508         forms system should be funneled through form_driver().</p>
6509
6510         <pre class="PROGRAMLISTING">
6511 int form_driver(FORM *form,     /* form on which to operate     */
6512                 int request)    /* form request code         */
6513 </pre>
6514         <p>As you have seen some of the examples above, you have to
6515         be in a loop looking for user input and then decide whether
6516         it is a field data or a form request. The form requests are
6517         then passed to form_driver() to do the work.</p>
6518
6519         <p>The requests roughly can be divided into following
6520         categories. Different requests and their usage is explained
6521         below:</p>
6522
6523         <div class="SECT3">
6524           <hr>
6525
6526           <h4 class="SECT3"><a name="PAGENAVREQ" id=
6527           "PAGENAVREQ">18.6.1. Page Navigation Requests</a></h4>
6528
6529           <p>These requests cause page-level moves through the
6530           form, triggering display of a new form screen. A form can
6531           be made of multiple pages. If you have a big form with
6532           lot of fields and logical sections, then you can divide
6533           the form into pages. The function set_new_page() to set a
6534           new page at the field specified.</p>
6535
6536           <pre class="PROGRAMLISTING">
6537 int set_new_page(FIELD *field,/* Field at which page break to be set or unset */
6538          bool new_page_flag); /* should be TRUE to put a break */
6539 </pre>
6540           <p>The following requests allow you to move to different
6541           pages</p>
6542
6543           <ul>
6544             <li>
6545               <p><span class="emphasis"><i class=
6546               "EMPHASIS">REQ_NEXT_PAGE</i></span> Move to the next
6547               form page.</p>
6548             </li>
6549
6550             <li>
6551               <p><span class="emphasis"><i class=
6552               "EMPHASIS">REQ_PREV_PAGE</i></span> Move to the
6553               previous form page.</p>
6554             </li>
6555
6556             <li>
6557               <p><span class="emphasis"><i class=
6558               "EMPHASIS">REQ_FIRST_PAGE</i></span> Move to the
6559               first form page.</p>
6560             </li>
6561
6562             <li>
6563               <p><span class="emphasis"><i class=
6564               "EMPHASIS">REQ_LAST_PAGE</i></span> Move to the last
6565               form page.</p>
6566             </li>
6567           </ul>
6568
6569           <p>These requests treat the list as cyclic; that is,
6570           REQ_NEXT_PAGE from the last page goes to the first, and
6571           REQ_PREV_PAGE from the first page goes to the last.</p>
6572         </div>
6573
6574         <div class="SECT3">
6575           <hr>
6576
6577           <h4 class="SECT3"><a name="INTERFIELDNAVREQ" id=
6578           "INTERFIELDNAVREQ">18.6.2. Inter-Field Navigation
6579           Requests</a></h4>
6580
6581           <p>These requests handle navigation between fields on the
6582           same page.</p>
6583
6584           <ul>
6585             <li>
6586               <p><span class="emphasis"><i class=
6587               "EMPHASIS">REQ_NEXT_FIELD</i></span> Move to next
6588               field.</p>
6589             </li>
6590
6591             <li>
6592               <p><span class="emphasis"><i class=
6593               "EMPHASIS">REQ_PREV_FIELD</i></span> Move to previous
6594               field.</p>
6595             </li>
6596
6597             <li>
6598               <p><span class="emphasis"><i class=
6599               "EMPHASIS">REQ_FIRST_FIELD</i></span> Move to the
6600               first field.</p>
6601             </li>
6602
6603             <li>
6604               <p><span class="emphasis"><i class=
6605               "EMPHASIS">REQ_LAST_FIELD</i></span> Move to the last
6606               field.</p>
6607             </li>
6608
6609             <li>
6610               <p><span class="emphasis"><i class=
6611               "EMPHASIS">REQ_SNEXT_FIELD</i></span> Move to sorted
6612               next field.</p>
6613             </li>
6614
6615             <li>
6616               <p><span class="emphasis"><i class=
6617               "EMPHASIS">REQ_SPREV_FIELD</i></span> Move to sorted
6618               previous field.</p>
6619             </li>
6620
6621             <li>
6622               <p><span class="emphasis"><i class=
6623               "EMPHASIS">REQ_SFIRST_FIELD</i></span> Move to the
6624               sorted first field.</p>
6625             </li>
6626
6627             <li>
6628               <p><span class="emphasis"><i class=
6629               "EMPHASIS">REQ_SLAST_FIELD</i></span> Move to the
6630               sorted last field.</p>
6631             </li>
6632
6633             <li>
6634               <p><span class="emphasis"><i class=
6635               "EMPHASIS">REQ_LEFT_FIELD</i></span> Move left to
6636               field.</p>
6637             </li>
6638
6639             <li>
6640               <p><span class="emphasis"><i class=
6641               "EMPHASIS">REQ_RIGHT_FIELD</i></span> Move right to
6642               field.</p>
6643             </li>
6644
6645             <li>
6646               <p><span class="emphasis"><i class=
6647               "EMPHASIS">REQ_UP_FIELD</i></span> Move up to
6648               field.</p>
6649             </li>
6650
6651             <li>
6652               <p><span class="emphasis"><i class=
6653               "EMPHASIS">REQ_DOWN_FIELD</i></span> Move down to
6654               field.</p>
6655             </li>
6656           </ul>
6657
6658           <p>These requests treat the list of fields on a page as
6659           cyclic; that is, REQ_NEXT_FIELD from the last field goes
6660           to the first, and REQ_PREV_FIELD from the first field
6661           goes to the last. The order of the fields for these (and
6662           the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is
6663           simply the order of the field pointers in the form array
6664           (as set up by new_form() or set_form_fields()</p>
6665
6666           <p>It is also possible to traverse the fields as if they
6667           had been sorted in screen-position order, so the sequence
6668           goes left-to-right and top-to-bottom. To do this, use the
6669           second group of four sorted-movement requests.</p>
6670
6671           <p>Finally, it is possible to move between fields using
6672           visual directions up, down, right, and left. To
6673           accomplish this, use the third group of four requests.
6674           Note, however, that the position of a form for purposes
6675           of these requests is its upper-left corner.</p>
6676
6677           <p>For example, suppose you have a multi-line field B,
6678           and two single-line fields A and C on the same line with
6679           B, with A to the left of B and C to the right of B. A
6680           REQ_MOVE_RIGHT from A will go to B only if A, B, and C
6681           all share the same first line; otherwise it will skip
6682           over B to C.</p>
6683         </div>
6684
6685         <div class="SECT3">
6686           <hr>
6687
6688           <h4 class="SECT3"><a name="INTRAFIELDNAVREQ" id=
6689           "INTRAFIELDNAVREQ">18.6.3. Intra-Field Navigation
6690           Requests</a></h4>
6691
6692           <p>These requests drive movement of the edit cursor
6693           within the currently selected field.</p>
6694
6695           <ul>
6696             <li>
6697               <p><span class="emphasis"><i class=
6698               "EMPHASIS">REQ_NEXT_CHAR</i></span> Move to next
6699               character.</p>
6700             </li>
6701
6702             <li>
6703               <p><span class="emphasis"><i class=
6704               "EMPHASIS">REQ_PREV_CHAR</i></span> Move to previous
6705               character.</p>
6706             </li>
6707
6708             <li>
6709               <p><span class="emphasis"><i class=
6710               "EMPHASIS">REQ_NEXT_LINE</i></span> Move to next
6711               line.</p>
6712             </li>
6713
6714             <li>
6715               <p><span class="emphasis"><i class=
6716               "EMPHASIS">REQ_PREV_LINE</i></span> Move to previous
6717               line.</p>
6718             </li>
6719
6720             <li>
6721               <p><span class="emphasis"><i class=
6722               "EMPHASIS">REQ_NEXT_WORD</i></span> Move to next
6723               word.</p>
6724             </li>
6725
6726             <li>
6727               <p><span class="emphasis"><i class=
6728               "EMPHASIS">REQ_PREV_WORD</i></span> Move to previous
6729               word.</p>
6730             </li>
6731
6732             <li>
6733               <p><span class="emphasis"><i class=
6734               "EMPHASIS">REQ_BEG_FIELD</i></span> Move to beginning
6735               of field.</p>
6736             </li>
6737
6738             <li>
6739               <p><span class="emphasis"><i class=
6740               "EMPHASIS">REQ_END_FIELD</i></span> Move to end of
6741               field.</p>
6742             </li>
6743
6744             <li>
6745               <p><span class="emphasis"><i class=
6746               "EMPHASIS">REQ_BEG_LINE</i></span> Move to beginning
6747               of line.</p>
6748             </li>
6749
6750             <li>
6751               <p><span class="emphasis"><i class=
6752               "EMPHASIS">REQ_END_LINE</i></span> Move to end of
6753               line.</p>
6754             </li>
6755
6756             <li>
6757               <p><span class="emphasis"><i class=
6758               "EMPHASIS">REQ_LEFT_CHAR</i></span> Move left in
6759               field.</p>
6760             </li>
6761
6762             <li>
6763               <p><span class="emphasis"><i class=
6764               "EMPHASIS">REQ_RIGHT_CHAR</i></span> Move right in
6765               field.</p>
6766             </li>
6767
6768             <li>
6769               <p><span class="emphasis"><i class=
6770               "EMPHASIS">REQ_UP_CHAR</i></span> Move up in
6771               field.</p>
6772             </li>
6773
6774             <li>
6775               <p><span class="emphasis"><i class=
6776               "EMPHASIS">REQ_DOWN_CHAR</i></span> Move down in
6777               field.</p>
6778             </li>
6779           </ul>
6780
6781           <p>Each word is separated from the previous and next
6782           characters by whitespace. The commands to move to
6783           beginning and end of line or field look for the first or
6784           last non-pad character in their ranges.</p>
6785         </div>
6786
6787         <div class="SECT3">
6788           <hr>
6789
6790           <h4 class="SECT3"><a name="SCROLLREQ" id=
6791           "SCROLLREQ">18.6.4. Scrolling Requests</a></h4>
6792
6793           <p>Fields that are dynamic and have grown and fields
6794           explicitly created with offscreen rows are scrollable.
6795           One-line fields scroll horizontally; multi-line fields
6796           scroll vertically. Most scrolling is triggered by editing
6797           and intra-field movement (the library scrolls the field
6798           to keep the cursor visible). It is possible to explicitly
6799           request scrolling with the following requests:</p>
6800
6801           <ul>
6802             <li>
6803               <p><span class="emphasis"><i class=
6804               "EMPHASIS">REQ_SCR_FLINE</i></span> Scroll vertically
6805               forward a line.</p>
6806             </li>
6807
6808             <li>
6809               <p><span class="emphasis"><i class=
6810               "EMPHASIS">REQ_SCR_BLINE</i></span> Scroll vertically
6811               backward a line.</p>
6812             </li>
6813
6814             <li>
6815               <p><span class="emphasis"><i class=
6816               "EMPHASIS">REQ_SCR_FPAGE</i></span> Scroll vertically
6817               forward a page.</p>
6818             </li>
6819
6820             <li>
6821               <p><span class="emphasis"><i class=
6822               "EMPHASIS">REQ_SCR_BPAGE</i></span> Scroll vertically
6823               backward a page.</p>
6824             </li>
6825
6826             <li>
6827               <p><span class="emphasis"><i class=
6828               "EMPHASIS">REQ_SCR_FHPAGE</i></span> Scroll
6829               vertically forward half a page.</p>
6830             </li>
6831
6832             <li>
6833               <p><span class="emphasis"><i class=
6834               "EMPHASIS">REQ_SCR_BHPAGE</i></span> Scroll
6835               vertically backward half a page.</p>
6836             </li>
6837
6838             <li>
6839               <p><span class="emphasis"><i class=
6840               "EMPHASIS">REQ_SCR_FCHAR</i></span> Scroll
6841               horizontally forward a character.</p>
6842             </li>
6843
6844             <li>
6845               <p><span class="emphasis"><i class=
6846               "EMPHASIS">REQ_SCR_BCHAR</i></span> Scroll
6847               horizontally backward a character.</p>
6848             </li>
6849
6850             <li>
6851               <p><span class="emphasis"><i class=
6852               "EMPHASIS">REQ_SCR_HFLINE</i></span> Scroll
6853               horizontally one field width forward.</p>
6854             </li>
6855
6856             <li>
6857               <p><span class="emphasis"><i class=
6858               "EMPHASIS">REQ_SCR_HBLINE</i></span> Scroll
6859               horizontally one field width backward.</p>
6860             </li>
6861
6862             <li>
6863               <p><span class="emphasis"><i class=
6864               "EMPHASIS">REQ_SCR_HFHALF</i></span> Scroll
6865               horizontally one half field width forward.</p>
6866             </li>
6867
6868             <li>
6869               <p><span class="emphasis"><i class=
6870               "EMPHASIS">REQ_SCR_HBHALF</i></span> Scroll
6871               horizontally one half field width backward.</p>
6872             </li>
6873           </ul>
6874
6875           <p>For scrolling purposes, a page of a field is the
6876           height of its visible part.</p>
6877         </div>
6878
6879         <div class="SECT3">
6880           <hr>
6881
6882           <h4 class="SECT3"><a name="EDITREQ" id="EDITREQ">18.6.5.
6883           Editing Requests</a></h4>
6884
6885           <p>When you pass the forms driver an ASCII character, it
6886           is treated as a request to add the character to the
6887           field's data buffer. Whether this is an insertion or a
6888           replacement depends on the field's edit mode (insertion
6889           is the default.</p>
6890
6891           <p>The following requests support editing the field and
6892           changing the edit mode:</p>
6893
6894           <ul>
6895             <li>
6896               <p><span class="emphasis"><i class=
6897               "EMPHASIS">REQ_INS_MODE</i></span> Set insertion
6898               mode.</p>
6899             </li>
6900
6901             <li>
6902               <p><span class="emphasis"><i class=
6903               "EMPHASIS">REQ_OVL_MODE</i></span> Set overlay
6904               mode.</p>
6905             </li>
6906
6907             <li>
6908               <p><span class="emphasis"><i class=
6909               "EMPHASIS">REQ_NEW_LINE</i></span> New line request
6910               (see below for explanation).</p>
6911             </li>
6912
6913             <li>
6914               <p><span class="emphasis"><i class=
6915               "EMPHASIS">REQ_INS_CHAR</i></span> Insert space at
6916               character location.</p>
6917             </li>
6918
6919             <li>
6920               <p><span class="emphasis"><i class=
6921               "EMPHASIS">REQ_INS_LINE</i></span> Insert blank line
6922               at character location.</p>
6923             </li>
6924
6925             <li>
6926               <p><span class="emphasis"><i class=
6927               "EMPHASIS">REQ_DEL_CHAR</i></span> Delete character
6928               at cursor.</p>
6929             </li>
6930
6931             <li>
6932               <p><span class="emphasis"><i class=
6933               "EMPHASIS">REQ_DEL_PREV</i></span> Delete previous
6934               word at cursor.</p>
6935             </li>
6936
6937             <li>
6938               <p><span class="emphasis"><i class=
6939               "EMPHASIS">REQ_DEL_LINE</i></span> Delete line at
6940               cursor.</p>
6941             </li>
6942
6943             <li>
6944               <p><span class="emphasis"><i class=
6945               "EMPHASIS">REQ_DEL_WORD</i></span> Delete word at
6946               cursor.</p>
6947             </li>
6948
6949             <li>
6950               <p><span class="emphasis"><i class=
6951               "EMPHASIS">REQ_CLR_EOL</i></span> Clear to end of
6952               line.</p>
6953             </li>
6954
6955             <li>
6956               <p><span class="emphasis"><i class=
6957               "EMPHASIS">REQ_CLR_EOF</i></span> Clear to end of
6958               field.</p>
6959             </li>
6960
6961             <li>
6962               <p><span class="emphasis"><i class=
6963               "EMPHASIS">REQ_CLR_FIELD</i></span> Clear entire
6964               field.</p>
6965             </li>
6966           </ul>
6967
6968           <p>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV
6969           requests is complicated and partly controlled by a pair
6970           of forms options. The special cases are triggered when
6971           the cursor is at the beginning of a field, or on the last
6972           line of the field.</p>
6973
6974           <p>First, we consider REQ_NEW_LINE:</p>
6975
6976           <p>The normal behavior of REQ_NEW_LINE in insert mode is
6977           to break the current line at the position of the edit
6978           cursor, inserting the portion of the current line after
6979           the cursor as a new line following the current and moving
6980           the cursor to the beginning of that new line (you may
6981           think of this as inserting a newline in the field
6982           buffer).</p>
6983
6984           <p>The normal behavior of REQ_NEW_LINE in overlay mode is
6985           to clear the current line from the position of the edit
6986           cursor to end of line. The cursor is then moved to the
6987           beginning of the next line.</p>
6988
6989           <p>However, REQ_NEW_LINE at the beginning of a field, or
6990           on the last line of a field, instead does a
6991           REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this special
6992           action is disabled.</p>
6993
6994           <p>Now, let us consider REQ_DEL_PREV:</p>
6995
6996           <p>The normal behavior of REQ_DEL_PREV is to delete the
6997           previous character. If insert mode is on, and the cursor
6998           is at the start of a line, and the text on that line will
6999           fit on the previous one, it instead appends the contents
7000           of the current line to the previous one and deletes the
7001           current line (you may think of this as deleting a newline
7002           from the field buffer).</p>
7003
7004           <p>However, REQ_DEL_PREV at the beginning of a field is
7005           instead treated as a REQ_PREV_FIELD.</p>
7006
7007           <p>If the O_BS_OVERLOAD option is off, this special
7008           action is disabled and the forms driver just returns
7009           E_REQUEST_DENIED.</p>
7010         </div>
7011
7012         <div class="SECT3">
7013           <hr>
7014
7015           <h4 class="SECT3"><a name="ORDERREQ" id=
7016           "ORDERREQ">18.6.6. Order Requests</a></h4>
7017
7018           <p>If the type of your field is ordered, and has
7019           associated functions for getting the next and previous
7020           values of the type from a given value, there are requests
7021           that can fetch that value into the field buffer:</p>
7022
7023           <ul>
7024             <li>
7025               <p><span class="emphasis"><i class=
7026               "EMPHASIS">REQ_NEXT_CHOICE</i></span> Place the
7027               successor value of the current value in the
7028               buffer.</p>
7029             </li>
7030
7031             <li>
7032               <p><span class="emphasis"><i class=
7033               "EMPHASIS">REQ_PREV_CHOICE</i></span> Place the
7034               predecessor value of the current value in the
7035               buffer.</p>
7036             </li>
7037           </ul>
7038
7039           <p>Of the built-in field types, only TYPE_ENUM has
7040           built-in successor and predecessor functions. When you
7041           define a field type of your own (see Custom Validation
7042           Types), you can associate our own ordering functions.</p>
7043         </div>
7044
7045         <div class="SECT3">
7046           <hr>
7047
7048           <h4 class="SECT3"><a name="APPLICCOMMANDS" id=
7049           "APPLICCOMMANDS">18.6.7. Application Commands</a></h4>
7050
7051           <p>Form requests are represented as integers above the
7052           curses value greater than KEY_MAX and less than or equal
7053           to the constant MAX_COMMAND. A value within this range
7054           gets ignored by form_driver(). So this can be used for
7055           any purpose by the application. It can be treated as an
7056           application specific action and take corresponding
7057           action.</p>
7058         </div>
7059       </div>
7060     </div>
7061
7062     <div class="SECT1">
7063       <hr>
7064
7065       <h2 class="SECT1"><a name="TOOLS" id="TOOLS">19. Tools and
7066       Widget Libraries</a></h2>
7067
7068       <p>Now that you have seen the capabilities of ncurses and its
7069       sister libraries, you are rolling your sleeves up and gearing
7070       for a project that heavily manipulates screen. But wait.. It
7071       can be pretty difficult to write and maintain complex GUI
7072       widgets in plain ncurses or even with the additional
7073       libraries. There are some ready-to-use tools and widget
7074       libraries that can be used instead of writing your own
7075       widgets. You can use some of them, get ideas from the code,
7076       or even extend them.</p>
7077
7078       <div class="SECT2">
7079         <hr>
7080
7081         <h3 class="SECT2"><a name="CDK" id="CDK">19.1. CDK (Curses
7082         Development Kit)</a></h3>
7083
7084         <p>In the author's words</p>
7085
7086         <p><span class="emphasis"><i class="EMPHASIS">CDK stands
7087         for 'Curses Development Kit' and it currently contains 21
7088         ready to use widgets which facilitate the speedy
7089         development of full screen curses programs.</i></span>
7090         </p>
7091
7092         <p>The kit provides some useful widgets, which can be used
7093         in your programs directly. It is pretty well written and
7094         the documentation is very good. The examples in the
7095         examples directory can be a good place to start for
7096         beginners. The CDK can be downloaded from <a href=
7097         "https://invisible-island.net/cdk/" target=
7098         "_top">https://invisible-island.net/cdk/</a> . Follow the
7099         instructions in README file to install it.</p>
7100
7101         <div class="SECT3">
7102           <hr>
7103
7104           <h4 class="SECT3"><a name="WIDGETLIST" id=
7105           "WIDGETLIST">19.1.1. Widget List</a></h4>
7106
7107           <p>The following is the list of widgets provided with cdk
7108           and their description.</p>
7109
7110           <pre class="PROGRAMLISTING">
7111 Widget Type           Quick Description
7112 ===========================================================================
7113 Alphalist             Allows a user to select from a list of words, with
7114                       the ability to narrow the search list by typing in a
7115                       few characters of the desired word.
7116 Buttonbox             This creates a multiple button widget. 
7117 Calendar              Creates a little simple calendar widget.
7118 Dialog                Prompts the user with a message, and the user
7119                       can pick an answer from the buttons provided.
7120 Entry                 Allows the user to enter various types of information.
7121 File Selector         A file selector built from Cdk base widgets. This
7122                       example shows how to create more complicated widgets
7123                       using the Cdk widget library.
7124 Graph                 Draws a graph.
7125 Histogram             Draws a histogram.
7126 Item List             Creates a pop up field which allows the user to select
7127                       one of several choices in a small field. Very useful
7128                       for things like days of the week or month names.
7129 Label                 Displays messages in a pop up box, or the label can be
7130                       considered part of the screen.
7131 Marquee               Displays a message in a scrolling marquee.
7132 Matrix                Creates a complex matrix with lots of options.
7133 Menu                  Creates a pull-down menu interface.
7134 Multiple Line Entry   A multiple line entry field. Very useful
7135                       for long fields. (like a description
7136                       field)
7137 Radio List            Creates a radio button list.
7138 Scale                 Creates a numeric scale. Used for allowing a user to
7139                       pick a numeric value and restrict them to a range of 
7140                       values.
7141 Scrolling List        Creates a scrolling list/menu list.
7142 Scrolling Window      Creates a scrolling log file viewer. Can add 
7143                       information into the window while its running. 
7144                       A good widget for displaying the progress of
7145                       something. (akin to a console window)
7146 Selection List        Creates a multiple option selection list.
7147 Slider                Akin to the scale widget, this widget provides a
7148                       visual slide bar to represent the numeric value.
7149 Template              Creates a entry field with character sensitive 
7150                       positions. Used for pre-formatted fields like
7151                       dates and phone numbers.
7152 Viewer                This is a file/information viewer. Very useful
7153                       when you need to display loads of information.
7154 ===========================================================================
7155 </pre>
7156           <p>A few of the widgets are modified by Thomas Dickey in
7157           recent versions.</p>
7158         </div>
7159
7160         <div class="SECT3">
7161           <hr>
7162
7163           <h4 class="SECT3"><a name="CDKATTRACT" id=
7164           "CDKATTRACT">19.1.2. Some Attractive Features</a></h4>
7165
7166           <p>Apart from making our life easier with readily usable
7167           widgets, cdk solves one frustrating problem with printing
7168           multi colored strings, justified strings elegantly.
7169           Special formatting tags can be embedded in the strings
7170           which are passed to CDK functions. For Example</p>
7171
7172           <p>If the string</p>
7173
7174           <pre class="PROGRAMLISTING">
7175 "&lt;/B/1&gt;This line should have a yellow foreground and a blue
7176 background.&lt;!1&gt;"
7177 </pre>
7178           <p>given as a parameter to newCDKLabel(), it prints the
7179           line with yellow foreground and blue background. There
7180           are other tags available for justifying string, embedding
7181           special drawing characters etc.. Please refer to the man
7182           page cdk_display(3X) for details. The man page explains
7183           the usage with nice examples.</p>
7184         </div>
7185
7186         <div class="SECT3">
7187           <hr>
7188
7189           <h4 class="SECT3"><a name="CDKCONCLUSION" id=
7190           "CDKCONCLUSION">19.1.3. Conclusion</a></h4>
7191
7192           <p>All in all, CDK is a well-written package of widgets,
7193           which if used properly can form a strong frame work for
7194           developing complex GUI.</p>
7195         </div>
7196       </div>
7197
7198       <div class="SECT2">
7199         <hr>
7200
7201         <h3 class="SECT2"><a name="DIALOG" id="DIALOG">19.2. The
7202         dialog</a></h3>
7203
7204         <p>Long long ago, in September 1994, when few people knew
7205         linux, Jeff Tranter wrote an <a href=
7206         "http://www2.linuxjournal.com/lj-issues/issue5/2807.html"
7207         target="_top">article</a> on dialog in Linux Journal. He
7208         starts the article with these words..</p>
7209
7210         <p><span class="emphasis"><i class="EMPHASIS">Linux is
7211         based on the Unix operating system, but also features a
7212         number of unique and useful kernel features and application
7213         programs that often go beyond what is available under Unix.
7214         One little-known gem is "dialog", a utility for creating
7215         professional-looking dialog boxes from within shell
7216         scripts. This article presents a tutorial introduction to
7217         the dialog utility, and shows examples of how and where it
7218         can be used</i></span>
7219         </p>
7220
7221         <p>As he explains, dialog is a real gem in making
7222         professional-looking dialog boxes with ease. It creates a
7223         variety of dialog boxes, menus, check lists etc.. It is
7224         usually installed by default. If not, you can download it
7225         from <a href="https://invisible-island.net/dialog/" target=
7226         "_top">Thomas Dickey</a>'s site.</p>
7227
7228         <p>The above-mentioned article gives a very good overview
7229         of its uses and capabilites. The man page has more details.
7230         It can be used in variety of situations. One good example
7231         is building of linux kernel in text mode. Linux kernel uses
7232         a modified version of dialog tailored for its needs.</p>
7233
7234         <p>dialog was initially designed to be used with shell
7235         scripts. If you want to use its functionality in a c
7236         program, then you can use libdialog. The documentation
7237         regarding this is sparse. Definitive reference is the
7238         dialog.h header file which comes with the library. You may
7239         need to hack here and there to get the required output. The
7240         source is easily customizable. I have used it on a number
7241         of occasions by modifying the code.</p>
7242       </div>
7243
7244       <div class="SECT2">
7245         <hr>
7246
7247         <h3 class="SECT2"><a name="PERLCURSES" id=
7248         "PERLCURSES">19.3. Perl Curses Modules CURSES::FORM and
7249         CURSES::WIDGETS</a></h3>
7250
7251         <p>The perl module Curses, Curses::Form and Curses::Widgets
7252         give access to curses from perl. If you have curses and
7253         basic perl is installed, you can get these modules from
7254         <a href="http://www.cpan.org/modules/01modules.index.html"
7255         target="_top">CPAN All Modules page</a>. Get the three
7256         zipped modules in the Curses category. Once installed you
7257         can use these modules from perl scripts like any other
7258         module. For more information on perl modules see perlmod
7259         man page. The above modules come with good documentation
7260         and they have some demo scripts to test the functionality.
7261         Though the widgets provided are very rudimentary, these
7262         modules provide good access to curses library from
7263         perl.</p>
7264
7265         <p>Some of my code examples are converted to perl by
7266         Anuradha Ratnaweera and they are available in the
7267         <tt class="LITERAL">perl</tt> directory.</p>
7268
7269         <p>For more information see man pages Curses(3) ,
7270         Curses::Form(3) and Curses::Widgets(3). These pages are
7271         installed only when the above modules are acquired and
7272         installed.</p>
7273       </div>
7274     </div>
7275
7276     <div class="SECT1">
7277       <hr>
7278
7279       <h2 class="SECT1"><a name="JUSTFORFUN" id="JUSTFORFUN">20.
7280       Just For Fun !!!</a></h2>
7281
7282       <p>This section contains few programs written by me just for
7283       fun. They don't signify a better programming practice or the
7284       best way of using ncurses. They are provided here so as to
7285       allow beginners to get ideas and add more programs to this
7286       section. If you have written a couple of nice, simple
7287       programs in curses and want them to included here, contact
7288       <a href="mailto:ppadala@gmail.com" target="_top">me</a>.</p>
7289
7290       <div class="SECT2">
7291         <hr>
7292
7293         <h3 class="SECT2"><a name="GAMEOFLIFE" id=
7294         "GAMEOFLIFE">20.1. The Game of Life</a></h3>
7295
7296         <p>Game of life is a wonder of math. In <a href=
7297         "http://www.math.com/students/wonders/life/life.html"
7298         target="_top">Paul Callahan</a>'s words</p>
7299
7300         <pre class="PROGRAMLISTING">
7301 <span class="emphasis"><i class=
7302 "EMPHASIS">The Game of Life (or simply Life) is not a game in the conventional sense. There
7303 are no players, and no winning or losing. Once the "pieces" are placed in the
7304 starting position, the rules determine everything that happens later.
7305 Nevertheless, Life is full of surprises! In most cases, it is impossible to look
7306 at a starting position (or pattern) and see what will happen in the future. The
7307 only way to find out is to follow the rules of the game.</i></span>
7308 </pre>
7309         <p>This program starts with a simple inverted U pattern and
7310         shows how wonderful life works. There is a lot of room for
7311         improvement in the program. You can let the user enter
7312         pattern of his choice or even take input from a file. You
7313         can also change rules and play with a lot of variations.
7314         Search on <a href="http://www.google.com" target=
7315         "_top">google</a> for interesting information on game of
7316         life.</p>
7317
7318         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7319         JustForFun/life.c</i></span>
7320         </p>
7321       </div>
7322
7323       <div class="SECT2">
7324         <hr>
7325
7326         <h3 class="SECT2"><a name="MAGIC" id="MAGIC">20.2. Magic
7327         Square</a></h3>
7328
7329         <p>Magic Square, another wonder of math, is very simple to
7330         understand but very difficult to make. In a magic square
7331         sum of the numbers in each row, each column is equal. Even
7332         diagnol sum can be equal. There are many variations which
7333         have special properties.</p>
7334
7335         <p>This program creates a simple magic square of odd
7336         order.</p>
7337
7338         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7339         JustForFun/magic.c</i></span>
7340         </p>
7341       </div>
7342
7343       <div class="SECT2">
7344         <hr>
7345
7346         <h3 class="SECT2"><a name="HANOI" id="HANOI">20.3. Towers
7347         of Hanoi</a></h3>
7348
7349         <p>The famous towers of hanoi solver. The aim of the game
7350         is to move the disks on the first peg to last peg, using
7351         middle peg as a temporary stay. The catch is not to place a
7352         larger disk over a small disk at any time.</p>
7353
7354         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7355         JustForFun/hanoi.c</i></span>
7356         </p>
7357       </div>
7358
7359       <div class="SECT2">
7360         <hr>
7361
7362         <h3 class="SECT2"><a name="QUEENS" id="QUEENS">20.4. Queens
7363         Puzzle</a></h3>
7364
7365         <p>The objective of the famous N-Queen puzzle is to put N
7366         queens on a N X N chess board without attacking each
7367         other.</p>
7368
7369         <p>This program solves it with a simple backtracking
7370         technique.</p>
7371
7372         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7373         JustForFun/queens.c</i></span>
7374         </p>
7375       </div>
7376
7377       <div class="SECT2">
7378         <hr>
7379
7380         <h3 class="SECT2"><a name="SHUFFLE" id="SHUFFLE">20.5.
7381         Shuffle</a></h3>
7382
7383         <p>A fun game, if you have time to kill.</p>
7384
7385         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7386         JustForFun/shuffle.c</i></span>
7387         </p>
7388       </div>
7389
7390       <div class="SECT2">
7391         <hr>
7392
7393         <h3 class="SECT2"><a name="TT" id="TT">20.6. Typing
7394         Tutor</a></h3>
7395
7396         <p>A simple typing tutor, I created more out of need than
7397         for ease of use. If you know how to put your fingers
7398         correctly on the keyboard, but lack practice, this can be
7399         helpful.</p>
7400
7401         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7402         JustForFun/tt.c</i></span>
7403         </p>
7404       </div>
7405     </div>
7406
7407     <div class="SECT1">
7408       <hr>
7409
7410       <h2 class="SECT1"><a name="REF" id="REF">21. References</a></h2>
7411
7412       <ul>
7413         <li>
7414           <p>NCURSES man pages</p>
7415         </li>
7416
7417         <li>
7418           <p>NCURSES FAQ at <a href=
7419           "https://invisible-island.net/ncurses/ncurses.faq.html"
7420           target=
7421           "_top">https://invisible-island.net/ncurses/ncurses.faq.html</a></p>
7422         </li>
7423
7424         <li>
7425           <p>Writing programs with NCURSES by Eric Raymond and Zeyd
7426           M. Ben-Halim at <a href=
7427           "https://invisible-island.net/ncurses/ncurses-intro.html"
7428           target=
7429           "_top">https://invisible-island.net/ncurses/ncurses-intro.html</a>
7430           - somewhat obsolete. I was inspired by this document and
7431           the structure of this HOWTO follows from the original
7432           document</p>
7433         </li>
7434       </ul>
7435     </div>
7436   </div>
7437 </body>
7438 </html>