]> 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         print_menu(menu_win, 1);
2980         /* Get all the mouse events */
2981         mousemask(ALL_MOUSE_EVENTS, NULL);
2982         
2983         while(1)
2984         {       c = wgetch(menu_win);
2985                 switch(c)
2986                 {       case KEY_MOUSE:
2987                         if(getmouse(&amp;event) == OK)
2988                         {       /* When the user clicks left mouse button */
2989                                 if(event.bstate &amp; BUTTON1_PRESSED)
2990                                 {       report_choice(event.x + 1, event.y + 1, &amp;choice);
2991                                         if(choice == -1) //Exit chosen
2992                                                 goto end;
2993                                         mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
2994                                         refresh(); 
2995                                 }
2996                         }
2997                         print_menu(menu_win, choice);
2998                         break;
2999                 }
3000         }               
3001 end:
3002         endwin();
3003         return 0;
3004 }
3005
3006 void print_menu(WINDOW *menu_win, int highlight)
3007 {
3008         int x, y, i;    
3009
3010         x = 2;
3011         y = 2;
3012         box(menu_win, 0, 0);
3013         for(i = 0; i &lt; n_choices; ++i)
3014         {       if(highlight == i + 1)
3015                 {       wattron(menu_win, A_REVERSE); 
3016                         mvwprintw(menu_win, y, x, "%s", choices[i]);
3017                         wattroff(menu_win, A_REVERSE);
3018                 }
3019                 else
3020                         mvwprintw(menu_win, y, x, "%s", choices[i]);
3021                 ++y;
3022         }
3023         wrefresh(menu_win);
3024 }
3025
3026 /* Report the choice according to mouse position */
3027 void report_choice(int mouse_x, int mouse_y, int *p_choice)
3028 {       int i,j, choice;
3029
3030         i = startx + 2;
3031         j = starty + 3;
3032         
3033         for(choice = 0; choice &lt; n_choices; ++choice)
3034                 if(mouse_y == j + choice &amp;&amp; mouse_x &gt;= i &amp;&amp; mouse_x &lt;= i + strlen(choices[choice]))
3035                 {       if(choice == n_choices - 1)
3036                                 *p_choice = -1;         
3037                         else
3038                                 *p_choice = choice + 1; 
3039                         break;
3040                 }
3041 }</span></pre>
3042         </div>
3043       </div>
3044
3045       <div class="SECT2">
3046         <hr>
3047
3048         <h3 class="SECT2"><a name="MISCMOUSEFUNCS" id=
3049         "MISCMOUSEFUNCS">12.4. Miscellaneous Functions</a></h3>
3050
3051         <p>The functions mouse_trafo() and wmouse_trafo() can be
3052         used to convert to mouse co-ordinates to screen relative
3053         co-ordinates. See curs_mouse(3X) man page for details.</p>
3054
3055         <p>The mouseinterval function sets the maximum time (in
3056         thousands of a second) that can elapse between press and
3057         release events in order for them to be recognized as a
3058         click. This function returns the previous interval value.
3059         The default is one fifth of a second.</p>
3060       </div>
3061     </div>
3062
3063     <div class="SECT1">
3064       <hr>
3065
3066       <h2 class="SECT1"><a name="SCREEN" id="SCREEN">13. Screen
3067       Manipulation</a></h2>
3068
3069       <p>In this section, we will look into some functions, which
3070       allow us to manage the screen efficiently and to write some
3071       fancy programs. This is especially important in writing
3072       games.</p>
3073
3074       <div class="SECT2">
3075         <hr>
3076
3077         <h3 class="SECT2"><a name="GETYX" id="GETYX">13.1. getyx()
3078         functions</a></h3>
3079
3080         <p>The function <tt class="LITERAL">getyx()</tt> can be
3081         used to find out the present cursor co-ordinates. It will
3082         fill the values of x and y co-ordinates in the arguments
3083         given to it. Since getyx() is a macro you don't have to
3084         pass the address of the variables. It can be called as</p>
3085
3086         <pre class="PROGRAMLISTING">    getyx(win, y, x);
3087     /* win: window pointer
3088      *   y, x: y, x co-ordinates will be put into this variables 
3089      */</pre>
3090         <p>The function getparyx() gets the beginning co-ordinates
3091         of the sub window relative to the main window. This is some
3092         times useful to update a sub window. When designing fancy
3093         stuff like writing multiple menus, it becomes difficult to
3094         store the menu positions, their first option co-ordinates,
3095         etc. A simple solution to this problem, is to create menus
3096         in sub windows and later find the starting co-ordinates of
3097         the menus by using getparyx().</p>
3098
3099         <p>The functions getbegyx() and getmaxyx() store current
3100         window's beginning and maximum co-ordinates. These
3101         functions are useful in the same way as above in managing
3102         the windows and sub windows effectively.</p>
3103       </div>
3104
3105       <div class="SECT2">
3106         <hr>
3107
3108         <h3 class="SECT2"><a name="SCREENDUMP" id=
3109         "SCREENDUMP">13.2. Screen Dumping</a></h3>
3110
3111         <p>While writing games, some times it becomes necessary to
3112         store the state of the screen and restore it back to the
3113         same state. The function scr_dump() can be used to dump the
3114         screen contents to a file given as an argument. Later it
3115         can be restored by scr_restore function. These two simple
3116         functions can be used effectively to maintain a fast moving
3117         game with changing scenarios.</p>
3118       </div>
3119
3120       <div class="SECT2">
3121         <hr>
3122
3123         <h3 class="SECT2"><a name="WINDOWDUMP" id=
3124         "WINDOWDUMP">13.3. Window Dumping</a></h3>
3125
3126         <p>To store and restore windows, the functions <tt class=
3127         "LITERAL">putwin()</tt> and <tt class=
3128         "LITERAL">getwin()</tt> can be used. <tt class=
3129         "LITERAL">putwin()</tt> puts the present window state into
3130         a file, which can be later restored by <tt class=
3131         "LITERAL">getwin()</tt>.</p>
3132
3133         <p>The function <tt class="LITERAL">copywin()</tt> can be
3134         used to copy a window completely onto another window. It
3135         takes the source and destination windows as parameters and
3136         according to the rectangle specified, it copies the
3137         rectangular region from source to destination window. Its
3138         last parameter specifies whether to overwrite or just
3139         overlay the contents on to the destination window. If this
3140         argument is true, then the copying is non-destructive.</p>
3141       </div>
3142     </div>
3143
3144     <div class="SECT1">
3145       <hr>
3146
3147       <h2 class="SECT1"><a name="MISC" id="MISC">14. Miscellaneous
3148       features</a></h2>
3149
3150       <p>Now you know enough features to write a good curses
3151       program, with all bells and whistles. There are some
3152       miscellaneous functions which are useful in various cases.
3153       Let's go headlong into some of those.</p>
3154
3155       <div class="SECT2">
3156         <hr>
3157
3158         <h3 class="SECT2"><a name="CURSSET" id="CURSSET">14.1.
3159         curs_set()</a></h3>
3160
3161         <p>This function can be used to make the cursor invisible.
3162         The parameter to this function should be</p>
3163
3164         <pre class="PROGRAMLISTING">    0 : invisible      or
3165     1 : normal    or
3166     2 : very visible.</pre>
3167       </div>
3168
3169       <div class="SECT2">
3170         <hr>
3171
3172         <h3 class="SECT2"><a name="TEMPLEAVE" id="TEMPLEAVE">14.2.
3173         Temporarily Leaving Curses mode</a></h3>
3174
3175         <p>Some times you may want to get back to cooked mode
3176         (normal line buffering mode) temporarily. In such a case
3177         you will first need to save the tty modes with a call to
3178         <tt class="LITERAL">def_prog_mode()</tt> and then call
3179         <tt class="LITERAL">endwin()</tt> to end the curses mode.
3180         This will leave you in the original tty mode. To get back
3181         to curses once you are done, call <tt class=
3182         "LITERAL">reset_prog_mode()</tt> . This function returns
3183         the tty to the state stored by <tt class=
3184         "LITERAL">def_prog_mode()</tt>. Then do refresh(), and you
3185         are back to the curses mode. Here is an example showing the
3186         sequence of things to be done.</p>
3187
3188         <div class="EXAMPLE">
3189           <a name="BTELE" id="BTELE"></a>
3190           <p><b>Example 12. Temporarily Leaving Curses Mode</b>
3191           </p>
3192
3193           <pre class="PROGRAMLISTING"><span class=
3194           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
3195 #include &lt;curses.h&gt;
3196
3197 int main()
3198 {       
3199         initscr();                      /* Start curses mode              */
3200         printw("Hello World !!!\n");    /* Print Hello World              */
3201         refresh();                      /* Print it on to the real screen */
3202         def_prog_mode();                /* Save the tty modes             */
3203         endwin();                       /* End curses mode temporarily    */
3204         system("/bin/sh");              /* Do whatever you like in cooked mode */
3205         reset_prog_mode();              /* Return to the previous tty mode*/
3206                                         /* stored by def_prog_mode()      */
3207         refresh();                      /* Do refresh() to restore the    */
3208                                         /* Screen contents                */
3209         printw("Another String\n");     /* Back to curses use the full    */
3210         refresh();                      /* capabilities of curses         */
3211         endwin();                       /* End curses mode                */
3212
3213         return 0;
3214 }</span></pre>
3215         </div>
3216       </div>
3217
3218       <div class="SECT2">
3219         <hr>
3220
3221         <h3 class="SECT2"><a name="ACSVARS" id="ACSVARS">14.3. ACS_
3222         variables</a></h3>
3223
3224         <p>If you have ever programmed in DOS, you know about those
3225         nifty characters in extended character set. They are
3226         printable only on some terminals. NCURSES functions like
3227         <tt class="LITERAL">box()</tt> use these characters. All
3228         these variables start with ACS meaning alternative
3229         character set. You might have noticed me using these
3230         characters in some of the programs above. Here is an
3231         example showing all the characters.</p>
3232
3233         <div class="EXAMPLE">
3234           <a name="BACSVARS" id="BACSVARS"></a>
3235           <p><b>Example 13. ACS Variables Example</b>
3236           </p>
3237
3238           <pre class="PROGRAMLISTING"><span class=
3239           "INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
3240
3241 int main()
3242 {
3243         initscr();
3244
3245         printw("Upper left corner           "); addch(ACS_ULCORNER); printw("\n"); 
3246         printw("Lower left corner           "); addch(ACS_LLCORNER); printw("\n");
3247         printw("Lower right corner          "); addch(ACS_LRCORNER); printw("\n");
3248         printw("Tee pointing right          "); addch(ACS_LTEE); printw("\n");
3249         printw("Tee pointing left           "); addch(ACS_RTEE); printw("\n");
3250         printw("Tee pointing up             "); addch(ACS_BTEE); printw("\n");
3251         printw("Tee pointing down           "); addch(ACS_TTEE); printw("\n");
3252         printw("Horizontal line             "); addch(ACS_HLINE); printw("\n");
3253         printw("Vertical line               "); addch(ACS_VLINE); printw("\n");
3254         printw("Large Plus or cross over    "); addch(ACS_PLUS); printw("\n");
3255         printw("Scan Line 1                 "); addch(ACS_S1); printw("\n");
3256         printw("Scan Line 3                 "); addch(ACS_S3); printw("\n");
3257         printw("Scan Line 7                 "); addch(ACS_S7); printw("\n");
3258         printw("Scan Line 9                 "); addch(ACS_S9); printw("\n");
3259         printw("Diamond                     "); addch(ACS_DIAMOND); printw("\n");
3260         printw("Checker board (stipple)     "); addch(ACS_CKBOARD); printw("\n");
3261         printw("Degree Symbol               "); addch(ACS_DEGREE); printw("\n");
3262         printw("Plus/Minus Symbol           "); addch(ACS_PLMINUS); printw("\n");
3263         printw("Bullet                      "); addch(ACS_BULLET); printw("\n");
3264         printw("Arrow Pointing Left         "); addch(ACS_LARROW); printw("\n");
3265         printw("Arrow Pointing Right        "); addch(ACS_RARROW); printw("\n");
3266         printw("Arrow Pointing Down         "); addch(ACS_DARROW); printw("\n");
3267         printw("Arrow Pointing Up           "); addch(ACS_UARROW); printw("\n");
3268         printw("Board of squares            "); addch(ACS_BOARD); printw("\n");
3269         printw("Lantern Symbol              "); addch(ACS_LANTERN); printw("\n");
3270         printw("Solid Square Block          "); addch(ACS_BLOCK); printw("\n");
3271         printw("Less/Equal sign             "); addch(ACS_LEQUAL); printw("\n");
3272         printw("Greater/Equal sign          "); addch(ACS_GEQUAL); printw("\n");
3273         printw("Pi                          "); addch(ACS_PI); printw("\n");
3274         printw("Not equal                   "); addch(ACS_NEQUAL); printw("\n");
3275         printw("UK pound sign               "); addch(ACS_STERLING); printw("\n");
3276
3277         refresh();
3278         getch();
3279         endwin();
3280
3281         return 0;
3282 }</span></pre>
3283         </div>
3284       </div>
3285     </div>
3286
3287     <div class="SECT1">
3288       <hr>
3289
3290       <h2 class="SECT1"><a name="OTHERLIB" id="OTHERLIB">15. Other
3291       libraries</a></h2>
3292
3293       <p>Apart from the curses library, there are few text mode
3294       libraries, which provide more functionality and a lot of
3295       features. The following sections explain three standard
3296       libraries which are usually distributed along with
3297       curses.</p>
3298     </div>
3299
3300     <div class="SECT1">
3301       <hr>
3302
3303       <h2 class="SECT1"><a name="PANELS" id="PANELS">16. Panel
3304       Library</a></h2>
3305
3306       <p>Now that you are proficient in curses, you wanted to do
3307       some thing big. You created a lot of overlapping windows to
3308       give a professional windows-type look. Unfortunately, it soon
3309       becomes difficult to manage these. The multiple refreshes,
3310       updates plunge you into a nightmare. The overlapping windows
3311       create blotches, whenever you forget to refresh the windows
3312       in the proper order.</p>
3313
3314       <p>Don't despair. There is an elegant solution provided in
3315       panels library. In the words of developers of ncurses</p>
3316
3317       <p><span class="emphasis"><i class="EMPHASIS">When your
3318       interface design is such that windows may dive deeper into
3319       the visibility stack or pop to the top at runtime, the
3320       resulting book-keeping can be tedious and difficult to get
3321       right. Hence the panels library.</i></span>
3322       </p>
3323
3324       <p>If you have lot of overlapping windows, then panels
3325       library is the way to go. It obviates the need of doing
3326       series of wnoutrefresh(), doupdate() and relieves the burden
3327       of doing it correctly(bottom up). The library maintains
3328       information about the order of windows, their overlapping and
3329       update the screen properly. So why wait? Let's take a close
3330       peek into panels.</p>
3331
3332       <div class="SECT2">
3333         <hr>
3334
3335         <h3 class="SECT2"><a name="PANELBASICS" id=
3336         "PANELBASICS">16.1. The Basics</a></h3>
3337
3338         <p>Panel object is a window that is implicitly treated as
3339         part of a deck including all other panel objects. The deck
3340         is treated as a stack with the top panel being completely
3341         visible and the other panels may or may not be obscured
3342         according to their positions. So the basic idea is to
3343         create a stack of overlapping panels and use panels library
3344         to display them correctly. There is a function similar to
3345         refresh() which, when called , displays panels in the
3346         correct order. Functions are provided to hide or show
3347         panels, move panels, change its size, etc. The overlapping
3348         problem is managed by the panels library during all the
3349         calls to these functions.</p>
3350
3351         <p>The general flow of a panel program goes like this:</p>
3352
3353         <ol type="1">
3354           <li>
3355             <p>Create the windows (with newwin()) to be attached to
3356             the panels.</p>
3357           </li>
3358
3359           <li>
3360             <p>Create panels with the chosen visibility order.
3361             Stack them up according to the desired visibility. The
3362             function new_panel() is used to created panels.</p>
3363           </li>
3364
3365           <li>
3366             <p>Call update_panels() to write the panels to the
3367             virtual screen in correct visibility order. Do a
3368             doupdate() to show it on the screen.</p>
3369           </li>
3370
3371           <li>
3372             <p>Mainpulate the panels with show_panel(),
3373             hide_panel(), move_panel(), etc. Make use of helper
3374             functions like panel_hidden() and panel_window(). Make
3375             use of user pointer to store custom data for a panel.
3376             Use the functions set_panel_userptr() and
3377             panel_userptr() to set and get the user pointer for a
3378             panel.</p>
3379           </li>
3380
3381           <li>
3382             <p>When you are done with the panel use del_panel() to
3383             delete the panel.</p>
3384           </li>
3385         </ol>
3386
3387         <p>Let's make the concepts clear, with some programs. The
3388         following is a simple program which creates 3 overlapping
3389         panels and shows them on the screen.</p>
3390       </div>
3391
3392       <div class="SECT2">
3393         <hr>
3394
3395         <h3 class="SECT2"><a name="COMPILEPANELS" id=
3396         "COMPILEPANELS">16.2. Compiling With the Panels Library</a></h3>
3397
3398         <p>To use panels library functions, you have to include
3399         panel.h and to link the program with panels library the
3400         flag -lpanel should be added along with -lncurses in that
3401         order.</p>
3402
3403         <pre class="PROGRAMLISTING">    #include &lt;panel.h&gt;
3404     .
3405     .
3406     .
3407
3408     compile and link: gcc &lt;program file&gt; -lpanel -lncurses</pre>
3409         <div class="EXAMPLE">
3410           <a name="PPASI" id="PPASI"></a>
3411           <p><b>Example 14. Panel basics</b>
3412           </p>
3413
3414           <pre class="PROGRAMLISTING"><span class=
3415           "INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3416
3417 int main()
3418 {       WINDOW *my_wins[3];
3419         PANEL  *my_panels[3];
3420         int lines = 10, cols = 40, y = 2, x = 4, i;
3421
3422         initscr();
3423         cbreak();
3424         noecho();
3425
3426         /* Create windows for the panels */
3427         my_wins[0] = newwin(lines, cols, y, x);
3428         my_wins[1] = newwin(lines, cols, y + 1, x + 5);
3429         my_wins[2] = newwin(lines, cols, y + 2, x + 10);
3430
3431         /* 
3432          * Create borders around the windows so that you can see the effect
3433          * of panels
3434          */
3435         for(i = 0; i &lt; 3; ++i)
3436                 box(my_wins[i], 0, 0);
3437
3438         /* Attach a panel to each window */     /* Order is bottom up */
3439         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3440         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3441         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3442
3443         /* Update the stacking order. 2nd panel will be on top */
3444         update_panels();
3445
3446         /* Show it on the screen */
3447         doupdate();
3448         
3449         getch();
3450         endwin();
3451 }
3452 </span></pre>
3453         </div>
3454
3455         <p>As you can see, above program follows a simple flow as
3456         explained. The windows are created with newwin() and then
3457         they are attached to panels with new_panel(). As we attach
3458         one panel after another, the stack of panels gets updated.
3459         To put them on screen update_panels() and doupdate() are
3460         called.</p>
3461       </div>
3462
3463       <div class="SECT2">
3464         <hr>
3465
3466         <h3 class="SECT2"><a name="PANELBROWSING" id=
3467         "PANELBROWSING">16.3. Panel Window Browsing</a></h3>
3468
3469         <p>A slightly complicated example is given below. This
3470         program creates 3 windows which can be cycled through using
3471         tab. Have a look at the code.</p>
3472
3473         <div class="EXAMPLE">
3474           <a name="PPABR" id="PPABR"></a>
3475           <p><b>Example 15. Panel Window Browsing Example</b>
3476           </p>
3477
3478           <pre class="PROGRAMLISTING"><span class=
3479           "INLINEMEDIAOBJECT">#include &lt;string.h&gt;
3480 #include &lt;panel.h&gt;
3481
3482 #define NLINES 10
3483 #define NCOLS 40
3484
3485 void init_wins(WINDOW **wins, int n);
3486 void win_show(WINDOW *win, char *label, int label_color);
3487 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3488
3489 int main()
3490 {       WINDOW *my_wins[3];
3491         PANEL  *my_panels[3];
3492         PANEL  *top;
3493         int ch;
3494
3495         /* Initialize curses */
3496         initscr();
3497         start_color();
3498         cbreak();
3499         noecho();
3500         keypad(stdscr, TRUE);
3501
3502         /* Initialize all the colors */
3503         init_pair(1, COLOR_RED, COLOR_BLACK);
3504         init_pair(2, COLOR_GREEN, COLOR_BLACK);
3505         init_pair(3, COLOR_BLUE, COLOR_BLACK);
3506         init_pair(4, COLOR_CYAN, COLOR_BLACK);
3507
3508         init_wins(my_wins, 3);
3509         
3510         /* Attach a panel to each window */     /* Order is bottom up */
3511         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3512         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3513         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3514
3515         /* Set up the user pointers to the next panel */
3516         set_panel_userptr(my_panels[0], my_panels[1]);
3517         set_panel_userptr(my_panels[1], my_panels[2]);
3518         set_panel_userptr(my_panels[2], my_panels[0]);
3519
3520         /* Update the stacking order. 2nd panel will be on top */
3521         update_panels();
3522
3523         /* Show it on the screen */
3524         attron(COLOR_PAIR(4));
3525         mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3526         attroff(COLOR_PAIR(4));
3527         doupdate();
3528
3529         top = my_panels[2];
3530         while((ch = getch()) != KEY_F(1))
3531         {       switch(ch)
3532                 {       case 9:
3533                                 top = (PANEL *)panel_userptr(top);
3534                                 top_panel(top);
3535                                 break;
3536                 }
3537                 update_panels();
3538                 doupdate();
3539         }
3540         endwin();
3541         return 0;
3542 }
3543
3544 /* Put all the windows */
3545 void init_wins(WINDOW **wins, int n)
3546 {       int x, y, i;
3547         char label[80];
3548
3549         y = 2;
3550         x = 10;
3551         for(i = 0; i &lt; n; ++i)
3552         {       wins[i] = newwin(NLINES, NCOLS, y, x);
3553                 sprintf(label, "Window Number %d", i + 1);
3554                 win_show(wins[i], label, i + 1);
3555                 y += 3;
3556                 x += 7;
3557         }
3558 }
3559
3560 /* Show the window with a border and a label */
3561 void win_show(WINDOW *win, char *label, int label_color)
3562 {       int startx, starty, height, width;
3563
3564         getbegyx(win, starty, startx);
3565         getmaxyx(win, height, width);
3566
3567         box(win, 0, 0);
3568         mvwaddch(win, 2, 0, ACS_LTEE); 
3569         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
3570         mvwaddch(win, 2, width - 1, ACS_RTEE); 
3571         
3572         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3573 }
3574
3575 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3576 {       int length, x, y;
3577         float temp;
3578
3579         if(win == NULL)
3580                 win = stdscr;
3581         getyx(win, y, x);
3582         if(startx != 0)
3583                 x = startx;
3584         if(starty != 0)
3585                 y = starty;
3586         if(width == 0)
3587                 width = 80;
3588
3589         length = strlen(string);
3590         temp = (width - length)/ 2;
3591         x = startx + (int)temp;
3592         wattron(win, color);
3593         mvwprintw(win, y, x, "%s", string);
3594         wattroff(win, color);
3595         refresh();
3596 }</span></pre>
3597         </div>
3598       </div>
3599
3600       <div class="SECT2">
3601         <hr>
3602
3603         <h3 class="SECT2"><a name="USERPTRUSING" id=
3604         "USERPTRUSING">16.4. Using User Pointers</a></h3>
3605
3606         <p>In the above example I used user pointers to find out
3607         the next window in the cycle. We can attach custom
3608         information to the panel by specifying a user pointer,
3609         which can point to any information you want to store. In
3610         this case I stored the pointer to the next panel in the
3611         cycle. User pointer for a panel can be set with the
3612         function <tt class="LITERAL">set_panel_userptr()</tt>. It
3613         can be accessed using the function <tt class=
3614         "LITERAL">panel_userptr()</tt> which will return the user
3615         pointer for the panel given as argument. After finding the
3616         next panel in the cycle, it is brought to the top by the
3617         function top_panel(). This function brings the panel given
3618         as argument to the top of the panel stack.</p>
3619       </div>
3620
3621       <div class="SECT2">
3622         <hr>
3623
3624         <h3 class="SECT2"><a name="PANELMOVERESIZE" id=
3625         "PANELMOVERESIZE">16.5. Moving and Resizing Panels</a></h3>
3626
3627         <p>The function <tt class="LITERAL">move_panel()</tt> can
3628         be used to move a panel to the desired location. It does
3629         not change the position of the panel in the stack. Make
3630         sure that you use move_panel() instead mvwin() on the
3631         window associated with the panel.</p>
3632
3633         <p>Resizing a panel is slightly complex. There is no
3634         straight forward function just to resize the window
3635         associated with a panel. A solution to resize a panel is to
3636         create a new window with the desired sizes, change the
3637         window associated with the panel using replace_panel().
3638         Don't forget to delete the old window. The window
3639         associated with a panel can be found by using the function
3640         panel_window().</p>
3641
3642         <p>The following program shows these concepts, in
3643         supposedly simple program. You can cycle through the window
3644         with &lt;TAB&gt; as usual. To resize or move the active
3645         panel press 'r' for resize 'm' for moving. Then use arrow
3646         keys to resize or move it to the desired way and press
3647         enter to end your resizing or moving. This example makes
3648         use of user data to get the required data to do the
3649         operations.</p>
3650
3651         <div class="EXAMPLE">
3652           <a name="PPARE" id="PPARE"></a>
3653           <p><b>Example 16. Panel Moving and Resizing example</b>
3654           </p>
3655
3656           <pre class="PROGRAMLISTING"><span class=
3657           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
3658 #include &lt;string.h&gt;
3659 #include &lt;panel.h&gt;
3660
3661 typedef struct _PANEL_DATA {
3662         int x, y, w, h;
3663         char label[80]; 
3664         int label_color;
3665         PANEL *next;
3666 }PANEL_DATA;
3667
3668 #define NLINES 10
3669 #define NCOLS 40
3670
3671 void init_wins(WINDOW **wins, int n);
3672 void win_show(WINDOW *win, char *label, int label_color);
3673 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3674 void set_user_ptrs(PANEL **panels, int n);
3675
3676 int main()
3677 {       WINDOW *my_wins[3];
3678         PANEL  *my_panels[3];
3679         PANEL_DATA  *top;
3680         PANEL *stack_top;
3681         WINDOW *temp_win, *old_win;
3682         int ch;
3683         int newx, newy, neww, newh;
3684         int size = FALSE, move = FALSE;
3685
3686         /* Initialize curses */
3687         initscr();
3688         start_color();
3689         cbreak();
3690         noecho();
3691         keypad(stdscr, TRUE);
3692
3693         /* Initialize all the colors */
3694         init_pair(1, COLOR_RED, COLOR_BLACK);
3695         init_pair(2, COLOR_GREEN, COLOR_BLACK);
3696         init_pair(3, COLOR_BLUE, COLOR_BLACK);
3697         init_pair(4, COLOR_CYAN, COLOR_BLACK);
3698
3699         init_wins(my_wins, 3);
3700         
3701         /* Attach a panel to each window */     /* Order is bottom up */
3702         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3703         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3704         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3705
3706         set_user_ptrs(my_panels, 3);
3707         /* Update the stacking order. 2nd panel will be on top */
3708         update_panels();
3709
3710         /* Show it on the screen */
3711         attron(COLOR_PAIR(4));
3712         mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3713         mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3714         attroff(COLOR_PAIR(4));
3715         doupdate();
3716
3717         stack_top = my_panels[2];
3718         top = (PANEL_DATA *)panel_userptr(stack_top);
3719         newx = top-&gt;x;
3720         newy = top-&gt;y;
3721         neww = top-&gt;w;
3722         newh = top-&gt;h;
3723         while((ch = getch()) != KEY_F(1))
3724         {       switch(ch)
3725                 {       case 9:         /* Tab */
3726                                 top = (PANEL_DATA *)panel_userptr(stack_top);
3727                                 top_panel(top-&gt;next);
3728                                 stack_top = top-&gt;next;
3729                                 top = (PANEL_DATA *)panel_userptr(stack_top);
3730                                 newx = top-&gt;x;
3731                                 newy = top-&gt;y;
3732                                 neww = top-&gt;w;
3733                                 newh = top-&gt;h;
3734                                 break;
3735                         case 'r':       /* Re-Size*/
3736                                 size = TRUE;
3737                                 attron(COLOR_PAIR(4));
3738                                 mvprintw(LINES - 4, 0, "Entered Resizing :Use Arrow Keys to resize and press &lt;ENTER&gt; to end resizing");
3739                                 refresh();
3740                                 attroff(COLOR_PAIR(4));
3741                                 break;
3742                         case 'm':       /* Move */
3743                                 attron(COLOR_PAIR(4));
3744                                 mvprintw(LINES - 4, 0, "Entered Moving: Use Arrow Keys to Move and press &lt;ENTER&gt; to end moving");
3745                                 refresh();
3746                                 attroff(COLOR_PAIR(4));
3747                                 move = TRUE;
3748                                 break;
3749                         case KEY_LEFT:
3750                                 if(size == TRUE)
3751                                 {       --newx;
3752                                         ++neww;
3753                                 }
3754                                 if(move == TRUE)
3755                                         --newx;
3756                                 break;
3757                         case KEY_RIGHT:
3758                                 if(size == TRUE)
3759                                 {       ++newx;
3760                                         --neww;
3761                                 }
3762                                 if(move == TRUE)
3763                                         ++newx;
3764                                 break;
3765                         case KEY_UP:
3766                                 if(size == TRUE)
3767                                 {       --newy;
3768                                         ++newh;
3769                                 }
3770                                 if(move == TRUE)
3771                                         --newy;
3772                                 break;
3773                         case KEY_DOWN:
3774                                 if(size == TRUE)
3775                                 {       ++newy;
3776                                         --newh;
3777                                 }
3778                                 if(move == TRUE)
3779                                         ++newy;
3780                                 break;
3781                         case 10:        /* Enter */
3782                                 move(LINES - 4, 0);
3783                                 clrtoeol();
3784                                 refresh();
3785                                 if(size == TRUE)
3786                                 {       old_win = panel_window(stack_top);
3787                                         temp_win = newwin(newh, neww, newy, newx);
3788                                         replace_panel(stack_top, temp_win);
3789                                         win_show(temp_win, top-&gt;label, top-&gt;label_color); 
3790                                         delwin(old_win);
3791                                         size = FALSE;
3792                                 }
3793                                 if(move == TRUE)
3794                                 {       move_panel(stack_top, newy, newx);
3795                                         move = FALSE;
3796                                 }
3797                                 break;
3798                         
3799                 }
3800                 attron(COLOR_PAIR(4));
3801                 mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3802                 mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3803                 attroff(COLOR_PAIR(4));
3804                 refresh();      
3805                 update_panels();
3806                 doupdate();
3807         }
3808         endwin();
3809         return 0;
3810 }
3811
3812 /* Put all the windows */
3813 void init_wins(WINDOW **wins, int n)
3814 {       int x, y, i;
3815         char label[80];
3816
3817         y = 2;
3818         x = 10;
3819         for(i = 0; i &lt; n; ++i)
3820         {       wins[i] = newwin(NLINES, NCOLS, y, x);
3821                 sprintf(label, "Window Number %d", i + 1);
3822                 win_show(wins[i], label, i + 1);
3823                 y += 3;
3824                 x += 7;
3825         }
3826 }
3827
3828 /* Set the PANEL_DATA structures for individual panels */
3829 void set_user_ptrs(PANEL **panels, int n)
3830 {       PANEL_DATA *ptrs;
3831         WINDOW *win;
3832         int x, y, w, h, i;
3833         char temp[80];
3834         
3835         ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA));
3836
3837         for(i = 0;i &lt; n; ++i)
3838         {       win = panel_window(panels[i]);
3839                 getbegyx(win, y, x);
3840                 getmaxyx(win, h, w);
3841                 ptrs[i].x = x;
3842                 ptrs[i].y = y;
3843                 ptrs[i].w = w;
3844                 ptrs[i].h = h;
3845                 sprintf(temp, "Window Number %d", i + 1);
3846                 strcpy(ptrs[i].label, temp);
3847                 ptrs[i].label_color = i + 1;
3848                 if(i + 1 == n)
3849                         ptrs[i].next = panels[0];
3850                 else
3851                         ptrs[i].next = panels[i + 1];
3852                 set_panel_userptr(panels[i], &amp;ptrs[i]);
3853         }
3854 }
3855
3856 /* Show the window with a border and a label */
3857 void win_show(WINDOW *win, char *label, int label_color)
3858 {       int startx, starty, height, width;
3859
3860         getbegyx(win, starty, startx);
3861         getmaxyx(win, height, width);
3862
3863         box(win, 0, 0);
3864         mvwaddch(win, 2, 0, ACS_LTEE); 
3865         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
3866         mvwaddch(win, 2, width - 1, ACS_RTEE); 
3867         
3868         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3869 }
3870
3871 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3872 {       int length, x, y;
3873         float temp;
3874
3875         if(win == NULL)
3876                 win = stdscr;
3877         getyx(win, y, x);
3878         if(startx != 0)
3879                 x = startx;
3880         if(starty != 0)
3881                 y = starty;
3882         if(width == 0)
3883                 width = 80;
3884
3885         length = strlen(string);
3886         temp = (width - length)/ 2;
3887         x = startx + (int)temp;
3888         wattron(win, color);
3889         mvwprintw(win, y, x, "%s", string);
3890         wattroff(win, color);
3891         refresh();
3892 }</span></pre>
3893         </div>
3894
3895         <p>Concentrate on the main while loop. Once it finds out
3896         the type of key pressed, it takes appropriate action. If
3897         'r' is pressed resizing mode is started. After this the new
3898         sizes are updated as the user presses the arrow keys. When
3899         the user presses &lt;ENTER&gt; present selection ends and
3900         panel is resized by using the concept explained. While in
3901         resizing mode the program doesn't show how the window is
3902         getting resized. It is left as an exercise to the reader to
3903         print a dotted border while it gets resized to a new
3904         position.</p>
3905
3906         <p>When the user presses 'm' the move mode starts. This is
3907         a bit simpler than resizing. As the arrow keys are pressed
3908         the new position is updated and pressing of &lt;ENTER&gt;
3909         causes the panel to be moved by calling the function
3910         move_panel().</p>
3911
3912         <p>In this program the user data which is represented as
3913         PANEL_DATA, plays very important role in finding the
3914         associated information with a panel. As written in the
3915         comments, the PANEL_DATA stores the panel sizes, label,
3916         label color and a pointer to the next panel in the
3917         cycle.</p>
3918       </div>
3919
3920       <div class="SECT2">
3921         <hr>
3922
3923         <h3 class="SECT2"><a name="PANELSHOWHIDE" id=
3924         "PANELSHOWHIDE">16.6. Hiding and Showing Panels</a></h3>
3925
3926         <p>A Panel can be hidden by using the function
3927         hide_panel(). This function merely removes it form the
3928         stack of panels, thus hiding it on the screen once you do
3929         update_panels() and doupdate(). It doesn't destroy the
3930         PANEL structure associated with the hidden panel. It can be
3931         shown again by using the show_panel() function.</p>
3932
3933         <p>The following program shows the hiding of panels. Press
3934         'a' or 'b' or 'c' to show or hide first, second and third
3935         windows respectively. It uses a user data with a small
3936         variable hide, which keeps track of whether the window is
3937         hidden or not. For some reason the function <tt class=
3938         "LITERAL">panel_hidden()</tt> which tells whether a panel
3939         is hidden or not is not working. A bug report was also
3940         presented by Michael Andres <a href=
3941         "http://www.geocrawler.com/archives/3/344/1999/9/0/2643549/"
3942         target="_top">here</a></p>
3943
3944         <div class="EXAMPLE">
3945           <a name="PPAHI" id="PPAHI"></a>
3946           <p><b>Example 17. Panel Hiding and Showing example</b>
3947           </p>
3948
3949           <pre class="PROGRAMLISTING"><span class=
3950           "INLINEMEDIAOBJECT">#include &lt;string.h&gt;
3951 #include &lt;panel.h&gt;
3952
3953 typedef struct _PANEL_DATA {
3954         int hide;       /* TRUE if panel is hidden */
3955 }PANEL_DATA;
3956
3957 #define NLINES 10
3958 #define NCOLS 40
3959
3960 void init_wins(WINDOW **wins, int n);
3961 void win_show(WINDOW *win, char *label, int label_color);
3962 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3963
3964 int main()
3965 {       WINDOW *my_wins[3];
3966         PANEL  *my_panels[3];
3967         PANEL_DATA panel_datas[3];
3968         PANEL_DATA *temp;
3969         int ch;
3970
3971         /* Initialize curses */
3972         initscr();
3973         start_color();
3974         cbreak();
3975         noecho();
3976         keypad(stdscr, TRUE);
3977
3978         /* Initialize all the colors */
3979         init_pair(1, COLOR_RED, COLOR_BLACK);
3980         init_pair(2, COLOR_GREEN, COLOR_BLACK);
3981         init_pair(3, COLOR_BLUE, COLOR_BLACK);
3982         init_pair(4, COLOR_CYAN, COLOR_BLACK);
3983
3984         init_wins(my_wins, 3);
3985         
3986         /* Attach a panel to each window */     /* Order is bottom up */
3987         my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3988         my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3989         my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3990
3991         /* Initialize panel data saying that nothing is hidden */
3992         panel_datas[0].hide = FALSE;
3993         panel_datas[1].hide = FALSE;
3994         panel_datas[2].hide = FALSE;
3995
3996         set_panel_userptr(my_panels[0], &amp;panel_datas[0]);
3997         set_panel_userptr(my_panels[1], &amp;panel_datas[1]);
3998         set_panel_userptr(my_panels[2], &amp;panel_datas[2]);
3999
4000         /* Update the stacking order. 2nd panel will be on top */
4001         update_panels();
4002
4003         /* Show it on the screen */
4004         attron(COLOR_PAIR(4));
4005         mvprintw(LINES - 3, 0, "Show or Hide a window with 'a'(first window)  'b'(Second Window)  'c'(Third Window)");
4006         mvprintw(LINES - 2, 0, "F1 to Exit");
4007
4008         attroff(COLOR_PAIR(4));
4009         doupdate();
4010         
4011         while((ch = getch()) != KEY_F(1))
4012         {       switch(ch)
4013                 {       case 'a':                       
4014                                 temp = (PANEL_DATA *)panel_userptr(my_panels[0]);
4015                                 if(temp-&gt;hide == FALSE)
4016                                 {       hide_panel(my_panels[0]);
4017                                         temp-&gt;hide = TRUE;
4018                                 }
4019                                 else
4020                                 {       show_panel(my_panels[0]);
4021                                         temp-&gt;hide = FALSE;
4022                                 }
4023                                 break;
4024                         case 'b':
4025                                 temp = (PANEL_DATA *)panel_userptr(my_panels[1]);
4026                                 if(temp-&gt;hide == FALSE)
4027                                 {       hide_panel(my_panels[1]);
4028                                         temp-&gt;hide = TRUE;
4029                                 }
4030                                 else
4031                                 {       show_panel(my_panels[1]);
4032                                         temp-&gt;hide = FALSE;
4033                                 }
4034                                 break;
4035                         case 'c':
4036                                 temp = (PANEL_DATA *)panel_userptr(my_panels[2]);
4037                                 if(temp-&gt;hide == FALSE)
4038                                 {       hide_panel(my_panels[2]);
4039                                         temp-&gt;hide = TRUE;
4040                                 }
4041                                 else
4042                                 {       show_panel(my_panels[2]);
4043                                         temp-&gt;hide = FALSE;
4044                                 }
4045                                 break;
4046                 }
4047                 update_panels();
4048                 doupdate();
4049         }
4050         endwin();
4051         return 0;
4052 }
4053
4054 /* Put all the windows */
4055 void init_wins(WINDOW **wins, int n)
4056 {       int x, y, i;
4057         char label[80];
4058
4059         y = 2;
4060         x = 10;
4061         for(i = 0; i &lt; n; ++i)
4062         {       wins[i] = newwin(NLINES, NCOLS, y, x);
4063                 sprintf(label, "Window Number %d", i + 1);
4064                 win_show(wins[i], label, i + 1);
4065                 y += 3;
4066                 x += 7;
4067         }
4068 }
4069
4070 /* Show the window with a border and a label */
4071 void win_show(WINDOW *win, char *label, int label_color)
4072 {       int startx, starty, height, width;
4073
4074         getbegyx(win, starty, startx);
4075         getmaxyx(win, height, width);
4076
4077         box(win, 0, 0);
4078         mvwaddch(win, 2, 0, ACS_LTEE); 
4079         mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
4080         mvwaddch(win, 2, width - 1, ACS_RTEE); 
4081         
4082         print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
4083 }
4084
4085 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4086 {       int length, x, y;
4087         float temp;
4088
4089         if(win == NULL)
4090                 win = stdscr;
4091         getyx(win, y, x);
4092         if(startx != 0)
4093                 x = startx;
4094         if(starty != 0)
4095                 y = starty;
4096         if(width == 0)
4097                 width = 80;
4098
4099         length = strlen(string);
4100         temp = (width - length)/ 2;
4101         x = startx + (int)temp;
4102         wattron(win, color);
4103         mvwprintw(win, y, x, "%s", string);
4104         wattroff(win, color);
4105         refresh();
4106 }</span></pre>
4107         </div>
4108       </div>
4109
4110       <div class="SECT2">
4111         <hr>
4112
4113         <h3 class="SECT2"><a name="PANELABOVE" id=
4114         "PANELABOVE">16.7. panel_above() and panel_below()
4115         Functions</a></h3>
4116
4117         <p>The functions <tt class="LITERAL">panel_above()</tt> and
4118         <tt class="LITERAL">panel_below()</tt> can be used to find
4119         out the panel above and below a panel. If the argument to
4120         these functions is NULL, then they return a pointer to
4121         bottom panel and top panel respectively.</p>
4122       </div>
4123     </div>
4124
4125     <div class="SECT1">
4126       <hr>
4127
4128       <h2 class="SECT1"><a name="MENUS" id="MENUS">17. Menus
4129       Library</a></h2>
4130
4131       <p>The menus library provides a nice extension to basic
4132       curses, through which you can create menus. It provides a set
4133       of functions to create menus. But they have to be customized
4134       to give a nicer look, with colors, etc. Let's get into the
4135       details.</p>
4136
4137       <p>A menu is a screen display that assists the user to choose
4138       some subset of a given set of items. To put it simple, a menu
4139       is a collection of items from which one or more items can be
4140       chosen. Some readers might not be aware of multiple item
4141       selection capability. Menu library provides functionality to
4142       write menus from which the user can chose more than one item
4143       as the preferred choice. This is dealt with in a later
4144       section. Now it is time for some rudiments.</p>
4145
4146       <div class="SECT2">
4147         <hr>
4148
4149         <h3 class="SECT2"><a name="MENUBASICS" id=
4150         "MENUBASICS">17.1. The Basics</a></h3>
4151
4152         <p>To create menus, you first create items, and then post
4153         the menu to the display. After that, all the processing of
4154         user responses is done in an elegant function menu_driver()
4155         which is the work horse of any menu program.</p>
4156
4157         <p>The general flow of control of a menu program looks like
4158         this.</p>
4159
4160         <ol type="1">
4161           <li>
4162             <p>Initialize curses</p>
4163           </li>
4164
4165           <li>
4166             <p>Create items using new_item(). You can specify a
4167             name and description for the items.</p>
4168           </li>
4169
4170           <li>
4171             <p>Create the menu with new_menu() by specifying the
4172             items to be attached with.</p>
4173           </li>
4174
4175           <li>
4176             <p>Post the menu with menu_post() and refresh the
4177             screen.</p>
4178           </li>
4179
4180           <li>
4181             <p>Process the user requests with a loop and do
4182             necessary updates to menu with menu_driver.</p>
4183           </li>
4184
4185           <li>
4186             <p>Unpost the menu with menu_unpost()</p>
4187           </li>
4188
4189           <li>
4190             <p>Free the memory allocated to menu by free_menu()</p>
4191           </li>
4192
4193           <li>
4194             <p>Free the memory allocated to the items with
4195             free_item()</p>
4196           </li>
4197
4198           <li>
4199             <p>End curses</p>
4200           </li>
4201         </ol>
4202
4203         <p>Let's see a program which prints a simple menu and
4204         updates the current selection with up, down arrows.</p>
4205       </div>
4206
4207       <div class="SECT2">
4208         <hr>
4209
4210         <h3 class="SECT2"><a name="COMPILEMENUS" id=
4211         "COMPILEMENUS">17.2. Compiling With the Menu Library</a></h3>
4212
4213         <p>To use menu library functions, you have to include
4214         menu.h and to link the program with menu library the flag
4215         -lmenu should be added along with -lncurses in that
4216         order.</p>
4217
4218         <pre class="PROGRAMLISTING">    #include &lt;menu.h&gt;
4219     .
4220     .
4221     .
4222
4223     compile and link: gcc &lt;program file&gt; -lmenu -lncurses</pre>
4224         <div class="EXAMPLE">
4225           <a name="MMESI" id="MMESI"></a>
4226           <p><b>Example 18. Menu Basics</b>
4227           </p>
4228
4229           <pre class="PROGRAMLISTING"><span class=
4230           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
4231 #include &lt;curses.h&gt;
4232 #include &lt;menu.h&gt;
4233
4234 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4235 #define CTRLD   4
4236
4237 char *choices[] = {
4238                         "Choice 1",
4239                         "Choice 2",
4240                         "Choice 3",
4241                         "Choice 4",
4242                         "Exit",
4243                   };
4244
4245 int main()
4246 {       ITEM **my_items;
4247         int c;                          
4248         MENU *my_menu;
4249         int n_choices, i;
4250         ITEM *cur_item;
4251         
4252         
4253         initscr();
4254         cbreak();
4255         noecho();
4256         keypad(stdscr, TRUE);
4257         
4258         n_choices = ARRAY_SIZE(choices);
4259         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
4260
4261         for(i = 0; i &lt; n_choices; ++i)
4262                 my_items[i] = new_item(choices[i], choices[i]);
4263         my_items[n_choices] = (ITEM *)NULL;
4264
4265         my_menu = new_menu((ITEM **)my_items);
4266         mvprintw(LINES - 2, 0, "F1 to Exit");
4267         post_menu(my_menu);
4268         refresh();
4269
4270         while((c = getch()) != KEY_F(1))
4271         {   switch(c)
4272             {   case KEY_DOWN:
4273                         menu_driver(my_menu, REQ_DOWN_ITEM);
4274                                 break;
4275                         case KEY_UP:
4276                                 menu_driver(my_menu, REQ_UP_ITEM);
4277                                 break;
4278                 }
4279         }       
4280
4281         free_item(my_items[0]);
4282         free_item(my_items[1]);
4283         free_menu(my_menu);
4284         endwin();
4285 }
4286         </span></pre>
4287         </div>
4288
4289         <p>This program demonstrates the basic concepts involved in
4290         creating a menu using menus library. First we create the
4291         items using new_item() and then attach them to the menu
4292         with new_menu() function. After posting the menu and
4293         refreshing the screen, the main processing loop starts. It
4294         reads user input and takes corresponding action. The
4295         function menu_driver() is the main work horse of the menu
4296         system. The second parameter to this function tells what's
4297         to be done with the menu. According to the parameter,
4298         menu_driver() does the corresponding task. The value can be
4299         either a menu navigational request, an ascii character, or
4300         a KEY_MOUSE special key associated with a mouse event.</p>
4301
4302         <p>The menu_driver accepts following navigational
4303         requests.</p>
4304
4305         <pre class=
4306         "PROGRAMLISTING">&#13;     REQ_LEFT_ITEM         Move left to an item.
4307      REQ_RIGHT_ITEM      Move right to an item.
4308      REQ_UP_ITEM         Move up to an item.
4309      REQ_DOWN_ITEM       Move down to an item.
4310      REQ_SCR_ULINE       Scroll up a line.
4311      REQ_SCR_DLINE          Scroll down a line.
4312      REQ_SCR_DPAGE          Scroll down a page.
4313      REQ_SCR_UPAGE         Scroll up a page.
4314      REQ_FIRST_ITEM     Move to the first item.
4315      REQ_LAST_ITEM         Move to the last item.
4316      REQ_NEXT_ITEM         Move to the next item.
4317      REQ_PREV_ITEM         Move to the previous item. 
4318      REQ_TOGGLE_ITEM     Select/deselect an item.
4319      REQ_CLEAR_PATTERN     Clear the menu pattern buffer.
4320      REQ_BACK_PATTERN      Delete the previous character from the pattern buffer.
4321      REQ_NEXT_MATCH     Move to the next item matching the pattern match.
4322      REQ_PREV_MATCH     Move to the previous item matching the pattern match.&#13;</pre>
4323         <p>Don't get overwhelmed by the number of options. We will
4324         see them slowly one after another. The options of interest
4325         in this example are REQ_UP_ITEM and REQ_DOWN_ITEM. These
4326         two options when passed to menu_driver, menu driver updates
4327         the current item to one item up or down respectively.</p>
4328       </div>
4329
4330       <div class="SECT2">
4331         <hr>
4332
4333         <h3 class="SECT2"><a name="MENUDRIVER" id=
4334         "MENUDRIVER">17.3. Menu Driver: The work horse of the menu
4335         system</a></h3>
4336
4337         <p>As you have seen in the above example, menu_driver plays
4338         an important role in updating the menu. It is very
4339         important to understand various options it takes and what
4340         they do. As explained above, the second parameter to
4341         menu_driver() can be either a navigational request, a
4342         printable character or a KEY_MOUSE key. Let's dissect the
4343         different navigational requests.</p>
4344
4345         <ul>
4346           <li>
4347             <p><span class="emphasis"><i class=
4348             "EMPHASIS">REQ_LEFT_ITEM and REQ_RIGHT_ITEM</i></span>
4349             </p>
4350
4351             <p>A Menu can be displayed with multiple columns for
4352             more than one item. This can be done by using the
4353             <tt class="LITERAL">menu_format()</tt>function. When a
4354             multi columnar menu is displayed these requests cause
4355             the menu driver to move the current selection to left
4356             or right.</p>
4357           </li>
4358
4359           <li>
4360             <p><span class="emphasis"><i class=
4361             "EMPHASIS">REQ_UP_ITEM and REQ_DOWN_ITEM</i></span>
4362             </p>
4363
4364             <p>These two options you have seen in the above
4365             example. These options when given, makes the
4366             menu_driver to move the current selection to an item up
4367             or down.</p>
4368           </li>
4369
4370           <li>
4371             <p><span class="emphasis"><i class="EMPHASIS">REQ_SCR_*
4372             options</i></span>
4373             </p>
4374
4375             <p>The four options REQ_SCR_ULINE, REQ_SCR_DLINE,
4376             REQ_SCR_DPAGE, REQ_SCR_UPAGE are related to scrolling.
4377             If all the items in the menu cannot be displayed in the
4378             menu sub window, then the menu is scrollable. These
4379             requests can be given to the menu_driver to do the
4380             scrolling either one line up, down or one page down or
4381             up respectively.</p>
4382           </li>
4383
4384           <li>
4385             <p><span class="emphasis"><i class=
4386             "EMPHASIS">REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_NEXT_ITEM
4387             and REQ_PREV_ITEM</i></span>
4388             </p>
4389
4390             <p>These requests are self explanatory.</p>
4391           </li>
4392
4393           <li>
4394             <p><span class="emphasis"><i class=
4395             "EMPHASIS">REQ_TOGGLE_ITEM</i></span>
4396             </p>
4397
4398             <p>This request when given, toggles the present
4399             selection. This option is to be used only in a multi
4400             valued menu. So to use this request the option
4401             O_ONEVALUE must be off. This option can be made off or
4402             on with set_menu_opts().</p>
4403           </li>
4404
4405           <li>
4406             <p><span class="emphasis"><i class="EMPHASIS">Pattern
4407             Requests</i></span>
4408             </p>
4409
4410             <p>Every menu has an associated pattern buffer, which
4411             is used to find the nearest match to the ascii
4412             characters entered by the user. Whenever ascii
4413             characters are given to menu_driver, it puts in to the
4414             pattern buffer. It also tries to find the nearest match
4415             to the pattern in the items list and moves current
4416             selection to that item. The request REQ_CLEAR_PATTERN
4417             clears the pattern buffer. The request REQ_BACK_PATTERN
4418             deletes the previous character in the pattern buffer.
4419             In case the pattern matches more than one item then the
4420             matched items can be cycled through REQ_NEXT_MATCH and
4421             REQ_PREV_MATCH which move the current selection to the
4422             next and previous matches respectively.</p>
4423           </li>
4424
4425           <li>
4426             <p><span class="emphasis"><i class="EMPHASIS">Mouse
4427             Requests</i></span>
4428             </p>
4429
4430             <p>In case of KEY_MOUSE requests, according to the
4431             mouse position an action is taken accordingly. The
4432             action to be taken is explained in the man page as,</p>
4433
4434             <pre class="PROGRAMLISTING"><span class=
4435             "emphasis"><i class=
4436             "EMPHASIS">       If  the  second argument is the KEY_MOUSE special key, the
4437        associated mouse event is translated into one of the above
4438        pre-defined  requests.   Currently only clicks in the user
4439        window (e.g. inside the menu display area or  the  decora&shy;
4440        tion  window)  are handled. If you click above the display
4441        region of the menu, a REQ_SCR_ULINE is generated,  if  you
4442        doubleclick  a  REQ_SCR_UPAGE  is  generated  and  if  you
4443        tripleclick a REQ_FIRST_ITEM is generated.  If  you  click
4444        below  the  display region of the menu, a REQ_SCR_DLINE is
4445        generated, if you doubleclick a REQ_SCR_DPAGE is generated
4446        and  if  you  tripleclick a REQ_LAST_ITEM is generated. If
4447        you click at an item inside the display area of the  menu,
4448        the menu cursor is positioned to that item.</i></span></pre>
4449           </li>
4450         </ul>
4451
4452         <p>Each of the above requests will be explained in the
4453         following lines with several examples whenever
4454         appropriate.</p>
4455       </div>
4456
4457       <div class="SECT2">
4458         <hr>
4459
4460         <h3 class="SECT2"><a name="MENUWINDOWS" id=
4461         "MENUWINDOWS">17.4. Menu Windows</a></h3>
4462
4463         <p>Every menu created is associated with a window and a sub
4464         window. The menu window displays any title or border
4465         associated with the menu. The menu sub window displays the
4466         menu items currently available for selection. But we didn't
4467         specify any window or sub window in the simple example.
4468         When a window is not specified, stdscr is taken as the main
4469         window, and then menu system calculates the sub window size
4470         required for the display of items. Then items are displayed
4471         in the calculated sub window. So let's play with these
4472         windows and display a menu with a border and a title.</p>
4473
4474         <div class="EXAMPLE">
4475           <a name="MMEWI" id="MMEWI"></a>
4476           <p><b>Example 19. Menu Windows Usage example</b>
4477           </p>
4478
4479           <pre class="PROGRAMLISTING"><span class=
4480           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
4481 #include &lt;string.h&gt;
4482 #include &lt;menu.h&gt;
4483
4484 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4485 #define CTRLD   4
4486
4487 char *choices[] = {
4488                         "Choice 1",
4489                         "Choice 2",
4490                         "Choice 3",
4491                         "Choice 4",
4492                         "Exit",
4493                         (char *)NULL,
4494                   };
4495 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4496
4497 int main()
4498 {       ITEM **my_items;
4499         int c;                          
4500         MENU *my_menu;
4501         WINDOW *my_menu_win;
4502         int n_choices, i;
4503         
4504         /* Initialize curses */
4505         initscr();
4506         start_color();
4507         cbreak();
4508         noecho();
4509         keypad(stdscr, TRUE);
4510         init_pair(1, COLOR_RED, COLOR_BLACK);
4511
4512         /* Create items */
4513         n_choices = ARRAY_SIZE(choices);
4514         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4515         for(i = 0; i &lt; n_choices; ++i)
4516                 my_items[i] = new_item(choices[i], choices[i]);
4517
4518         /* Crate menu */
4519         my_menu = new_menu((ITEM **)my_items);
4520
4521         /* Create the window to be associated with the menu */
4522         my_menu_win = newwin(10, 40, 4, 4);
4523         keypad(my_menu_win, TRUE);
4524      
4525         /* Set main window and sub window */
4526         set_menu_win(my_menu, my_menu_win);
4527         set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4528
4529         /* Set menu mark to the string " * " */
4530         set_menu_mark(my_menu, " * ");
4531
4532         /* Print a border around the main window and print a title */
4533         box(my_menu_win, 0, 0);
4534         print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4535         mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4536         mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4537         mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4538         mvprintw(LINES - 2, 0, "F1 to exit");
4539         refresh();
4540         
4541         /* Post the menu */
4542         post_menu(my_menu);
4543         wrefresh(my_menu_win);
4544
4545         while((c = wgetch(my_menu_win)) != KEY_F(1))
4546         {       switch(c)
4547                 {       case KEY_DOWN:
4548                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4549                                 break;
4550                         case KEY_UP:
4551                                 menu_driver(my_menu, REQ_UP_ITEM);
4552                                 break;
4553                 }
4554                 wrefresh(my_menu_win);
4555         }       
4556
4557         /* Unpost and free all the memory taken up */
4558         unpost_menu(my_menu);
4559         free_menu(my_menu);
4560         for(i = 0; i &lt; n_choices; ++i)
4561                 free_item(my_items[i]);
4562         endwin();
4563 }
4564
4565 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4566 {       int length, x, y;
4567         float temp;
4568
4569         if(win == NULL)
4570                 win = stdscr;
4571         getyx(win, y, x);
4572         if(startx != 0)
4573                 x = startx;
4574         if(starty != 0)
4575                 y = starty;
4576         if(width == 0)
4577                 width = 80;
4578
4579         length = strlen(string);
4580         temp = (width - length)/ 2;
4581         x = startx + (int)temp;
4582         wattron(win, color);
4583         mvwprintw(win, y, x, "%s", string);
4584         wattroff(win, color);
4585         refresh();
4586 }</span></pre>
4587         </div>
4588
4589         <p>This example creates a menu with a title, border, a
4590         fancy line separating title and the items. As you can see,
4591         in order to attach a window to a menu the function
4592         set_menu_win() has to be used. Then we attach the sub
4593         window also. This displays the items in the sub window. You
4594         can also set the mark string which gets displayed to the
4595         left of the selected item with set_menu_mark().</p>
4596       </div>
4597
4598       <div class="SECT2">
4599         <hr>
4600
4601         <h3 class="SECT2"><a name="SCROLLMENUS" id=
4602         "SCROLLMENUS">17.5. Scrolling Menus</a></h3>
4603
4604         <p>If the sub window given for a window is not big enough
4605         to show all the items, then the menu will be scrollable.
4606         When you are on the last item in the present list, if you
4607         send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE
4608         and the menu scrolls by one item. You can manually give
4609         REQ_SCR_ operations to do scrolling. Let's see how it can
4610         be done.</p>
4611
4612         <div class="EXAMPLE">
4613           <a name="MMESC" id="MMESC"></a>
4614           <p><b>Example 20. Scrolling Menus example</b>
4615           </p>
4616
4617           <pre class="PROGRAMLISTING"><span class=
4618           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
4619 #include &lt;string.h&gt;
4620 #include &lt;curses.h&gt;
4621 #include &lt;menu.h&gt;
4622
4623 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4624 #define CTRLD   4
4625
4626 char *choices[] = {
4627                         "Choice 1",
4628                         "Choice 2",
4629                         "Choice 3",
4630                         "Choice 4",
4631                         "Choice 5",
4632                         "Choice 6",
4633                         "Choice 7",
4634                         "Choice 8",
4635                         "Choice 9",
4636                         "Choice 10",
4637                         "Exit",
4638                         (char *)NULL,
4639                   };
4640 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4641
4642 int main()
4643 {       ITEM **my_items;
4644         int c;                          
4645         MENU *my_menu;
4646         WINDOW *my_menu_win;
4647         int n_choices, i;
4648         
4649         /* Initialize curses */
4650         initscr();
4651         start_color();
4652         cbreak();
4653         noecho();
4654         keypad(stdscr, TRUE);
4655         init_pair(1, COLOR_RED, COLOR_BLACK);
4656         init_pair(2, COLOR_CYAN, COLOR_BLACK);
4657
4658         /* Create items */
4659         n_choices = ARRAY_SIZE(choices);
4660         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4661         for(i = 0; i &lt; n_choices; ++i)
4662                 my_items[i] = new_item(choices[i], choices[i]);
4663
4664         /* Crate menu */
4665         my_menu = new_menu((ITEM **)my_items);
4666
4667         /* Create the window to be associated with the menu */
4668         my_menu_win = newwin(10, 40, 4, 4);
4669         keypad(my_menu_win, TRUE);
4670      
4671         /* Set main window and sub window */
4672         set_menu_win(my_menu, my_menu_win);
4673         set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4674         set_menu_format(my_menu, 5, 1);
4675                         
4676         /* Set menu mark to the string " * " */
4677         set_menu_mark(my_menu, " * ");
4678
4679         /* Print a border around the main window and print a title */
4680         box(my_menu_win, 0, 0);
4681         print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4682         mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4683         mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4684         mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4685         
4686         /* Post the menu */
4687         post_menu(my_menu);
4688         wrefresh(my_menu_win);
4689         
4690         attron(COLOR_PAIR(2));
4691         mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scroll down or up a page of items");
4692         mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)");
4693         attroff(COLOR_PAIR(2));
4694         refresh();
4695
4696         while((c = wgetch(my_menu_win)) != KEY_F(1))
4697         {       switch(c)
4698                 {       case KEY_DOWN:
4699                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4700                                 break;
4701                         case KEY_UP:
4702                                 menu_driver(my_menu, REQ_UP_ITEM);
4703                                 break;
4704                         case KEY_NPAGE:
4705                                 menu_driver(my_menu, REQ_SCR_DPAGE);
4706                                 break;
4707                         case KEY_PPAGE:
4708                                 menu_driver(my_menu, REQ_SCR_UPAGE);
4709                                 break;
4710                 }
4711                 wrefresh(my_menu_win);
4712         }       
4713
4714         /* Unpost and free all the memory taken up */
4715         unpost_menu(my_menu);
4716         free_menu(my_menu);
4717         for(i = 0; i &lt; n_choices; ++i)
4718                 free_item(my_items[i]);
4719         endwin();
4720 }
4721
4722 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4723 {       int length, x, y;
4724         float temp;
4725
4726         if(win == NULL)
4727                 win = stdscr;
4728         getyx(win, y, x);
4729         if(startx != 0)
4730                 x = startx;
4731         if(starty != 0)
4732                 y = starty;
4733         if(width == 0)
4734                 width = 80;
4735
4736         length = strlen(string);
4737         temp = (width - length)/ 2;
4738         x = startx + (int)temp;
4739         wattron(win, color);
4740         mvwprintw(win, y, x, "%s", string);
4741         wattroff(win, color);
4742         refresh();
4743 }</span></pre>
4744         </div>
4745
4746         <p>This program is self-explanatory. In this example the
4747         number of choices has been increased to ten, which is
4748         larger than our sub window size which can hold 6 items.
4749         This message has to be explicitly conveyed to the menu
4750         system with the function set_menu_format(). In here we
4751         specify the number of rows and columns we want to be
4752         displayed for a single page. We can specify any number of
4753         items to be shown, in the rows variables, if it is less
4754         than the height of the sub window. If the key pressed by
4755         the user is a PAGE UP or PAGE DOWN, the menu is scrolled a
4756         page due to the requests (REQ_SCR_DPAGE and REQ_SCR_UPAGE)
4757         given to menu_driver().</p>
4758       </div>
4759
4760       <div class="SECT2">
4761         <hr>
4762
4763         <h3 class="SECT2"><a name="MULTICOLUMN" id=
4764         "MULTICOLUMN">17.6. Multi Columnar Menus</a></h3>
4765
4766         <p>In the above example you have seen how to use the
4767         function set_menu_format(). I didn't mention what the cols
4768         variable (third parameter) does. Well, If your sub window
4769         is wide enough, you can opt to display more than one item
4770         per row. This can be specified in the cols variable. To
4771         make things simpler, the following example doesn't show
4772         descriptions for the items.</p>
4773
4774         <div class="EXAMPLE">
4775           <a name="MMEMUCO" id="MMEMUCO"></a>
4776           <p><b>Example 21. Milt Columnar Menus Example</b>
4777           </p>
4778
4779           <pre class="PROGRAMLISTING"><span class=
4780           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
4781 #include &lt;curses.h&gt;
4782 #include &lt;menu.h&gt;
4783
4784 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4785 #define CTRLD   4
4786
4787 char *choices[] = {
4788                         "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5",
4789                         "Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10",
4790                         "Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15",
4791                         "Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20",
4792                         "Exit",
4793                         (char *)NULL,
4794                   };
4795
4796 int main()
4797 {       ITEM **my_items;
4798         int c;                          
4799         MENU *my_menu;
4800         WINDOW *my_menu_win;
4801         int n_choices, i;
4802         
4803         /* Initialize curses */
4804         initscr();
4805         start_color();
4806         cbreak();
4807         noecho();
4808         keypad(stdscr, TRUE);
4809         init_pair(1, COLOR_RED, COLOR_BLACK);
4810         init_pair(2, COLOR_CYAN, COLOR_BLACK);
4811
4812         /* Create items */
4813         n_choices = ARRAY_SIZE(choices);
4814         my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4815         for(i = 0; i &lt; n_choices; ++i)
4816                 my_items[i] = new_item(choices[i], choices[i]);
4817
4818         /* Crate menu */
4819         my_menu = new_menu((ITEM **)my_items);
4820
4821         /* Set menu option not to show the description */
4822         menu_opts_off(my_menu, O_SHOWDESC);
4823
4824         /* Create the window to be associated with the menu */
4825         my_menu_win = newwin(10, 70, 4, 4);
4826         keypad(my_menu_win, TRUE);
4827      
4828         /* Set main window and sub window */
4829         set_menu_win(my_menu, my_menu_win);
4830         set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1));
4831         set_menu_format(my_menu, 5, 3);
4832         set_menu_mark(my_menu, " * ");
4833
4834         /* Print a border around the main window and print a title */
4835         box(my_menu_win, 0, 0);
4836         
4837         attron(COLOR_PAIR(2));
4838         mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll");
4839         mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)");
4840         attroff(COLOR_PAIR(2));
4841         refresh();
4842
4843         /* Post the menu */
4844         post_menu(my_menu);
4845         wrefresh(my_menu_win);
4846         
4847         while((c = wgetch(my_menu_win)) != KEY_F(1))
4848         {       switch(c)
4849                 {       case KEY_DOWN:
4850                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4851                                 break;
4852                         case KEY_UP:
4853                                 menu_driver(my_menu, REQ_UP_ITEM);
4854                                 break;
4855                         case KEY_LEFT:
4856                                 menu_driver(my_menu, REQ_LEFT_ITEM);
4857                                 break;
4858                         case KEY_RIGHT:
4859                                 menu_driver(my_menu, REQ_RIGHT_ITEM);
4860                                 break;
4861                         case KEY_NPAGE:
4862                                 menu_driver(my_menu, REQ_SCR_DPAGE);
4863                                 break;
4864                         case KEY_PPAGE:
4865                                 menu_driver(my_menu, REQ_SCR_UPAGE);
4866                                 break;
4867                 }
4868                 wrefresh(my_menu_win);
4869         }       
4870
4871         /* Unpost and free all the memory taken up */
4872         unpost_menu(my_menu);
4873         free_menu(my_menu);
4874         for(i = 0; i &lt; n_choices; ++i)
4875                 free_item(my_items[i]);
4876         endwin();
4877 }</span></pre>
4878         </div>
4879
4880         <p>Watch the function call to set_menu_format(). It
4881         specifies the number of columns to be 3, thus displaying 3
4882         items per row. We have also switched off the showing
4883         descriptions with the function menu_opts_off(). There are
4884         couple of functions set_menu_opts(), menu_opts_on() and
4885         menu_opts() which can be used to manipulate menu options.
4886         The following menu options can be specified.</p>
4887
4888         <pre class="PROGRAMLISTING">       O_ONEVALUE
4889             Only one item can be selected for this menu.
4890
4891        O_SHOWDESC
4892             Display  the  item  descriptions  when  the  menu  is
4893             posted.
4894
4895        O_ROWMAJOR
4896             Display the menu in row-major order.
4897
4898        O_IGNORECASE
4899             Ignore the case when pattern-matching.
4900
4901        O_SHOWMATCH
4902             Move the cursor to within the item  name  while  pat&shy;
4903             tern-matching.
4904
4905        O_NONCYCLIC
4906             Don't   wrap   around  next-item  and  previous-item,
4907             requests to the other end of the menu.</pre>
4908         <p>All options are on by default. You can switch specific
4909         attributes on or off with menu_opts_on() and
4910         menu_opts_off() functions. You can also use set_menu_opts()
4911         to directly specify the options. The argument to this
4912         function should be a OR ed value of some of those above
4913         constants. The function menu_opts() can be used to find out
4914         a menu's present options.</p>
4915       </div>
4916
4917       <div class="SECT2">
4918         <hr>
4919
4920         <h3 class="SECT2"><a name="MULTIVALUEMENUS" id=
4921         "MULTIVALUEMENUS">17.7. Multi Valued Menus</a></h3>
4922
4923         <p>You might be wondering what if you switch off the option
4924         O_ONEVALUE. Then the menu becomes multi-valued. That means
4925         you can select more than one item. This brings us to the
4926         request REQ_TOGGLE_ITEM. Let's see it in action.</p>
4927
4928         <div class="EXAMPLE">
4929           <a name="MMETO" id="MMETO"></a>
4930           <p><b>Example 22. Multi Valued Menus example</b>
4931           </p>
4932
4933           <pre class="PROGRAMLISTING"><span class=
4934           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
4935 #include &lt;string.h&gt;
4936 #include &lt;curses.h&gt;
4937 #include &lt;menu.h&gt;
4938
4939 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4940 #define CTRLD   4
4941
4942 char *choices[] = {
4943                         "Choice 1",
4944                         "Choice 2",
4945                         "Choice 3",
4946                         "Choice 4",
4947                         "Choice 5",
4948                         "Choice 6",
4949                         "Choice 7",
4950                         "Exit",
4951                   };
4952
4953 int main()
4954 {       ITEM **my_items;
4955         int c;                          
4956         MENU *my_menu;
4957         int n_choices, i;
4958         ITEM *cur_item;
4959         
4960         /* Initialize curses */ 
4961         initscr();
4962         cbreak();
4963         noecho();
4964         keypad(stdscr, TRUE);
4965
4966         /* Initialize items */
4967         n_choices = ARRAY_SIZE(choices);
4968         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
4969         for(i = 0; i &lt; n_choices; ++i)
4970                 my_items[i] = new_item(choices[i], choices[i]);
4971         my_items[n_choices] = (ITEM *)NULL;
4972
4973         my_menu = new_menu((ITEM **)my_items);
4974
4975         /* Make the menu multi valued */
4976         menu_opts_off(my_menu, O_ONEVALUE);
4977
4978         mvprintw(LINES - 3, 0, "Use &lt;SPACE&gt; to select or unselect an item.");
4979         mvprintw(LINES - 2, 0, "&lt;ENTER&gt; to see presently selected items(F1 to Exit)");
4980         post_menu(my_menu);
4981         refresh();
4982
4983         while((c = getch()) != KEY_F(1))
4984         {       switch(c)
4985                 {       case KEY_DOWN:
4986                                 menu_driver(my_menu, REQ_DOWN_ITEM);
4987                                 break;
4988                         case KEY_UP:
4989                                 menu_driver(my_menu, REQ_UP_ITEM);
4990                                 break;
4991                         case ' ':
4992                                 menu_driver(my_menu, REQ_TOGGLE_ITEM);
4993                                 break;
4994                         case 10:        /* Enter */
4995                         {       char temp[200];
4996                                 ITEM **items;
4997
4998                                 items = menu_items(my_menu);
4999                                 temp[0] = '\0';
5000                                 for(i = 0; i &lt; item_count(my_menu); ++i)
5001                                         if(item_value(items[i]) == TRUE)
5002                                         {       strcat(temp, item_name(items[i]));
5003                                                 strcat(temp, " ");
5004                                         }
5005                                 move(20, 0);
5006                                 clrtoeol();
5007                                 mvprintw(20, 0, temp);
5008                                 refresh();
5009                         }
5010                         break;
5011                 }
5012         }       
5013
5014         free_item(my_items[0]);
5015         free_item(my_items[1]);
5016         free_menu(my_menu);
5017         endwin();
5018 }
5019         </span></pre>
5020         </div>
5021
5022         <p>Whew, A lot of new functions. Let's take them one after
5023         another. Firstly, the REQ_TOGGLE_ITEM. In a multi-valued
5024         menu, the user should be allowed to select or un select
5025         more than one item. The request REQ_TOGGLE_ITEM toggles the
5026         present selection. In this case when space is pressed
5027         REQ_TOGGLE_ITEM request is sent to menu_driver to achieve
5028         the result.</p>
5029
5030         <p>Now when the user presses &lt;ENTER&gt; we show the
5031         items he presently selected. First we find out the items
5032         associated with the menu using the function menu_items().
5033         Then we loop through the items to find out if the item is
5034         selected or not. The function item_value() returns TRUE if
5035         an item is selected. The function item_count() returns the
5036         number of items in the menu. The item name can be found
5037         with item_name(). You can also find the description
5038         associated with an item using item_description().</p>
5039       </div>
5040
5041       <div class="SECT2">
5042         <hr>
5043
5044         <h3 class="SECT2"><a name="MENUOPT" id="MENUOPT">17.8. Menu
5045         Options</a></h3>
5046
5047         <p>Well, by this time you must be itching for some
5048         difference in your menu, with lots of functionality. I
5049         know. You want Colors !!!. You want to create nice menus
5050         similar to those text mode <a href=
5051         "http://www.jersey.net/~debinjoe/games/" target="_top">dos
5052         games</a>. The functions set_menu_fore() and
5053         set_menu_back() can be used to change the attribute of the
5054         selected item and unselected item. The names are
5055         misleading. They don't change menu's foreground or
5056         background which would have been useless.</p>
5057
5058         <p>The function set_menu_grey() can be used to set the
5059         display attribute for the non-selectable items in the menu.
5060         This brings us to the interesting option for an item the
5061         one and only O_SELECTABLE. We can turn it off by the
5062         function item_opts_off() and after that that item is not
5063         selectable. It is like a grayed item in those fancy windows
5064         menus. Let's put these concepts in practice with this
5065         example</p>
5066
5067         <div class="EXAMPLE">
5068           <a name="MMEAT" id="MMEAT"></a>
5069           <p><b>Example 23. Menu Options example</b>
5070           </p>
5071
5072           <pre class="PROGRAMLISTING"><span class=
5073           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
5074 #include &lt;menu.h&gt;
5075
5076 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5077 #define CTRLD   4
5078
5079 char *choices[] = {
5080                         "Choice 1",
5081                         "Choice 2",
5082                         "Choice 3",
5083                         "Choice 4",
5084                         "Choice 5",
5085                         "Choice 6",
5086                         "Choice 7",
5087                         "Exit",
5088                   };
5089
5090 int main()
5091 {       ITEM **my_items;
5092         int c;                          
5093         MENU *my_menu;
5094         int n_choices, i;
5095         ITEM *cur_item;
5096         
5097         /* Initialize curses */ 
5098         initscr();
5099         start_color();
5100         cbreak();
5101         noecho();
5102         keypad(stdscr, TRUE);
5103         init_pair(1, COLOR_RED, COLOR_BLACK);
5104         init_pair(2, COLOR_GREEN, COLOR_BLACK);
5105         init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5106
5107         /* Initialize items */
5108         n_choices = ARRAY_SIZE(choices);
5109         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5110         for(i = 0; i &lt; n_choices; ++i)
5111                 my_items[i] = new_item(choices[i], choices[i]);
5112         my_items[n_choices] = (ITEM *)NULL;
5113         item_opts_off(my_items[3], O_SELECTABLE);
5114         item_opts_off(my_items[6], O_SELECTABLE);
5115
5116         /* Create menu */
5117         my_menu = new_menu((ITEM **)my_items);
5118
5119         /* Set fore ground and back ground of the menu */
5120         set_menu_fore(my_menu, COLOR_PAIR(1) | A_REVERSE);
5121         set_menu_back(my_menu, COLOR_PAIR(2));
5122         set_menu_grey(my_menu, COLOR_PAIR(3));
5123
5124         /* Post the menu */
5125         mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5126         mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5127         post_menu(my_menu);
5128         refresh();
5129
5130         while((c = getch()) != KEY_F(1))
5131         {       switch(c)
5132                 {       case KEY_DOWN:
5133                                 menu_driver(my_menu, REQ_DOWN_ITEM);
5134                                 break;
5135                         case KEY_UP:
5136                                 menu_driver(my_menu, REQ_UP_ITEM);
5137                                 break;
5138                         case 10: /* Enter */
5139                                 move(20, 0);
5140                                 clrtoeol();
5141                                 mvprintw(20, 0, "Item selected is : %s", 
5142                                                 item_name(current_item(my_menu)));
5143                                 pos_menu_cursor(my_menu);
5144                                 break;
5145                 }
5146         }       
5147         unpost_menu(my_menu);
5148         for(i = 0; i &lt; n_choices; ++i)
5149                 free_item(my_items[i]);
5150         free_menu(my_menu);
5151         endwin();
5152 }
5153         </span></pre>
5154         </div>
5155       </div>
5156
5157       <div class="SECT2">
5158         <hr>
5159
5160         <h3 class="SECT2"><a name="MENUUSERPTR" id=
5161         "MENUUSERPTR">17.9. The useful User Pointer</a></h3>
5162
5163         <p>We can associate a user pointer with each item in the
5164         menu. It works the same way as user pointer in panels. It
5165         is not touched by menu system. You can store any thing you
5166         like in that. I usually use it to store the function to be
5167         executed when the menu option is chosen (It is selected and
5168         may be the user pressed &lt;ENTER&gt;);</p>
5169
5170         <div class="EXAMPLE">
5171           <a name="MMEUS" id="MMEUS"></a>
5172           <p><b>Example 24. Menu User Pointer Usage</b>
5173           </p>
5174
5175           <pre class="PROGRAMLISTING"><span class=
5176           "INLINEMEDIAOBJECT">#include &lt;stdlib.h&gt;
5177 #include &lt;curses.h&gt;
5178 #include &lt;menu.h&gt;
5179
5180 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5181 #define CTRLD   4
5182
5183 char *choices[] = {
5184                         "Choice 1",
5185                         "Choice 2",
5186                         "Choice 3",
5187                         "Choice 4",
5188                         "Choice 5",
5189                         "Choice 6",
5190                         "Choice 7",
5191                         "Exit",
5192                   };
5193 void func(char *name);
5194
5195 int main()
5196 {       ITEM **my_items;
5197         int c;                          
5198         MENU *my_menu;
5199         int n_choices, i;
5200         ITEM *cur_item;
5201         
5202         /* Initialize curses */ 
5203         initscr();
5204         start_color();
5205         cbreak();
5206         noecho();
5207         keypad(stdscr, TRUE);
5208         init_pair(1, COLOR_RED, COLOR_BLACK);
5209         init_pair(2, COLOR_GREEN, COLOR_BLACK);
5210         init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5211
5212         /* Initialize items */
5213         n_choices = ARRAY_SIZE(choices);
5214         my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5215         for(i = 0; i &lt; n_choices; ++i)
5216         {       my_items[i] = new_item(choices[i], choices[i]);
5217                 /* Set the user pointer */
5218                 set_item_userptr(my_items[i], func);
5219         }
5220         my_items[n_choices] = (ITEM *)NULL;
5221
5222         /* Create menu */
5223         my_menu = new_menu((ITEM **)my_items);
5224
5225         /* Post the menu */
5226         mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5227         mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5228         post_menu(my_menu);
5229         refresh();
5230
5231         while((c = getch()) != KEY_F(1))
5232         {       switch(c)
5233                 {       case KEY_DOWN:
5234                                 menu_driver(my_menu, REQ_DOWN_ITEM);
5235                                 break;
5236                         case KEY_UP:
5237                                 menu_driver(my_menu, REQ_UP_ITEM);
5238                                 break;
5239                         case 10: /* Enter */
5240                         {       ITEM *cur;
5241                                 void (*p)(char *);
5242
5243                                 cur = current_item(my_menu);
5244                                 p = item_userptr(cur);
5245                                 p((char *)item_name(cur));
5246                                 pos_menu_cursor(my_menu);
5247                                 break;
5248                         }
5249                         break;
5250                 }
5251         }       
5252         unpost_menu(my_menu);
5253         for(i = 0; i &lt; n_choices; ++i)
5254                 free_item(my_items[i]);
5255         free_menu(my_menu);
5256         endwin();
5257 }
5258
5259 void func(char *name)
5260 {       move(20, 0);
5261         clrtoeol();
5262         mvprintw(20, 0, "Item selected is : %s", name);
5263 }       </span></pre>
5264         </div>
5265       </div>
5266     </div>
5267
5268     <div class="SECT1">
5269       <hr>
5270
5271       <h2 class="SECT1"><a name="FORMS" id="FORMS">18. Forms
5272       Library</a></h2>
5273
5274       <p>Well. If you have seen those forms on web pages which take
5275       input from users and do various kinds of things, you might be
5276       wondering how would any one create such forms in text mode
5277       display. It is quite difficult to write those nifty forms in
5278       plain ncurses. Forms library tries to provide a basic frame
5279       work to build and maintain forms with ease. It has lot of
5280       features(functions) which manage validation, dynamic
5281       expansion of fields, etc. Let's see it in full flow.</p>
5282
5283       <p>A form is a collection of fields; each field can be either
5284       a label(static text) or a data-entry location. The forms also
5285       library provides functions to divide forms into multiple
5286       pages.</p>
5287
5288       <div class="SECT2">
5289         <hr>
5290
5291         <h3 class="SECT2"><a name="FORMBASICS" id=
5292         "FORMBASICS">18.1. The Basics</a></h3>
5293
5294         <p>Forms are created in much the same way as menus. First
5295         the fields related to the form are created with
5296         new_field(). You can set options for the fields, so that
5297         they can be displayed with some fancy attributes, validated
5298         before the field looses focus, etc. Then the fields are
5299         attached to form. After this, the form can be posted to
5300         display and is ready to receive inputs. On the similar
5301         lines to menu_driver(), the form is manipulated with
5302         form_driver(). We can send requests to form_driver to move
5303         focus to a certain field, move cursor to end of the field
5304         etc. After the user enters values in the fields and
5305         validation done, form can be unposted and memory allocated
5306         can be freed.</p>
5307
5308         <p>The general flow of control of a forms program looks
5309         like this.</p>
5310
5311         <ol type="1">
5312           <li>
5313             <p>Initialize curses</p>
5314           </li>
5315
5316           <li>
5317             <p>Create fields using new_field(). You can specify the
5318             height and width of the field, and its position on the
5319             form.</p>
5320           </li>
5321
5322           <li>
5323             <p>Create the forms with new_form() by specifying the
5324             fields to be attached with.</p>
5325           </li>
5326
5327           <li>
5328             <p>Post the form with form_post() and refresh the
5329             screen.</p>
5330           </li>
5331
5332           <li>
5333             <p>Process the user requests with a loop and do
5334             necessary updates to form with form_driver.</p>
5335           </li>
5336
5337           <li>
5338             <p>Unpost the menu with form_unpost()</p>
5339           </li>
5340
5341           <li>
5342             <p>Free the memory allocated to menu by free_form()</p>
5343           </li>
5344
5345           <li>
5346             <p>Free the memory allocated to the items with
5347             free_field()</p>
5348           </li>
5349
5350           <li>
5351             <p>End curses</p>
5352           </li>
5353         </ol>
5354
5355         <p>As you can see, working with forms library is much
5356         similar to handling menu library. The following examples
5357         will explore various aspects of form processing. Let's
5358         start the journey with a simple example. first.</p>
5359       </div>
5360
5361       <div class="SECT2">
5362         <hr>
5363
5364         <h3 class="SECT2"><a name="COMPILEFORMS" id=
5365         "COMPILEFORMS">18.2. Compiling With the Forms Library</a></h3>
5366
5367         <p>To use forms library functions, you have to include
5368         form.h and to link the program with forms library the flag
5369         -lform should be added along with -lncurses in that
5370         order.</p>
5371
5372         <pre class="PROGRAMLISTING">    #include &lt;form.h&gt;
5373     .
5374     .
5375     .
5376
5377     compile and link: gcc &lt;program file&gt; -lform -lncurses</pre>
5378         <div class="EXAMPLE">
5379           <a name="FFOSI" id="FFOSI"></a>
5380           <p><b>Example 25. Forms Basics</b>
5381           </p>
5382
5383           <pre class="PROGRAMLISTING"><span class=
5384           "INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5385
5386 int main()
5387 {       FIELD *field[3];
5388         FORM  *my_form;
5389         int ch;
5390         
5391         /* Initialize curses */
5392         initscr();
5393         cbreak();
5394         noecho();
5395         keypad(stdscr, TRUE);
5396
5397         /* Initialize the fields */
5398         field[0] = new_field(1, 10, 4, 18, 0, 0);
5399         field[1] = new_field(1, 10, 6, 18, 0, 0);
5400         field[2] = NULL;
5401
5402         /* Set field options */
5403         set_field_back(field[0], A_UNDERLINE);  /* Print a line for the option  */
5404         field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5405                                                 /* Field is filled up           */
5406         set_field_back(field[1], A_UNDERLINE); 
5407         field_opts_off(field[1], O_AUTOSKIP);
5408
5409         /* Create the form and post it */
5410         my_form = new_form(field);
5411         post_form(my_form);
5412         refresh();
5413         
5414         mvprintw(4, 10, "Value 1:");
5415         mvprintw(6, 10, "Value 2:");
5416         refresh();
5417
5418         /* Loop through to get user requests */
5419         while((ch = getch()) != KEY_F(1))
5420         {       switch(ch)
5421                 {       case KEY_DOWN:
5422                                 /* Go to next field */
5423                                 form_driver(my_form, REQ_NEXT_FIELD);
5424                                 /* Go to the end of the present buffer */
5425                                 /* Leaves nicely at the last character */
5426                                 form_driver(my_form, REQ_END_LINE);
5427                                 break;
5428                         case KEY_UP:
5429                                 /* Go to previous field */
5430                                 form_driver(my_form, REQ_PREV_FIELD);
5431                                 form_driver(my_form, REQ_END_LINE);
5432                                 break;
5433                         default:
5434                                 /* If this is a normal character, it gets */
5435                                 /* Printed                                */    
5436                                 form_driver(my_form, ch);
5437                                 break;
5438                 }
5439         }
5440
5441         /* Un post form and free the memory */
5442         unpost_form(my_form);
5443         free_form(my_form);
5444         free_field(field[0]);
5445         free_field(field[1]); 
5446
5447         endwin();
5448         return 0;
5449 }</span></pre>
5450         </div>
5451
5452         <p>Above example is pretty straight forward. It creates two
5453         fields with <tt class="LITERAL">new_field()</tt>.
5454         new_field() takes height, width, starty, startx, number of
5455         offscreen rows and number of additional working buffers.
5456         The fifth argument number of offscreen rows specifies how
5457         much of the field to be shown. If it is zero, the entire
5458         field is always displayed otherwise the form will be
5459         scrollable when the user accesses not displayed parts of
5460         the field. The forms library allocates one buffer per field
5461         to store the data user enters. Using the last parameter to
5462         new_field() we can specify it to allocate some additional
5463         buffers. These can be used for any purpose you like.</p>
5464
5465         <p>After creating the fields, back ground attribute of both
5466         of them is set to an underscore with set_field_back(). The
5467         AUTOSKIP option is turned off using field_opts_off(). If
5468         this option is turned on, focus will move to the next field
5469         in the form once the active field is filled up
5470         completely.</p>
5471
5472         <p>After attaching the fields to the form, it is posted.
5473         Here on, user inputs are processed in the while loop, by
5474         making corresponding requests to form_driver. The details
5475         of all the requests to the form_driver() are explained
5476         later.</p>
5477       </div>
5478
5479       <div class="SECT2">
5480         <hr>
5481
5482         <h3 class="SECT2"><a name="PLAYFIELDS" id=
5483         "PLAYFIELDS">18.3. Playing with Fields</a></h3>
5484
5485         <p>Each form field is associated with a lot of attributes.
5486         They can be manipulated to get the required effect and to
5487         have fun !!!. So why wait?</p>
5488
5489         <div class="SECT3">
5490           <hr>
5491
5492           <h4 class="SECT3"><a name="FETCHINFO" id=
5493           "FETCHINFO">18.3.1. Fetching Size and Location of
5494           Field</a></h4>
5495
5496           <p>The parameters we have given at the time of creation
5497           of a field can be retrieved with field_info(). It returns
5498           height, width, starty, startx, number of offscreen rows,
5499           and number of additional buffers into the parameters
5500           given to it. It is a sort of inverse of new_field().</p>
5501
5502           <pre class=
5503           "PROGRAMLISTING">int field_info(     FIELD *field,              /* field from which to fetch */
5504                     int *height, *int width,   /* field size */ 
5505                     int *top, int *left,       /* upper left corner */
5506                     int *offscreen,            /* number of offscreen rows */
5507                     int *nbuf);                /* number of working buffers */</pre>
5508         </div>
5509
5510         <div class="SECT3">
5511           <hr>
5512
5513           <h4 class="SECT3"><a name="MOVEFIELD" id=
5514           "MOVEFIELD">18.3.2. Moving the field</a></h4>
5515
5516           <p>The location of the field can be moved to a different
5517           position with move_field().</p>
5518
5519           <pre class=
5520           "PROGRAMLISTING">int move_field(    FIELD *field,              /* field to alter */
5521                    int top, int left);        /* new upper-left corner */</pre>
5522           <p>As usual, the changed position can be queried with
5523           field_infor().</p>
5524         </div>
5525
5526         <div class="SECT3">
5527           <hr>
5528
5529           <h4 class="SECT3"><a name="JUSTIFYFIELD" id=
5530           "JUSTIFYFIELD">18.3.3. Field Justification</a></h4>
5531
5532           <p>The justification to be done for the field can be
5533           fixed using the function set_field_just().</p>
5534
5535           <pre class=
5536           "PROGRAMLISTING">    int set_field_just(FIELD *field,          /* field to alter */
5537                int justmode);         /* mode to set */
5538     int field_just(FIELD *field);          /* fetch justify mode of field */</pre>
5539           <p>The justification mode valued accepted and returned by
5540           these functions are NO_JUSTIFICATION, JUSTIFY_RIGHT,
5541           JUSTIFY_LEFT, or JUSTIFY_CENTER.</p>
5542         </div>
5543
5544         <div class="SECT3">
5545           <hr>
5546
5547           <h4 class="SECT3"><a name="FIELDDISPATTRIB" id=
5548           "FIELDDISPATTRIB">18.3.4. Field Display Attributes</a></h4>
5549
5550           <p>As you have seen, in the above example, display
5551           attribute for the fields can be set with set_field_fore()
5552           and setfield_back(). These functions set foreground and
5553           background attribute of the fields. You can also specify
5554           a pad character which will be filled in the unfilled
5555           portion of the field. The pad character is set with a
5556           call to set_field_pad(). Default pad value is a space.
5557           The functions field_fore(), field_back, field_pad() can
5558           be used to query the present foreground, background
5559           attributes and pad character for the field. The following
5560           list gives the usage of functions.</p>
5561
5562           <pre class=
5563           "PROGRAMLISTING">&#13;int set_field_fore(FIELD *field,        /* field to alter */
5564                    chtype attr);        /* attribute to set */ 
5565
5566 chtype field_fore(FIELD *field);        /* field to query */
5567                                         /* returns foreground attribute */
5568
5569 int set_field_back(FIELD *field,        /* field to alter */
5570                    chtype attr);        /* attribute to set */ 
5571
5572 chtype field_back(FIELD *field);        /* field to query */
5573                                         /* returns background attribute */
5574
5575 int set_field_pad(FIELD *field,         /* field to alter */
5576                   int pad);             /* pad character to set */ 
5577
5578 chtype field_pad(FIELD *field);         /* field to query */  
5579                                         /* returns present pad character */&#13;</pre>
5580           <p>Though above functions seem quite simple, using colors
5581           with set_field_fore() may be frustrating in the
5582           beginning. Let me first explain about foreground and
5583           background attributes of a field. The foreground
5584           attribute is associated with the character. That means a
5585           character in the field is printed with the attribute you
5586           have set with set_field_fore(). Background attribute is
5587           the attribute used to fill background of field, whether
5588           any character is there or not. So what about colors?
5589           Since colors are always defined in pairs, what is the
5590           right way to display colored fields? Here's an example
5591           clarifying color attributes.</p>
5592
5593           <div class="EXAMPLE">
5594             <a name="FFOAT" id="FFOAT"></a>
5595             <p><b>Example 26. Form Attributes example</b>
5596             </p>
5597
5598             <pre class="PROGRAMLISTING"><span class=
5599             "INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5600
5601 int main()
5602 {       FIELD *field[3];
5603         FORM  *my_form;
5604         int ch;
5605         
5606         /* Initialize curses */
5607         initscr();
5608         start_color();
5609         cbreak();
5610         noecho();
5611         keypad(stdscr, TRUE);
5612
5613         /* Initialize few color pairs */
5614         init_pair(1, COLOR_WHITE, COLOR_BLUE);
5615         init_pair(2, COLOR_WHITE, COLOR_BLUE);
5616
5617         /* Initialize the fields */
5618         field[0] = new_field(1, 10, 4, 18, 0, 0);
5619         field[1] = new_field(1, 10, 6, 18, 0, 0);
5620         field[2] = NULL;
5621
5622         /* Set field options */
5623         set_field_fore(field[0], COLOR_PAIR(1));/* Put the field with blue background */
5624         set_field_back(field[0], COLOR_PAIR(2));/* and white foreground (characters */
5625                                                 /* are printed in white         */
5626         field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5627                                                 /* Field is filled up           */
5628         set_field_back(field[1], A_UNDERLINE); 
5629         field_opts_off(field[1], O_AUTOSKIP);
5630
5631         /* Create the form and post it */
5632         my_form = new_form(field);
5633         post_form(my_form);
5634         refresh();
5635         
5636         set_current_field(my_form, field[0]); /* Set focus to the colored field */
5637         mvprintw(4, 10, "Value 1:");
5638         mvprintw(6, 10, "Value 2:");
5639         mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
5640         refresh();
5641
5642         /* Loop through to get user requests */
5643         while((ch = getch()) != KEY_F(1))
5644         {       switch(ch)
5645                 {       case KEY_DOWN:
5646                                 /* Go to next field */
5647                                 form_driver(my_form, REQ_NEXT_FIELD);
5648                                 /* Go to the end of the present buffer */
5649                                 /* Leaves nicely at the last character */
5650                                 form_driver(my_form, REQ_END_LINE);
5651                                 break;
5652                         case KEY_UP:
5653                                 /* Go to previous field */
5654                                 form_driver(my_form, REQ_PREV_FIELD);
5655                                 form_driver(my_form, REQ_END_LINE);
5656                                 break;
5657                         default:
5658                                 /* If this is a normal character, it gets */
5659                                 /* Printed                                */    
5660                                 form_driver(my_form, ch);
5661                                 break;
5662                 }
5663         }
5664
5665         /* Un post form and free the memory */
5666         unpost_form(my_form);
5667         free_form(my_form);
5668         free_field(field[0]);
5669         free_field(field[1]); 
5670
5671         endwin();
5672         return 0;
5673 }</span></pre>
5674           </div>
5675
5676           <p>Play with the color pairs and try to understand the
5677           foreground and background attributes. In my programs
5678           using color attributes, I usually set only the background
5679           with set_field_back(). Curses simply doesn't allow
5680           defining individual color attributes.</p>
5681         </div>
5682
5683         <div class="SECT3">
5684           <hr>
5685
5686           <h4 class="SECT3"><a name="FIELDOPTIONBITS" id=
5687           "FIELDOPTIONBITS">18.3.5. Field Option Bits</a></h4>
5688
5689           <p>There is also a large collection of field option bits
5690           you can set to control various aspects of forms
5691           processing. You can manipulate them with these
5692           functions:</p>
5693
5694           <pre class=
5695           "PROGRAMLISTING">int set_field_opts(FIELD *field,          /* field to alter */
5696                    int attr);             /* attribute to set */ 
5697
5698 int field_opts_on(FIELD *field,           /* field to alter */
5699                   int attr);              /* attributes to turn on */ 
5700
5701 int field_opts_off(FIELD *field,          /* field to alter */
5702                   int attr);              /* attributes to turn off */ 
5703
5704 int field_opts(FIELD *field);             /* field to query */ </pre>
5705           <p>The function set_field_opts() can be used to directly
5706           set attributes of a field or you can choose to switch a
5707           few attributes on and off with field_opts_on() and
5708           field_opts_off() selectively. Anytime you can query the
5709           attributes of a field with field_opts(). The following is
5710           the list of available options. By default, all options
5711           are on.</p>
5712
5713           <div class="VARIABLELIST">
5714             <dl>
5715               <dt>O_VISIBLE</dt>
5716
5717               <dd>
5718                 <p>Controls whether the field is visible on the
5719                 screen. Can be used during form processing to hide
5720                 or pop up fields depending on the value of parent
5721                 fields.</p>
5722               </dd>
5723
5724               <dt>O_ACTIVE</dt>
5725
5726               <dd>
5727                 <p>Controls whether the field is active during
5728                 forms processing (i.e. visited by form navigation
5729                 keys). Can be used to make labels or derived fields
5730                 with buffer values alterable by the forms
5731                 application, not the user.</p>
5732               </dd>
5733
5734               <dt>O_PUBLIC</dt>
5735
5736               <dd>
5737                 <p>Controls whether data is displayed during field
5738                 entry. If this option is turned off on a field, the
5739                 library will accept and edit data in that field,
5740                 but it will not be displayed and the visible field
5741                 cursor will not move. You can turn off the O_PUBLIC
5742                 bit to define password fields.</p>
5743               </dd>
5744
5745               <dt>O_EDIT</dt>
5746
5747               <dd>
5748                 <p>Controls whether the field's data can be
5749                 modified. When this option is off, all editing
5750                 requests except <tt class=
5751                 "LITERAL">REQ_PREV_CHOICE</tt> and <tt class=
5752                 "LITERAL">REQ_NEXT_CHOICE</tt>will fail. Such
5753                 read-only fields may be useful for help
5754                 messages.</p>
5755               </dd>
5756
5757               <dt>O_WRAP</dt>
5758
5759               <dd>
5760                 <p>Controls word-wrapping in multi-line fields.
5761                 Normally, when any character of a (blank-separated)
5762                 word reaches the end of the current line, the
5763                 entire word is wrapped to the next line (assuming
5764                 there is one). When this option is off, the word
5765                 will be split across the line break.</p>
5766               </dd>
5767
5768               <dt>O_BLANK</dt>
5769
5770               <dd>
5771                 <p>Controls field blanking. When this option is on,
5772                 entering a character at the first field position
5773                 erases the entire field (except for the
5774                 just-entered character).</p>
5775               </dd>
5776
5777               <dt>O_AUTOSKIP</dt>
5778
5779               <dd>
5780                 <p>Controls automatic skip to next field when this
5781                 one fills. Normally, when the forms user tries to
5782                 type more data into a field than will fit, the
5783                 editing location jumps to next field. When this
5784                 option is off, the user's cursor will hang at the
5785                 end of the field. This option is ignored in dynamic
5786                 fields that have not reached their size limit.</p>
5787               </dd>
5788
5789               <dt>O_NULLOK</dt>
5790
5791               <dd>
5792                 <p>Controls whether validation is applied to blank
5793                 fields. Normally, it is not; the user can leave a
5794                 field blank without invoking the usual validation
5795                 check on exit. If this option is off on a field,
5796                 exit from it will invoke a validation check.</p>
5797               </dd>
5798
5799               <dt>O_PASSOK</dt>
5800
5801               <dd>
5802                 <p>Controls whether validation occurs on every
5803                 exit, or only after the field is modified. Normally
5804                 the latter is true. Setting O_PASSOK may be useful
5805                 if your field's validation function may change
5806                 during forms processing.</p>
5807               </dd>
5808
5809               <dt>O_STATIC</dt>
5810
5811               <dd>
5812                 <p>Controls whether the field is fixed to its
5813                 initial dimensions. If you turn this off, the field
5814                 becomes dynamic and will stretch to fit entered
5815                 data.</p>
5816               </dd>
5817             </dl>
5818           </div>
5819
5820           <p>A field's options cannot be changed while the field is
5821           currently selected. However, options may be changed on
5822           posted fields that are not current.</p>
5823
5824           <p>The option values are bit-masks and can be composed
5825           with logical-or in the obvious way. You have seen the
5826           usage of switching off O_AUTOSKIP option. The following
5827           example clarifies usage of some more options. Other
5828           options are explained where appropriate.</p>
5829
5830           <div class="EXAMPLE">
5831             <a name="FFOOP" id="FFOOP"></a>
5832             <p><b>Example 27. Field Options Usage example</b>
5833             </p>
5834
5835             <pre class="PROGRAMLISTING"><span class=
5836             "INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5837
5838 #define STARTX 15
5839 #define STARTY 4
5840 #define WIDTH 25
5841
5842 #define N_FIELDS 3
5843
5844 int main()
5845 {       FIELD *field[N_FIELDS];
5846         FORM  *my_form;
5847         int ch, i;
5848         
5849         /* Initialize curses */
5850         initscr();
5851         cbreak();
5852         noecho();
5853         keypad(stdscr, TRUE);
5854
5855         /* Initialize the fields */
5856         for(i = 0; i &lt; N_FIELDS - 1; ++i)
5857                 field[i] = new_field(1, WIDTH, STARTY + i * 2, STARTX, 0, 0);
5858         field[N_FIELDS - 1] = NULL;
5859
5860         /* Set field options */
5861         set_field_back(field[1], A_UNDERLINE);  /* Print a line for the option  */
5862         
5863         field_opts_off(field[0], O_ACTIVE); /* This field is a static label */
5864         field_opts_off(field[1], O_PUBLIC); /* This filed is like a password field*/
5865         field_opts_off(field[1], O_AUTOSKIP); /* To avoid entering the same field */
5866                                               /* after last character is entered */
5867         
5868         /* Create the form and post it */
5869         my_form = new_form(field);
5870         post_form(my_form);
5871         refresh();
5872         
5873         set_field_just(field[0], JUSTIFY_CENTER); /* Center Justification */
5874         set_field_buffer(field[0], 0, "This is a static Field"); 
5875                                                   /* Initialize the field  */
5876         mvprintw(STARTY, STARTX - 10, "Field 1:");
5877         mvprintw(STARTY + 2, STARTX - 10, "Field 2:");
5878         refresh();
5879
5880         /* Loop through to get user requests */
5881         while((ch = getch()) != KEY_F(1))
5882         {       switch(ch)
5883                 {       case KEY_DOWN:
5884                                 /* Go to next field */
5885                                 form_driver(my_form, REQ_NEXT_FIELD);
5886                                 /* Go to the end of the present buffer */
5887                                 /* Leaves nicely at the last character */
5888                                 form_driver(my_form, REQ_END_LINE);
5889                                 break;
5890                         case KEY_UP:
5891                                 /* Go to previous field */
5892                                 form_driver(my_form, REQ_PREV_FIELD);
5893                                 form_driver(my_form, REQ_END_LINE);
5894                                 break;
5895                         default:
5896                                 /* If this is a normal character, it gets */
5897                                 /* Printed                                */    
5898                                 form_driver(my_form, ch);
5899                                 break;
5900                 }
5901         }
5902
5903         /* Un post form and free the memory */
5904         unpost_form(my_form);
5905         free_form(my_form);
5906         free_field(field[0]);
5907         free_field(field[1]); 
5908
5909         endwin();
5910         return 0;
5911 }</span></pre>
5912           </div>
5913
5914           <p>This example, though useless, shows the usage of
5915           options. If used properly, they can present information
5916           very effectively in a form. The second field being not
5917           O_PUBLIC, does not show the characters you are
5918           typing.</p>
5919         </div>
5920
5921         <div class="SECT3">
5922           <hr>
5923
5924           <h4 class="SECT3"><a name="FIELDSTATUS" id=
5925           "FIELDSTATUS">18.3.6. Field Status</a></h4>
5926
5927           <p>The field status specifies whether the field has got
5928           edited or not. It is initially set to FALSE and when user
5929           enters something and the data buffer gets modified it
5930           becomes TRUE. So a field's status can be queried to find
5931           out whether it has been modified or not. The following
5932           functions can assist in those operations.</p>
5933
5934           <pre class=
5935           "PROGRAMLISTING">int set_field_status(FIELD *field,      /* field to alter */
5936                    int status);         /* status to set */
5937
5938 int field_status(FIELD *field);         /* fetch status of field */</pre>
5939           <p>It is better to check the field's status only after
5940           after leaving the field, as data buffer might not have
5941           been updated yet as the validation is still due. To
5942           guarantee that right status is returned, call
5943           field_status() either (1) in the field's exit validation
5944           check routine, (2) from the field's or form's
5945           initialization or termination hooks, or (3) just after a
5946           REQ_VALIDATION request has been processed by the forms
5947           driver</p>
5948         </div>
5949
5950         <div class="SECT3">
5951           <hr>
5952
5953           <h4 class="SECT3"><a name="FIELDUSERPTR" id=
5954           "FIELDUSERPTR">18.3.7. Field User Pointer</a></h4>
5955
5956           <p>Every field structure contains one pointer that can be
5957           used by the user for various purposes. It is not touched
5958           by forms library and can be used for any purpose by the
5959           user. The following functions set and fetch user
5960           pointer.</p>
5961
5962           <pre class=
5963           "PROGRAMLISTING">int set_field_userptr(FIELD *field,   
5964            char *userptr);      /* the user pointer you wish to associate */
5965                                 /* with the field    */
5966
5967 char *field_userptr(FIELD *field);      /* fetch user pointer of the field */</pre>
5968         </div>
5969
5970         <div class="SECT3">
5971           <hr>
5972
5973           <h4 class="SECT3"><a name="VARIABLESIZEFIELDS" id=
5974           "VARIABLESIZEFIELDS">18.3.8. Variable-Sized Fields</a></h4>
5975
5976           <p>If you want a dynamically changing field with variable
5977           width, this is the feature you want to put to full use.
5978           This will allow the user to enter more data than the
5979           original size of the field and let the field grow.
5980           According to the field orientation it will scroll
5981           horizontally or vertically to incorporate the new
5982           data.</p>
5983
5984           <p>To make a field dynamically growable, the option
5985           O_STATIC should be turned off. This can be done with
5986           a</p>
5987
5988           <pre class=
5989           "PROGRAMLISTING">    field_opts_off(field_pointer, O_STATIC);</pre>
5990           <p>But it is usually not advisable to allow a field to
5991           grow infinitely. You can set a maximum limit to the
5992           growth of the field with</p>
5993
5994           <pre class=
5995           "PROGRAMLISTING">int set_max_field(FIELD *field,    /* Field on which to operate */
5996                   int max_growth); /* maximum growth allowed for the field */</pre>
5997           <p>The field info for a dynamically growable field can be
5998           retrieved by</p>
5999
6000           <pre class=
6001           "PROGRAMLISTING">int dynamic_field_info( FIELD *field,     /* Field on which to operate */
6002             int   *prows,     /* number of rows will be filled in this */
6003             int   *pcols,     /* number of columns will be filled in this*/
6004             int   *pmax)      /* maximum allowable growth will be filled */
6005                               /* in this */</pre>Though field_info
6006 work as usual, it is advisable to use this function to get the
6007 proper attributes of a dynamically growable field.
6008           <p>Recall the library routine new_field; a new field
6009           created with height set to one will be defined to be a
6010           one line field. A new field created with height greater
6011           than one will be defined to be a multi line field.</p>
6012
6013           <p>A one line field with O_STATIC turned off (dynamically
6014           growable field) will contain a single fixed row, but the
6015           number of columns can increase if the user enters more
6016           data than the initial field will hold. The number of
6017           columns displayed will remain fixed and the additional
6018           data will scroll horizontally.</p>
6019
6020           <p>A multi line field with O_STATIC turned off
6021           (dynamically growable field) will contain a fixed number
6022           of columns, but the number of rows can increase if the
6023           user enters more data than the initial field will hold.
6024           The number of rows displayed will remain fixed and the
6025           additional data will scroll vertically.</p>
6026
6027           <p>The above two paragraphs pretty much describe a
6028           dynamically growable field's behavior. The way other
6029           parts of forms library behaves is described below:</p>
6030
6031           <ol type="1">
6032             <li>
6033               <p>The field option O_AUTOSKIP will be ignored if the
6034               option O_STATIC is off and there is no maximum growth
6035               specified for the field. Currently, O_AUTOSKIP
6036               generates an automatic REQ_NEXT_FIELD form driver
6037               request when the user types in the last character
6038               position of a field. On a growable field with no
6039               maximum growth specified, there is no last character
6040               position. If a maximum growth is specified, the
6041               O_AUTOSKIP option will work as normal if the field
6042               has grown to its maximum size.</p>
6043             </li>
6044
6045             <li>
6046               <p>The field justification will be ignored if the
6047               option O_STATIC is off. Currently, set_field_just can
6048               be used to JUSTIFY_LEFT, JUSTIFY_RIGHT,
6049               JUSTIFY_CENTER the contents of a one line field. A
6050               growable one line field will, by definition, grow and
6051               scroll horizontally and may contain more data than
6052               can be justified. The return from field_just will be
6053               unchanged.</p>
6054             </li>
6055
6056             <li>
6057               <p>The overloaded form driver request REQ_NEW_LINE
6058               will operate the same way regardless of the
6059               O_NL_OVERLOAD form option if the field option
6060               O_STATIC is off and there is no maximum growth
6061               specified for the field. Currently, if the form
6062               option O_NL_OVERLOAD is on, REQ_NEW_LINE implicitly
6063               generates a REQ_NEXT_FIELD if called from the last
6064               line of a field. If a field can grow without bound,
6065               there is no last line, so REQ_NEW_LINE will never
6066               implicitly generate a REQ_NEXT_FIELD. If a maximum
6067               growth limit is specified and the O_NL_OVERLOAD form
6068               option is on, REQ_NEW_LINE will only implicitly
6069               generate REQ_NEXT_FIELD if the field has grown to its
6070               maximum size and the user is on the last line.</p>
6071             </li>
6072
6073             <li>
6074               <p>The library call dup_field will work as usual; it
6075               will duplicate the field, including the current
6076               buffer size and contents of the field being
6077               duplicated. Any specified maximum growth will also be
6078               duplicated.</p>
6079             </li>
6080
6081             <li>
6082               <p>The library call link_field will work as usual; it
6083               will duplicate all field attributes and share buffers
6084               with the field being linked. If the O_STATIC field
6085               option is subsequently changed by a field sharing
6086               buffers, how the system reacts to an attempt to enter
6087               more data into the field than the buffer will
6088               currently hold will depend on the setting of the
6089               option in the current field.</p>
6090             </li>
6091
6092             <li>
6093               <p>The library call field_info will work as usual;
6094               the variable nrow will contain the value of the
6095               original call to new_field. The user should use
6096               dynamic_field_info, described above, to query the
6097               current size of the buffer.</p>
6098             </li>
6099           </ol>
6100
6101           <p>Some of the above points make sense only after
6102           explaining form driver. We will be looking into that in
6103           next few sections.</p>
6104         </div>
6105       </div>
6106
6107       <div class="SECT2">
6108         <hr>
6109
6110         <h3 class="SECT2"><a name="FORMWINDOWS" id=
6111         "FORMWINDOWS">18.4. Form Windows</a></h3>
6112
6113         <p>The form windows concept is pretty much similar to menu
6114         windows. Every form is associated with a main window and a
6115         sub window. The form main window displays any title or
6116         border associated or whatever the user wishes. Then the sub
6117         window contains all the fields and displays them according
6118         to their position. This gives the flexibility of
6119         manipulating fancy form displaying very easily.</p>
6120
6121         <p>Since this is pretty much similar to menu windows, I am
6122         providing an example with out much explanation. The
6123         functions are similar and they work the same way.</p>
6124
6125         <div class="EXAMPLE">
6126           <a name="FFOWI" id="FFOWI"></a>
6127           <p><b>Example 28. Form Windows Example</b>
6128           </p>
6129
6130           <pre class="PROGRAMLISTING"><span class=
6131           "INLINEMEDIAOBJECT">#include &lt;string.h&gt;
6132 #include &lt;form.h&gt;
6133
6134 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
6135
6136 int main()
6137 {
6138         FIELD *field[3];
6139         FORM  *my_form;
6140         WINDOW *my_form_win;
6141         int ch, rows, cols;
6142         
6143         /* Initialize curses */
6144         initscr();
6145         start_color();
6146         cbreak();
6147         noecho();
6148         keypad(stdscr, TRUE);
6149
6150         /* Initialize few color pairs */
6151         init_pair(1, COLOR_RED, COLOR_BLACK);
6152
6153         /* Initialize the fields */
6154         field[0] = new_field(1, 10, 6, 1, 0, 0);
6155         field[1] = new_field(1, 10, 8, 1, 0, 0);
6156         field[2] = NULL;
6157
6158         /* Set field options */
6159         set_field_back(field[0], A_UNDERLINE);
6160         field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */
6161                                               /* Field is filled up             */
6162         set_field_back(field[1], A_UNDERLINE); 
6163         field_opts_off(field[1], O_AUTOSKIP);
6164         
6165         /* Create the form and post it */
6166         my_form = new_form(field);
6167         
6168         /* Calculate the area required for the form */
6169         scale_form(my_form, &amp;rows, &amp;cols);
6170
6171         /* Create the window to be associated with the form */
6172         my_form_win = newwin(rows + 4, cols + 4, 4, 4);
6173         keypad(my_form_win, TRUE);
6174
6175         /* Set main window and sub window */
6176         set_form_win(my_form, my_form_win);
6177         set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2));
6178
6179         /* Print a border around the main window and print a title */
6180         box(my_form_win, 0, 0);
6181         print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1));
6182         
6183         post_form(my_form);
6184         wrefresh(my_form_win);
6185
6186         mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
6187         refresh();
6188
6189         /* Loop through to get user requests */
6190         while((ch = wgetch(my_form_win)) != KEY_F(1))
6191         {       switch(ch)
6192                 {       case KEY_DOWN:
6193                                 /* Go to next field */
6194                                 form_driver(my_form, REQ_NEXT_FIELD);
6195                                 /* Go to the end of the present buffer */
6196                                 /* Leaves nicely at the last character */
6197                                 form_driver(my_form, REQ_END_LINE);
6198                                 break;
6199                         case KEY_UP:
6200                                 /* Go to previous field */
6201                                 form_driver(my_form, REQ_PREV_FIELD);
6202                                 form_driver(my_form, REQ_END_LINE);
6203                                 break;
6204                         default:
6205                                 /* If this is a normal character, it gets */
6206                                 /* Printed                                */    
6207                                 form_driver(my_form, ch);
6208                                 break;
6209                 }
6210         }
6211
6212         /* Un post form and free the memory */
6213         unpost_form(my_form);
6214         free_form(my_form);
6215         free_field(field[0]);
6216         free_field(field[1]); 
6217
6218         endwin();
6219         return 0;
6220 }
6221
6222 void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
6223 {       int length, x, y;
6224         float temp;
6225
6226         if(win == NULL)
6227                 win = stdscr;
6228         getyx(win, y, x);
6229         if(startx != 0)
6230                 x = startx;
6231         if(starty != 0)
6232                 y = starty;
6233         if(width == 0)
6234                 width = 80;
6235
6236         length = strlen(string);
6237         temp = (width - length)/ 2;
6238         x = startx + (int)temp;
6239         wattron(win, color);
6240         mvwprintw(win, y, x, "%s", string);
6241         wattroff(win, color);
6242         refresh();
6243 }</span></pre>
6244         </div>
6245       </div>
6246
6247       <div class="SECT2">
6248         <hr>
6249
6250         <h3 class="SECT2"><a name="FILEDVALIDATE" id=
6251         "FILEDVALIDATE">18.5. Field Validation</a></h3>
6252
6253         <p>By default, a field will accept any data input by the
6254         user. It is possible to attach validation to the field.
6255         Then any attempt by the user to leave the field, while it
6256         contains data that doesn't match the validation type will
6257         fail. Some validation types also have a character-validity
6258         check for each time a character is entered in the
6259         field.</p>
6260
6261         <p>Validation can be attached to a field with the following
6262         function.</p>
6263
6264         <pre class=
6265         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6266                    FIELDTYPE *ftype,      /* type to associate */
6267                    ...);                  /* additional arguments*/</pre>Once
6268 set, the validation type for a field can be queried with
6269
6270         <pre class=
6271         "PROGRAMLISTING">FIELDTYPE *field_type(FIELD *field);      /* field to query */</pre>
6272         <p>The form driver validates the data in a field only when
6273         data is entered by the end-user. Validation does not occur
6274         when</p>
6275
6276         <ul>
6277           <li>
6278             <p>the application program changes the field value by
6279             calling set_field_buffer.</p>
6280           </li>
6281
6282           <li>
6283             <p>linked field values are changed indirectly -- by
6284             changing the field to which they are linked</p>
6285           </li>
6286         </ul>
6287
6288         <p>The following are the pre-defined validation types. You
6289         can also specify custom validation, though it is a bit
6290         tricky and cumbersome.</p>
6291
6292         <h1 class="BRIDGEHEAD"><a name="AEN1074" id=
6293         "AEN1074"></a>TYPE_ALPHA</h1>
6294
6295         <p>This field type accepts alphabetic data; no blanks, no
6296         digits, no special characters (this is checked at
6297         character-entry time). It is set up with:</p>
6298
6299         <pre class=
6300         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6301                    TYPE_ALPHA,            /* type to associate */
6302                    int width);            /* minimum width of field */</pre>
6303         <p>The width argument sets a minimum width of data. The
6304         user has to enter at-least width number of characters
6305         before he can leave the field. Typically you'll want to set
6306         this to the field width; if it is greater than the field
6307         width, the validation check will always fail. A minimum
6308         width of zero makes field completion optional.</p>
6309
6310         <h1 class="BRIDGEHEAD"><a name="AEN1078" id=
6311         "AEN1078"></a>TYPE_ALNUM</h1>
6312
6313         <p>This field type accepts alphabetic data and digits; no
6314         blanks, no special characters (this is checked at
6315         character-entry time). It is set up with:</p>
6316
6317         <pre class=
6318         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6319                    TYPE_ALNUM,            /* type to associate */
6320                    int width);            /* minimum width of field */</pre>
6321         <p>The width argument sets a minimum width of data. As with
6322         TYPE_ALPHA, typically you'll want to set this to the field
6323         width; if it is greater than the field width, the
6324         validation check will always fail. A minimum width of zero
6325         makes field completion optional.</p>
6326
6327         <h1 class="BRIDGEHEAD"><a name="AEN1082" id=
6328         "AEN1082"></a>TYPE_ENUM</h1>
6329
6330         <p>This type allows you to restrict a field's values to be
6331         among a specified set of string values (for example, the
6332         two-letter postal codes for U.S. states). It is set up
6333         with:</p>
6334
6335         <pre class=
6336         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6337                    TYPE_ENUM,             /* type to associate */
6338                    char **valuelist;      /* list of possible values */
6339                    int checkcase;         /* case-sensitive? */
6340                    int checkunique);      /* must specify uniquely? */</pre>
6341         <p>The valuelist parameter must point at a NULL-terminated
6342         list of valid strings. The checkcase argument, if true,
6343         makes comparison with the string case-sensitive.</p>
6344
6345         <p>When the user exits a TYPE_ENUM field, the validation
6346         procedure tries to complete the data in the buffer to a
6347         valid entry. If a complete choice string has been entered,
6348         it is of course valid. But it is also possible to enter a
6349         prefix of a valid string and have it completed for you.</p>
6350
6351         <p>By default, if you enter such a prefix and it matches
6352         more than one value in the string list, the prefix will be
6353         completed to the first matching value. But the checkunique
6354         argument, if true, requires prefix matches to be unique in
6355         order to be valid.</p>
6356
6357         <p>The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests
6358         can be particularly useful with these fields.</p>
6359
6360         <h1 class="BRIDGEHEAD"><a name="AEN1089" id=
6361         "AEN1089"></a>TYPE_INTEGER</h1>
6362
6363         <p>This field type accepts an integer. It is set up as
6364         follows:</p>
6365
6366         <pre class=
6367         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6368                    TYPE_INTEGER,          /* type to associate */
6369                    int padding,           /* # places to zero-pad to */
6370                    int vmin, int vmax);   /* valid range */</pre>
6371         <p>Valid characters consist of an optional leading minus
6372         and digits. The range check is performed on exit. If the
6373         range maximum is less than or equal to the minimum, the
6374         range is ignored.</p>
6375
6376         <p>If the value passes its range check, it is padded with
6377         as many leading zero digits as necessary to meet the
6378         padding argument.</p>
6379
6380         <p>A TYPE_INTEGER value buffer can conveniently be
6381         interpreted with the C library function atoi(3).</p>
6382
6383         <h1 class="BRIDGEHEAD"><a name="AEN1095" id=
6384         "AEN1095"></a>TYPE_NUMERIC</h1>
6385
6386         <p>This field type accepts a decimal number. It is set up
6387         as follows:</p>
6388
6389         <pre class=
6390         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6391                    TYPE_NUMERIC,          /* type to associate */
6392                    int padding,           /* # places of precision */
6393                    int vmin, int vmax);   /* valid range */</pre>
6394         <p>Valid characters consist of an optional leading minus
6395         and digits. possibly including a decimal point. The range
6396         check is performed on exit. If the range maximum is less
6397         than or equal to the minimum, the range is ignored.</p>
6398
6399         <p>If the value passes its range check, it is padded with
6400         as many trailing zero digits as necessary to meet the
6401         padding argument.</p>
6402
6403         <p>A TYPE_NUMERIC value buffer can conveniently be
6404         interpreted with the C library function atof(3).</p>
6405
6406         <h1 class="BRIDGEHEAD"><a name="AEN1101" id=
6407         "AEN1101"></a>TYPE_REGEXP</h1>
6408
6409         <p>This field type accepts data matching a regular
6410         expression. It is set up as follows:</p>
6411
6412         <pre class=
6413         "PROGRAMLISTING">int set_field_type(FIELD *field,          /* field to alter */
6414                    TYPE_REGEXP,           /* type to associate */
6415                    char *regexp);         /* expression to match */</pre>
6416         <p>The syntax for regular expressions is that of
6417         regcomp(3). The check for regular-expression match is
6418         performed on exit.</p>
6419       </div>
6420
6421       <div class="SECT2">
6422         <hr>
6423
6424         <h3 class="SECT2"><a name="FORMDRIVER" id=
6425         "FORMDRIVER">18.6. Form Driver: The work horse of the forms
6426         system</a></h3>
6427
6428         <p>As in the menu system, form_driver() plays a very
6429         important role in forms system. All types of requests to
6430         forms system should be funneled through form_driver().</p>
6431
6432         <pre class=
6433         "PROGRAMLISTING">int form_driver(FORM *form,     /* form on which to operate     */
6434                 int request)    /* form request code         */</pre>
6435         <p>As you have seen some of the examples above, you have to
6436         be in a loop looking for user input and then decide whether
6437         it is a field data or a form request. The form requests are
6438         then passed to form_driver() to do the work.</p>
6439
6440         <p>The requests roughly can be divided into following
6441         categories. Different requests and their usage is explained
6442         below:</p>
6443
6444         <div class="SECT3">
6445           <hr>
6446
6447           <h4 class="SECT3"><a name="PAGENAVREQ" id=
6448           "PAGENAVREQ">18.6.1. Page Navigation Requests</a></h4>
6449
6450           <p>These requests cause page-level moves through the
6451           form, triggering display of a new form screen. A form can
6452           be made of multiple pages. If you have a big form with
6453           lot of fields and logical sections, then you can divide
6454           the form into pages. The function set_new_page() to set a
6455           new page at the field specified.</p>
6456
6457           <pre class=
6458           "PROGRAMLISTING">int set_new_page(FIELD *field,/* Field at which page break to be set or unset */
6459          bool new_page_flag); /* should be TRUE to put a break */</pre>
6460           <p>The following requests allow you to move to different
6461           pages</p>
6462
6463           <ul>
6464             <li>
6465               <p><span class="emphasis"><i class=
6466               "EMPHASIS">REQ_NEXT_PAGE</i></span> Move to the next
6467               form page.</p>
6468             </li>
6469
6470             <li>
6471               <p><span class="emphasis"><i class=
6472               "EMPHASIS">REQ_PREV_PAGE</i></span> Move to the
6473               previous form page.</p>
6474             </li>
6475
6476             <li>
6477               <p><span class="emphasis"><i class=
6478               "EMPHASIS">REQ_FIRST_PAGE</i></span> Move to the
6479               first form page.</p>
6480             </li>
6481
6482             <li>
6483               <p><span class="emphasis"><i class=
6484               "EMPHASIS">REQ_LAST_PAGE</i></span> Move to the last
6485               form page.</p>
6486             </li>
6487           </ul>
6488
6489           <p>These requests treat the list as cyclic; that is,
6490           REQ_NEXT_PAGE from the last page goes to the first, and
6491           REQ_PREV_PAGE from the first page goes to the last.</p>
6492         </div>
6493
6494         <div class="SECT3">
6495           <hr>
6496
6497           <h4 class="SECT3"><a name="INTERFIELDNAVREQ" id=
6498           "INTERFIELDNAVREQ">18.6.2. Inter-Field Navigation
6499           Requests</a></h4>
6500
6501           <p>These requests handle navigation between fields on the
6502           same page.</p>
6503
6504           <ul>
6505             <li>
6506               <p><span class="emphasis"><i class=
6507               "EMPHASIS">REQ_NEXT_FIELD</i></span> Move to next
6508               field.</p>
6509             </li>
6510
6511             <li>
6512               <p><span class="emphasis"><i class=
6513               "EMPHASIS">REQ_PREV_FIELD</i></span> Move to previous
6514               field.</p>
6515             </li>
6516
6517             <li>
6518               <p><span class="emphasis"><i class=
6519               "EMPHASIS">REQ_FIRST_FIELD</i></span> Move to the
6520               first field.</p>
6521             </li>
6522
6523             <li>
6524               <p><span class="emphasis"><i class=
6525               "EMPHASIS">REQ_LAST_FIELD</i></span> Move to the last
6526               field.</p>
6527             </li>
6528
6529             <li>
6530               <p><span class="emphasis"><i class=
6531               "EMPHASIS">REQ_SNEXT_FIELD</i></span> Move to sorted
6532               next field.</p>
6533             </li>
6534
6535             <li>
6536               <p><span class="emphasis"><i class=
6537               "EMPHASIS">REQ_SPREV_FIELD</i></span> Move to sorted
6538               previous field.</p>
6539             </li>
6540
6541             <li>
6542               <p><span class="emphasis"><i class=
6543               "EMPHASIS">REQ_SFIRST_FIELD</i></span> Move to the
6544               sorted first field.</p>
6545             </li>
6546
6547             <li>
6548               <p><span class="emphasis"><i class=
6549               "EMPHASIS">REQ_SLAST_FIELD</i></span> Move to the
6550               sorted last field.</p>
6551             </li>
6552
6553             <li>
6554               <p><span class="emphasis"><i class=
6555               "EMPHASIS">REQ_LEFT_FIELD</i></span> Move left to
6556               field.</p>
6557             </li>
6558
6559             <li>
6560               <p><span class="emphasis"><i class=
6561               "EMPHASIS">REQ_RIGHT_FIELD</i></span> Move right to
6562               field.</p>
6563             </li>
6564
6565             <li>
6566               <p><span class="emphasis"><i class=
6567               "EMPHASIS">REQ_UP_FIELD</i></span> Move up to
6568               field.</p>
6569             </li>
6570
6571             <li>
6572               <p><span class="emphasis"><i class=
6573               "EMPHASIS">REQ_DOWN_FIELD</i></span> Move down to
6574               field.</p>
6575             </li>
6576           </ul>
6577
6578           <p>These requests treat the list of fields on a page as
6579           cyclic; that is, REQ_NEXT_FIELD from the last field goes
6580           to the first, and REQ_PREV_FIELD from the first field
6581           goes to the last. The order of the fields for these (and
6582           the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is
6583           simply the order of the field pointers in the form array
6584           (as set up by new_form() or set_form_fields()</p>
6585
6586           <p>It is also possible to traverse the fields as if they
6587           had been sorted in screen-position order, so the sequence
6588           goes left-to-right and top-to-bottom. To do this, use the
6589           second group of four sorted-movement requests.</p>
6590
6591           <p>Finally, it is possible to move between fields using
6592           visual directions up, down, right, and left. To
6593           accomplish this, use the third group of four requests.
6594           Note, however, that the position of a form for purposes
6595           of these requests is its upper-left corner.</p>
6596
6597           <p>For example, suppose you have a multi-line field B,
6598           and two single-line fields A and C on the same line with
6599           B, with A to the left of B and C to the right of B. A
6600           REQ_MOVE_RIGHT from A will go to B only if A, B, and C
6601           all share the same first line; otherwise it will skip
6602           over B to C.</p>
6603         </div>
6604
6605         <div class="SECT3">
6606           <hr>
6607
6608           <h4 class="SECT3"><a name="INTRAFIELDNAVREQ" id=
6609           "INTRAFIELDNAVREQ">18.6.3. Intra-Field Navigation
6610           Requests</a></h4>
6611
6612           <p>These requests drive movement of the edit cursor
6613           within the currently selected field.</p>
6614
6615           <ul>
6616             <li>
6617               <p><span class="emphasis"><i class=
6618               "EMPHASIS">REQ_NEXT_CHAR</i></span> Move to next
6619               character.</p>
6620             </li>
6621
6622             <li>
6623               <p><span class="emphasis"><i class=
6624               "EMPHASIS">REQ_PREV_CHAR</i></span> Move to previous
6625               character.</p>
6626             </li>
6627
6628             <li>
6629               <p><span class="emphasis"><i class=
6630               "EMPHASIS">REQ_NEXT_LINE</i></span> Move to next
6631               line.</p>
6632             </li>
6633
6634             <li>
6635               <p><span class="emphasis"><i class=
6636               "EMPHASIS">REQ_PREV_LINE</i></span> Move to previous
6637               line.</p>
6638             </li>
6639
6640             <li>
6641               <p><span class="emphasis"><i class=
6642               "EMPHASIS">REQ_NEXT_WORD</i></span> Move to next
6643               word.</p>
6644             </li>
6645
6646             <li>
6647               <p><span class="emphasis"><i class=
6648               "EMPHASIS">REQ_PREV_WORD</i></span> Move to previous
6649               word.</p>
6650             </li>
6651
6652             <li>
6653               <p><span class="emphasis"><i class=
6654               "EMPHASIS">REQ_BEG_FIELD</i></span> Move to beginning
6655               of field.</p>
6656             </li>
6657
6658             <li>
6659               <p><span class="emphasis"><i class=
6660               "EMPHASIS">REQ_END_FIELD</i></span> Move to end of
6661               field.</p>
6662             </li>
6663
6664             <li>
6665               <p><span class="emphasis"><i class=
6666               "EMPHASIS">REQ_BEG_LINE</i></span> Move to beginning
6667               of line.</p>
6668             </li>
6669
6670             <li>
6671               <p><span class="emphasis"><i class=
6672               "EMPHASIS">REQ_END_LINE</i></span> Move to end of
6673               line.</p>
6674             </li>
6675
6676             <li>
6677               <p><span class="emphasis"><i class=
6678               "EMPHASIS">REQ_LEFT_CHAR</i></span> Move left in
6679               field.</p>
6680             </li>
6681
6682             <li>
6683               <p><span class="emphasis"><i class=
6684               "EMPHASIS">REQ_RIGHT_CHAR</i></span> Move right in
6685               field.</p>
6686             </li>
6687
6688             <li>
6689               <p><span class="emphasis"><i class=
6690               "EMPHASIS">REQ_UP_CHAR</i></span> Move up in
6691               field.</p>
6692             </li>
6693
6694             <li>
6695               <p><span class="emphasis"><i class=
6696               "EMPHASIS">REQ_DOWN_CHAR</i></span> Move down in
6697               field.</p>
6698             </li>
6699           </ul>
6700
6701           <p>Each word is separated from the previous and next
6702           characters by whitespace. The commands to move to
6703           beginning and end of line or field look for the first or
6704           last non-pad character in their ranges.</p>
6705         </div>
6706
6707         <div class="SECT3">
6708           <hr>
6709
6710           <h4 class="SECT3"><a name="SCROLLREQ" id=
6711           "SCROLLREQ">18.6.4. Scrolling Requests</a></h4>
6712
6713           <p>Fields that are dynamic and have grown and fields
6714           explicitly created with offscreen rows are scrollable.
6715           One-line fields scroll horizontally; multi-line fields
6716           scroll vertically. Most scrolling is triggered by editing
6717           and intra-field movement (the library scrolls the field
6718           to keep the cursor visible). It is possible to explicitly
6719           request scrolling with the following requests:</p>
6720
6721           <ul>
6722             <li>
6723               <p><span class="emphasis"><i class=
6724               "EMPHASIS">REQ_SCR_FLINE</i></span> Scroll vertically
6725               forward a line.</p>
6726             </li>
6727
6728             <li>
6729               <p><span class="emphasis"><i class=
6730               "EMPHASIS">REQ_SCR_BLINE</i></span> Scroll vertically
6731               backward a line.</p>
6732             </li>
6733
6734             <li>
6735               <p><span class="emphasis"><i class=
6736               "EMPHASIS">REQ_SCR_FPAGE</i></span> Scroll vertically
6737               forward a page.</p>
6738             </li>
6739
6740             <li>
6741               <p><span class="emphasis"><i class=
6742               "EMPHASIS">REQ_SCR_BPAGE</i></span> Scroll vertically
6743               backward a page.</p>
6744             </li>
6745
6746             <li>
6747               <p><span class="emphasis"><i class=
6748               "EMPHASIS">REQ_SCR_FHPAGE</i></span> Scroll
6749               vertically forward half a page.</p>
6750             </li>
6751
6752             <li>
6753               <p><span class="emphasis"><i class=
6754               "EMPHASIS">REQ_SCR_BHPAGE</i></span> Scroll
6755               vertically backward half a page.</p>
6756             </li>
6757
6758             <li>
6759               <p><span class="emphasis"><i class=
6760               "EMPHASIS">REQ_SCR_FCHAR</i></span> Scroll
6761               horizontally forward a character.</p>
6762             </li>
6763
6764             <li>
6765               <p><span class="emphasis"><i class=
6766               "EMPHASIS">REQ_SCR_BCHAR</i></span> Scroll
6767               horizontally backward a character.</p>
6768             </li>
6769
6770             <li>
6771               <p><span class="emphasis"><i class=
6772               "EMPHASIS">REQ_SCR_HFLINE</i></span> Scroll
6773               horizontally one field width forward.</p>
6774             </li>
6775
6776             <li>
6777               <p><span class="emphasis"><i class=
6778               "EMPHASIS">REQ_SCR_HBLINE</i></span> Scroll
6779               horizontally one field width backward.</p>
6780             </li>
6781
6782             <li>
6783               <p><span class="emphasis"><i class=
6784               "EMPHASIS">REQ_SCR_HFHALF</i></span> Scroll
6785               horizontally one half field width forward.</p>
6786             </li>
6787
6788             <li>
6789               <p><span class="emphasis"><i class=
6790               "EMPHASIS">REQ_SCR_HBHALF</i></span> Scroll
6791               horizontally one half field width backward.</p>
6792             </li>
6793           </ul>
6794
6795           <p>For scrolling purposes, a page of a field is the
6796           height of its visible part.</p>
6797         </div>
6798
6799         <div class="SECT3">
6800           <hr>
6801
6802           <h4 class="SECT3"><a name="EDITREQ" id="EDITREQ">18.6.5.
6803           Editing Requests</a></h4>
6804
6805           <p>When you pass the forms driver an ASCII character, it
6806           is treated as a request to add the character to the
6807           field's data buffer. Whether this is an insertion or a
6808           replacement depends on the field's edit mode (insertion
6809           is the default.</p>
6810
6811           <p>The following requests support editing the field and
6812           changing the edit mode:</p>
6813
6814           <ul>
6815             <li>
6816               <p><span class="emphasis"><i class=
6817               "EMPHASIS">REQ_INS_MODE</i></span> Set insertion
6818               mode.</p>
6819             </li>
6820
6821             <li>
6822               <p><span class="emphasis"><i class=
6823               "EMPHASIS">REQ_OVL_MODE</i></span> Set overlay
6824               mode.</p>
6825             </li>
6826
6827             <li>
6828               <p><span class="emphasis"><i class=
6829               "EMPHASIS">REQ_NEW_LINE</i></span> New line request
6830               (see below for explanation).</p>
6831             </li>
6832
6833             <li>
6834               <p><span class="emphasis"><i class=
6835               "EMPHASIS">REQ_INS_CHAR</i></span> Insert space at
6836               character location.</p>
6837             </li>
6838
6839             <li>
6840               <p><span class="emphasis"><i class=
6841               "EMPHASIS">REQ_INS_LINE</i></span> Insert blank line
6842               at character location.</p>
6843             </li>
6844
6845             <li>
6846               <p><span class="emphasis"><i class=
6847               "EMPHASIS">REQ_DEL_CHAR</i></span> Delete character
6848               at cursor.</p>
6849             </li>
6850
6851             <li>
6852               <p><span class="emphasis"><i class=
6853               "EMPHASIS">REQ_DEL_PREV</i></span> Delete previous
6854               word at cursor.</p>
6855             </li>
6856
6857             <li>
6858               <p><span class="emphasis"><i class=
6859               "EMPHASIS">REQ_DEL_LINE</i></span> Delete line at
6860               cursor.</p>
6861             </li>
6862
6863             <li>
6864               <p><span class="emphasis"><i class=
6865               "EMPHASIS">REQ_DEL_WORD</i></span> Delete word at
6866               cursor.</p>
6867             </li>
6868
6869             <li>
6870               <p><span class="emphasis"><i class=
6871               "EMPHASIS">REQ_CLR_EOL</i></span> Clear to end of
6872               line.</p>
6873             </li>
6874
6875             <li>
6876               <p><span class="emphasis"><i class=
6877               "EMPHASIS">REQ_CLR_EOF</i></span> Clear to end of
6878               field.</p>
6879             </li>
6880
6881             <li>
6882               <p><span class="emphasis"><i class=
6883               "EMPHASIS">REQ_CLR_FIELD</i></span> Clear entire
6884               field.</p>
6885             </li>
6886           </ul>
6887
6888           <p>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV
6889           requests is complicated and partly controlled by a pair
6890           of forms options. The special cases are triggered when
6891           the cursor is at the beginning of a field, or on the last
6892           line of the field.</p>
6893
6894           <p>First, we consider REQ_NEW_LINE:</p>
6895
6896           <p>The normal behavior of REQ_NEW_LINE in insert mode is
6897           to break the current line at the position of the edit
6898           cursor, inserting the portion of the current line after
6899           the cursor as a new line following the current and moving
6900           the cursor to the beginning of that new line (you may
6901           think of this as inserting a newline in the field
6902           buffer).</p>
6903
6904           <p>The normal behavior of REQ_NEW_LINE in overlay mode is
6905           to clear the current line from the position of the edit
6906           cursor to end of line. The cursor is then moved to the
6907           beginning of the next line.</p>
6908
6909           <p>However, REQ_NEW_LINE at the beginning of a field, or
6910           on the last line of a field, instead does a
6911           REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this special
6912           action is disabled.</p>
6913
6914           <p>Now, let us consider REQ_DEL_PREV:</p>
6915
6916           <p>The normal behavior of REQ_DEL_PREV is to delete the
6917           previous character. If insert mode is on, and the cursor
6918           is at the start of a line, and the text on that line will
6919           fit on the previous one, it instead appends the contents
6920           of the current line to the previous one and deletes the
6921           current line (you may think of this as deleting a newline
6922           from the field buffer).</p>
6923
6924           <p>However, REQ_DEL_PREV at the beginning of a field is
6925           instead treated as a REQ_PREV_FIELD.</p>
6926
6927           <p>If the O_BS_OVERLOAD option is off, this special
6928           action is disabled and the forms driver just returns
6929           E_REQUEST_DENIED.</p>
6930         </div>
6931
6932         <div class="SECT3">
6933           <hr>
6934
6935           <h4 class="SECT3"><a name="ORDERREQ" id=
6936           "ORDERREQ">18.6.6. Order Requests</a></h4>
6937
6938           <p>If the type of your field is ordered, and has
6939           associated functions for getting the next and previous
6940           values of the type from a given value, there are requests
6941           that can fetch that value into the field buffer:</p>
6942
6943           <ul>
6944             <li>
6945               <p><span class="emphasis"><i class=
6946               "EMPHASIS">REQ_NEXT_CHOICE</i></span> Place the
6947               successor value of the current value in the
6948               buffer.</p>
6949             </li>
6950
6951             <li>
6952               <p><span class="emphasis"><i class=
6953               "EMPHASIS">REQ_PREV_CHOICE</i></span> Place the
6954               predecessor value of the current value in the
6955               buffer.</p>
6956             </li>
6957           </ul>
6958
6959           <p>Of the built-in field types, only TYPE_ENUM has
6960           built-in successor and predecessor functions. When you
6961           define a field type of your own (see Custom Validation
6962           Types), you can associate our own ordering functions.</p>
6963         </div>
6964
6965         <div class="SECT3">
6966           <hr>
6967
6968           <h4 class="SECT3"><a name="APPLICCOMMANDS" id=
6969           "APPLICCOMMANDS">18.6.7. Application Commands</a></h4>
6970
6971           <p>Form requests are represented as integers above the
6972           curses value greater than KEY_MAX and less than or equal
6973           to the constant MAX_COMMAND. A value within this range
6974           gets ignored by form_driver(). So this can be used for
6975           any purpose by the application. It can be treated as an
6976           application specific action and take corresponding
6977           action.</p>
6978         </div>
6979       </div>
6980     </div>
6981
6982     <div class="SECT1">
6983       <hr>
6984
6985       <h2 class="SECT1"><a name="TOOLS" id="TOOLS">19. Tools and
6986       Widget Libraries</a></h2>
6987
6988       <p>Now that you have seen the capabilities of ncurses and its
6989       sister libraries, you are rolling your sleeves up and gearing
6990       for a project that heavily manipulates screen. But wait.. It
6991       can be pretty difficult to write and maintain complex GUI
6992       widgets in plain ncurses or even with the additional
6993       libraries. There are some ready-to-use tools and widget
6994       libraries that can be used instead of writing your own
6995       widgets. You can use some of them, get ideas from the code,
6996       or even extend them.</p>
6997
6998       <div class="SECT2">
6999         <hr>
7000
7001         <h3 class="SECT2"><a name="CDK" id="CDK">19.1. CDK (Curses
7002         Development Kit)</a></h3>
7003
7004         <p>In the author's words</p>
7005
7006         <p><span class="emphasis"><i class="EMPHASIS">CDK stands
7007         for 'Curses Development Kit' and it currently contains 21
7008         ready to use widgets which facilitate the speedy
7009         development of full screen curses programs.</i></span>
7010         </p>
7011
7012         <p>The kit provides some useful widgets, which can be used
7013         in your programs directly. It is pretty well written and
7014         the documentation is very good. The examples in the
7015         examples directory can be a good place to start for
7016         beginners. The CDK can be downloaded from <a href=
7017         "https://invisible-island.net/cdk/" target=
7018         "_top">https://invisible-island.net/cdk/</a> . Follow the
7019         instructions in README file to install it.</p>
7020
7021         <div class="SECT3">
7022           <hr>
7023
7024           <h4 class="SECT3"><a name="WIDGETLIST" id=
7025           "WIDGETLIST">19.1.1. Widget List</a></h4>
7026
7027           <p>The following is the list of widgets provided with cdk
7028           and their description.</p>
7029
7030           <pre class=
7031           "PROGRAMLISTING">Widget Type           Quick Description
7032 ===========================================================================
7033 Alphalist             Allows a user to select from a list of words, with
7034                       the ability to narrow the search list by typing in a
7035                       few characters of the desired word.
7036 Buttonbox             This creates a multiple button widget. 
7037 Calendar              Creates a little simple calendar widget.
7038 Dialog                Prompts the user with a message, and the user
7039                       can pick an answer from the buttons provided.
7040 Entry                 Allows the user to enter various types of information.
7041 File Selector         A file selector built from Cdk base widgets. This
7042                       example shows how to create more complicated widgets
7043                       using the Cdk widget library.
7044 Graph                 Draws a graph.
7045 Histogram             Draws a histogram.
7046 Item List             Creates a pop up field which allows the user to select
7047                       one of several choices in a small field. Very useful
7048                       for things like days of the week or month names.
7049 Label                 Displays messages in a pop up box, or the label can be
7050                       considered part of the screen.
7051 Marquee               Displays a message in a scrolling marquee.
7052 Matrix                Creates a complex matrix with lots of options.
7053 Menu                  Creates a pull-down menu interface.
7054 Multiple Line Entry   A multiple line entry field. Very useful
7055                       for long fields. (like a description
7056                       field)
7057 Radio List            Creates a radio button list.
7058 Scale                 Creates a numeric scale. Used for allowing a user to
7059                       pick a numeric value and restrict them to a range of 
7060                       values.
7061 Scrolling List        Creates a scrolling list/menu list.
7062 Scrolling Window      Creates a scrolling log file viewer. Can add 
7063                       information into the window while its running. 
7064                       A good widget for displaying the progress of
7065                       something. (akin to a console window)
7066 Selection List        Creates a multiple option selection list.
7067 Slider                Akin to the scale widget, this widget provides a
7068                       visual slide bar to represent the numeric value.
7069 Template              Creates a entry field with character sensitive 
7070                       positions. Used for pre-formatted fields like
7071                       dates and phone numbers.
7072 Viewer                This is a file/information viewer. Very useful
7073                       when you need to display loads of information.
7074 ===========================================================================</pre>
7075           <p>A few of the widgets are modified by Thomas Dickey in
7076           recent versions.</p>
7077         </div>
7078
7079         <div class="SECT3">
7080           <hr>
7081
7082           <h4 class="SECT3"><a name="CDKATTRACT" id=
7083           "CDKATTRACT">19.1.2. Some Attractive Features</a></h4>
7084
7085           <p>Apart from making our life easier with readily usable
7086           widgets, cdk solves one frustrating problem with printing
7087           multi colored strings, justified strings elegantly.
7088           Special formatting tags can be embedded in the strings
7089           which are passed to CDK functions. For Example</p>
7090
7091           <p>If the string</p>
7092
7093           <pre class=
7094           "PROGRAMLISTING">"&lt;/B/1&gt;This line should have a yellow foreground and a blue
7095 background.&lt;!1&gt;"</pre>
7096           <p>given as a parameter to newCDKLabel(), it prints the
7097           line with yellow foreground and blue background. There
7098           are other tags available for justifying string, embedding
7099           special drawing characters, etc. Please refer to the man
7100           page cdk_display(3X) for details. The man page explains
7101           the usage with nice examples.</p>
7102         </div>
7103
7104         <div class="SECT3">
7105           <hr>
7106
7107           <h4 class="SECT3"><a name="CDKCONCLUSION" id=
7108           "CDKCONCLUSION">19.1.3. Conclusion</a></h4>
7109
7110           <p>All in all, CDK is a well-written package of widgets,
7111           which if used properly can form a strong frame work for
7112           developing complex GUI.</p>
7113         </div>
7114       </div>
7115
7116       <div class="SECT2">
7117         <hr>
7118
7119         <h3 class="SECT2"><a name="DIALOG" id="DIALOG">19.2. The
7120         dialog</a></h3>
7121
7122         <p>Long long ago, in September 1994, when few people knew
7123         linux, Jeff Tranter wrote an <a href=
7124         "http://www2.linuxjournal.com/lj-issues/issue5/2807.html"
7125         target="_top">article</a> on dialog in Linux Journal. He
7126         starts the article with these words..</p>
7127
7128         <p><span class="emphasis"><i class="EMPHASIS">Linux is
7129         based on the Unix operating system, but also features a
7130         number of unique and useful kernel features and application
7131         programs that often go beyond what is available under Unix.
7132         One little-known gem is "dialog", a utility for creating
7133         professional-looking dialog boxes from within shell
7134         scripts. This article presents a tutorial introduction to
7135         the dialog utility, and shows examples of how and where it
7136         can be used</i></span>
7137         </p>
7138
7139         <p>As he explains, dialog is a real gem in making
7140         professional-looking dialog boxes with ease. It creates a
7141         variety of dialog boxes, menus, check lists, etc. It is
7142         usually installed by default. If not, you can download it
7143         from <a href="https://invisible-island.net/dialog/" target=
7144         "_top">Thomas Dickey</a>'s site.</p>
7145
7146         <p>The above-mentioned article gives a very good overview
7147         of its uses and capabilities. The man page has more
7148         details. It can be used in variety of situations. One good
7149         example is building of linux kernel in text mode. Linux
7150         kernel uses a modified version of dialog tailored for its
7151         needs.</p>
7152
7153         <p>dialog was initially designed to be used with shell
7154         scripts. If you want to use its functionality in a c
7155         program, then you can use libdialog. The documentation
7156         regarding this is sparse. Definitive reference is the
7157         dialog.h header file which comes with the library. You may
7158         need to hack here and there to get the required output. The
7159         source is easily customizable. I have used it on a number
7160         of occasions by modifying the code.</p>
7161       </div>
7162
7163       <div class="SECT2">
7164         <hr>
7165
7166         <h3 class="SECT2"><a name="PERLCURSES" id=
7167         "PERLCURSES">19.3. Perl Curses Modules CURSES::FORM and
7168         CURSES::WIDGETS</a></h3>
7169
7170         <p>The perl module Curses, Curses::Form and Curses::Widgets
7171         give access to curses from perl. If you have curses and
7172         basic perl is installed, you can get these modules from
7173         <a href="http://www.cpan.org/modules/01modules.index.html"
7174         target="_top">CPAN All Modules page</a>. Get the three
7175         zipped modules in the Curses category. Once installed you
7176         can use these modules from perl scripts like any other
7177         module. For more information on perl modules see perlmod
7178         man page. The above modules come with good documentation
7179         and they have some demo scripts to test the functionality.
7180         Though the widgets provided are very rudimentary, these
7181         modules provide good access to curses library from
7182         perl.</p>
7183
7184         <p>Some of my code examples are converted to perl by
7185         Anuradha Ratnaweera and they are available in the
7186         <tt class="LITERAL">perl</tt> directory.</p>
7187
7188         <p>For more information see man pages Curses(3) ,
7189         Curses::Form(3) and Curses::Widgets(3). These pages are
7190         installed only when the above modules are acquired and
7191         installed.</p>
7192       </div>
7193     </div>
7194
7195     <div class="SECT1">
7196       <hr>
7197
7198       <h2 class="SECT1"><a name="JUSTFORFUN" id="JUSTFORFUN">20.
7199       Just For Fun !!!</a></h2>
7200
7201       <p>This section contains few programs written by me just for
7202       fun. They don't signify a better programming practice or the
7203       best way of using ncurses. They are provided here so as to
7204       allow beginners to get ideas and add more programs to this
7205       section. If you have written a couple of nice, simple
7206       programs in curses and want them to included here, contact
7207       <a href="mailto:ppadala@gmail.com" target="_top">me</a>.</p>
7208
7209       <div class="SECT2">
7210         <hr>
7211
7212         <h3 class="SECT2"><a name="GAMEOFLIFE" id=
7213         "GAMEOFLIFE">20.1. The Game of Life</a></h3>
7214
7215         <p>Game of life is a wonder of math. In <a href=
7216         "http://www.math.com/students/wonders/life/life.html"
7217         target="_top">Paul Callahan</a>'s words</p>
7218
7219         <pre class="PROGRAMLISTING"><span class="emphasis"><i class=
7220         "EMPHASIS">The Game of Life (or simply Life) is not a game in the conventional sense. There
7221 are no players, and no winning or losing. Once the "pieces" are placed in the
7222 starting position, the rules determine everything that happens later.
7223 Nevertheless, Life is full of surprises! In most cases, it is impossible to look
7224 at a starting position (or pattern) and see what will happen in the future. The
7225 only way to find out is to follow the rules of the game.</i></span></pre>
7226         <p>This program starts with a simple inverted U pattern and
7227         shows how wonderful life works. There is a lot of room for
7228         improvement in the program. You can let the user enter
7229         pattern of his choice or even take input from a file. You
7230         can also change rules and play with a lot of variations.
7231         Search on <a href="https://www.google.com" target=
7232         "_top">google</a> for interesting information on game of
7233         life.</p>
7234
7235         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7236         JustForFun/life.c</i></span>
7237         </p>
7238       </div>
7239
7240       <div class="SECT2">
7241         <hr>
7242
7243         <h3 class="SECT2"><a name="MAGIC" id="MAGIC">20.2. Magic
7244         Square</a></h3>
7245
7246         <p>Magic Square, another wonder of math, is very simple to
7247         understand but very difficult to make. In a magic square
7248         sum of the numbers in each row, each column is equal. Even
7249         diagonal sum can be equal. There are many variations which
7250         have special properties.</p>
7251
7252         <p>This program creates a simple magic square of odd
7253         order.</p>
7254
7255         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7256         JustForFun/magic.c</i></span>
7257         </p>
7258       </div>
7259
7260       <div class="SECT2">
7261         <hr>
7262
7263         <h3 class="SECT2"><a name="HANOI" id="HANOI">20.3. Towers
7264         of Hanoi</a></h3>
7265
7266         <p>The famous towers of hanoi solver. The aim of the game
7267         is to move the disks on the first peg to last peg, using
7268         middle peg as a temporary stay. The catch is not to place a
7269         larger disk over a small disk at any time.</p>
7270
7271         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7272         JustForFun/hanoi.c</i></span>
7273         </p>
7274       </div>
7275
7276       <div class="SECT2">
7277         <hr>
7278
7279         <h3 class="SECT2"><a name="QUEENS" id="QUEENS">20.4. Queens
7280         Puzzle</a></h3>
7281
7282         <p>The objective of the famous N-Queen puzzle is to put N
7283         queens on a N X N chess board without attacking each
7284         other.</p>
7285
7286         <p>This program solves it with a simple backtracking
7287         technique.</p>
7288
7289         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7290         JustForFun/queens.c</i></span>
7291         </p>
7292       </div>
7293
7294       <div class="SECT2">
7295         <hr>
7296
7297         <h3 class="SECT2"><a name="SHUFFLE" id="SHUFFLE">20.5.
7298         Shuffle</a></h3>
7299
7300         <p>A fun game, if you have time to kill.</p>
7301
7302         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7303         JustForFun/shuffle.c</i></span>
7304         </p>
7305       </div>
7306
7307       <div class="SECT2">
7308         <hr>
7309
7310         <h3 class="SECT2"><a name="TT" id="TT">20.6. Typing
7311         Tutor</a></h3>
7312
7313         <p>A simple typing tutor, I created more out of need than
7314         for ease of use. If you know how to put your fingers
7315         correctly on the keyboard, but lack practice, this can be
7316         helpful.</p>
7317
7318         <p><span class="emphasis"><i class="EMPHASIS">File Path:
7319         JustForFun/tt.c</i></span>
7320         </p>
7321       </div>
7322     </div>
7323
7324     <div class="SECT1">
7325       <hr>
7326
7327       <h2 class="SECT1"><a name="REF" id="REF">21. References</a></h2>
7328
7329       <ul>
7330         <li>
7331           <p>NCURSES man pages</p>
7332         </li>
7333
7334         <li>
7335           <p>NCURSES FAQ at <a href=
7336           "https://invisible-island.net/ncurses/ncurses.faq.html"
7337           target=
7338           "_top">https://invisible-island.net/ncurses/ncurses.faq.html</a></p>
7339         </li>
7340
7341         <li>
7342           <p>Writing programs with NCURSES by Eric Raymond and Zeyd
7343           M. Ben-Halim at <a href=
7344           "https://invisible-island.net/ncurses/ncurses-intro.html"
7345           target=
7346           "_top">https://invisible-island.net/ncurses/ncurses-intro.html</a>
7347           - somewhat obsolete. I was inspired by this document and
7348           the structure of this HOWTO follows from the original
7349           document</p>
7350         </li>
7351       </ul>
7352     </div>
7353   </div>
7354 </body>
7355 </html>