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