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