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" summary="revisions">
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">vw_printw()</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">vw_scanw()</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">
680echo "^[[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">
690echo "^[[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">
841ncurses
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">
861Description of files in each directory
862--------------------------------------
863JustForFun
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
1172int 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
1410int 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          vw_printw()</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
1704int 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          vw_scanw()</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
1901int 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
1946int 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
2167int 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
2258WINDOW *create_newwin(int height, int width, int starty, int startx);
2259void destroy_win(WINDOW *local_win);
2260
2261int 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
2304WINDOW *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
2316void 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
2431typedef struct _win_border_struct {
2432        chtype  ls, rs, ts, bs,
2433                tl, tr, bl, br;
2434}WIN_BORDER;
2435
2436typedef struct _WIN_struct {
2437
2438        int startx, starty;
2439        int height, width;
2440        WIN_BORDER border;
2441}WIN;
2442
2443void init_win_params(WIN *p_win);
2444void print_win_params(WIN *p_win);
2445void create_box(WIN *win, bool flag);
2446
2447int 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}
2496void 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}
2513void 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}
2521void 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
2575void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
2576int 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}
2592void 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
2773int startx = 0;
2774int starty = 0;
2775
2776char *choices[] = {
2777                        "Choice 1",
2778                        "Choice 2",
2779                        "Choice 3",
2780                        "Choice 4",
2781                        "Exit",
2782                  };
2783int n_choices = sizeof(choices) / sizeof(char *);
2784void print_menu(WINDOW *menu_win, int highlight);
2785
2786int 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
2839void 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
2992int startx = 0;
2993int starty = 0;
2994
2995char *choices[] = {     "Choice 1",
2996                        "Choice 2",
2997                        "Choice 3",
2998                        "Choice 4",
2999                        "Exit",
3000                  };
3001
3002int n_choices = sizeof(choices) / sizeof(char *);
3003
3004void print_menu(WINDOW *menu_win, int highlight);
3005void report_choice(int mouse_x, int mouse_y, int *p_choice);
3006
3007int 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        }
3051end:
3052        endwin();
3053        return 0;
3054}
3055
3056
3057void 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 */
3078void 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
3250int 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
3294int 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
3472int 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
3539void init_wins(WINDOW **wins, int n);
3540void win_show(WINDOW *win, char *label, int label_color);
3541void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3542
3543int 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 */
3599void 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 */
3615void 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
3629void 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
3714typedef 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
3724void init_wins(WINDOW **wins, int n);
3725void win_show(WINDOW *win, char *label, int label_color);
3726void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3727void set_user_ptrs(PANEL **panels, int n);
3728
3729int 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 */
3866void 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 */
3882void 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 */
3910void 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
3924void 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
4006typedef struct _PANEL_DATA {
4007        int hide;       /* TRUE if panel is hidden */
4008}PANEL_DATA;
4009
4010#define NLINES 10
4011#define NCOLS 40
4012
4013void init_wins(WINDOW **wins, int n);
4014void win_show(WINDOW *win, char *label, int label_color);
4015void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4016
4017int 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 */
4108void 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 */
4124void 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
4138void 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
4292char *choices[] = {
4293                        "Choice 1",
4294                        "Choice 2",
4295                        "Choice 3",
4296                        "Choice 4",
4297                        "Exit",
4298                  };
4299
4300int 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
4535char *choices[] = {
4536                        "Choice 1",
4537                        "Choice 2",
4538                        "Choice 3",
4539                        "Choice 4",
4540                        "Exit",
4541                        (char *)NULL,
4542                  };
4543void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4544
4545int 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
4613void 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
4672char *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                  };
4686void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4687
4688int 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
4768void 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
4832char *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
4841int 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
4987char *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
4998int 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
5123char *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
5134int 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
5226char *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                  };
5236void func(char *name);
5237
5238int 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
5302void 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
5432int 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">
5549int 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">
5566int 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
5615chtype field_fore(FIELD *field);        /* field to query */
5616                                        /* returns foreground attribute */
5617
5618int set_field_back(FIELD *field,        /* field to alter */
5619                   chtype attr);        /* attribute to set */
5620
5621chtype field_back(FIELD *field);        /* field to query */
5622                                        /* returns background attribute */
5623
5624int set_field_pad(FIELD *field,         /* field to alter */
5625                  int pad);             /* pad character to set */
5626
5627chtype 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
5651int 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">
5745int set_field_opts(FIELD *field,          /* field to alter */
5746                   int attr);             /* attribute to set */
5747
5748int field_opts_on(FIELD *field,           /* field to alter */
5749                  int attr);              /* attributes to turn on */
5750
5751int field_opts_off(FIELD *field,          /* field to alter */
5752                  int attr);              /* attributes to turn off */
5753
5754int 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
5895int 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">
5986int set_field_status(FIELD *field,      /* field to alter */
5987                   int status);         /* status to set */
5988
5989int 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">
6015int set_field_userptr(FIELD *field,
6016           char *userptr);      /* the user pointer you wish to associate */
6017                                /* with the field    */
6018
6019char *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">
6049int 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">
6056int 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
6062function to get the proper attributes of a dynamically growable
6063field.
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
6189void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
6190
6191int 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
6277void 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">
6320int 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">
6325FIELDTYPE *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">
6355int 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">
6374int 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">
6393int 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">
6425int set_field_type(FIELD *field,          /* field to alter */
6426                   TYPE_INTEGER,          /* type to associate */
6427                   int padding,           /* # places to zero-pad to */
6428                   int vmin, int vmax);   /* valid range */
6429</pre>
6430
6431        <p>Valid characters consist of an optional leading minus
6432        and digits. The range check is performed on exit. If the
6433        range maximum is less than or equal to the minimum, the
6434        range is ignored.</p>
6435
6436        <p>If the value passes its range check, it is padded with
6437        as many leading zero digits as necessary to meet the
6438        padding argument.</p>
6439
6440        <p>A TYPE_INTEGER value buffer can conveniently be
6441        interpreted with the C library function atoi(3).</p>
6442
6443        <h1 class="BRIDGEHEAD"><a name="AEN1090" id=
6444        "AEN1090"></a>TYPE_NUMERIC</h1>
6445
6446        <p>This field type accepts a decimal number. It is set up
6447        as follows:</p>
6448        <pre class="PROGRAMLISTING">
6449int set_field_type(FIELD *field,          /* field to alter */
6450                   TYPE_NUMERIC,          /* type to associate */
6451                   int padding,           /* # places of precision */
6452                   int vmin, int vmax);   /* valid range */
6453</pre>
6454
6455        <p>Valid characters consist of an optional leading minus
6456        and digits. possibly including a decimal point. The range
6457        check is performed on exit. If the range maximum is less
6458        than or equal to the minimum, the range is ignored.</p>
6459
6460        <p>If the value passes its range check, it is padded with
6461        as many trailing zero digits as necessary to meet the
6462        padding argument.</p>
6463
6464        <p>A TYPE_NUMERIC value buffer can conveniently be
6465        interpreted with the C library function atof(3).</p>
6466
6467        <h1 class="BRIDGEHEAD"><a name="AEN1096" id=
6468        "AEN1096"></a>TYPE_REGEXP</h1>
6469
6470        <p>This field type accepts data matching a regular
6471        expression. It is set up as follows:</p>
6472        <pre class="PROGRAMLISTING">
6473int set_field_type(FIELD *field,          /* field to alter */
6474                   TYPE_REGEXP,           /* type to associate */
6475                   char *regexp);         /* expression to match */
6476</pre>
6477
6478        <p>The syntax for regular expressions is that of
6479        regcomp(3). The check for regular-expression match is
6480        performed on exit.</p>
6481      </div>
6482
6483      <div class="SECT2">
6484        <hr>
6485
6486        <h3 class="SECT2"><a name="FORMDRIVER" id=
6487        "FORMDRIVER">18.6. Form Driver: The work horse of the forms
6488        system</a></h3>
6489
6490        <p>As in the menu system, form_driver() plays a very
6491        important role in forms system. All types of requests to
6492        forms system should be funneled through form_driver().</p>
6493        <pre class="PROGRAMLISTING">
6494int form_driver(FORM *form,     /* form on which to operate     */
6495                int request)    /* form request code         */
6496</pre>
6497
6498        <p>As you have seen some of the examples above, you have to
6499        be in a loop looking for user input and then decide whether
6500        it's a field data or a form request. The form requests are
6501        then passed to form_driver() to do the work.</p>
6502
6503        <p>The requests roughly can be divided into following
6504        categories. Different requests and their usage is explained
6505        below:</p>
6506
6507        <div class="SECT3">
6508          <hr>
6509
6510          <h4 class="SECT3"><a name="PAGENAVREQ" id=
6511          "PAGENAVREQ">18.6.1. Page Navigation Requests</a></h4>
6512
6513          <p>These requests cause page-level moves through the
6514          form, triggering display of a new form screen. A form can
6515          be made of multiple pages. If you have a big form with
6516          lot of fields and logical sections, then you can divide
6517          the form into pages. The function set_new_page() to set a
6518          new page at the field specified.</p>
6519          <pre class="PROGRAMLISTING">
6520int set_new_page(FIELD *field,/* Field at which page break to be set or unset */
6521         bool new_page_flag); /* should be TRUE to put a break */
6522</pre>
6523
6524          <p>The following requests allow you to move to different
6525          pages</p>
6526
6527          <ul>
6528            <li>
6529              <p><span class="emphasis"><i class=
6530              "EMPHASIS">REQ_NEXT_PAGE</i></span> Move to the next
6531              form page.</p>
6532            </li>
6533
6534            <li>
6535              <p><span class="emphasis"><i class=
6536              "EMPHASIS">REQ_PREV_PAGE</i></span> Move to the
6537              previous form page.</p>
6538            </li>
6539
6540            <li>
6541              <p><span class="emphasis"><i class=
6542              "EMPHASIS">REQ_FIRST_PAGE</i></span> Move to the
6543              first form page.</p>
6544            </li>
6545
6546            <li>
6547              <p><span class="emphasis"><i class=
6548              "EMPHASIS">REQ_LAST_PAGE</i></span> Move to the last
6549              form page.</p>
6550            </li>
6551          </ul>
6552
6553          <p>These requests treat the list as cyclic; that is,
6554          REQ_NEXT_PAGE from the last page goes to the first, and
6555          REQ_PREV_PAGE from the first page goes to the last.</p>
6556        </div>
6557
6558        <div class="SECT3">
6559          <hr>
6560
6561          <h4 class="SECT3"><a name="INTERFIELDNAVREQ" id=
6562          "INTERFIELDNAVREQ">18.6.2. Inter-Field Navigation
6563          Requests</a></h4>
6564
6565          <p>These requests handle navigation between fields on the
6566          same page.</p>
6567
6568          <ul>
6569            <li>
6570              <p><span class="emphasis"><i class=
6571              "EMPHASIS">REQ_NEXT_FIELD</i></span> Move to next
6572              field.</p>
6573            </li>
6574
6575            <li>
6576              <p><span class="emphasis"><i class=
6577              "EMPHASIS">REQ_PREV_FIELD</i></span> Move to previous
6578              field.</p>
6579            </li>
6580
6581            <li>
6582              <p><span class="emphasis"><i class=
6583              "EMPHASIS">REQ_FIRST_FIELD</i></span> Move to the
6584              first field.</p>
6585            </li>
6586
6587            <li>
6588              <p><span class="emphasis"><i class=
6589              "EMPHASIS">REQ_LAST_FIELD</i></span> Move to the last
6590              field.</p>
6591            </li>
6592
6593            <li>
6594              <p><span class="emphasis"><i class=
6595              "EMPHASIS">REQ_SNEXT_FIELD</i></span> Move to sorted
6596              next field.</p>
6597            </li>
6598
6599            <li>
6600              <p><span class="emphasis"><i class=
6601              "EMPHASIS">REQ_SPREV_FIELD</i></span> Move to sorted
6602              previous field.</p>
6603            </li>
6604
6605            <li>
6606              <p><span class="emphasis"><i class=
6607              "EMPHASIS">REQ_SFIRST_FIELD</i></span> Move to the
6608              sorted first field.</p>
6609            </li>
6610
6611            <li>
6612              <p><span class="emphasis"><i class=
6613              "EMPHASIS">REQ_SLAST_FIELD</i></span> Move to the
6614              sorted last field.</p>
6615            </li>
6616
6617            <li>
6618              <p><span class="emphasis"><i class=
6619              "EMPHASIS">REQ_LEFT_FIELD</i></span> Move left to
6620              field.</p>
6621            </li>
6622
6623            <li>
6624              <p><span class="emphasis"><i class=
6625              "EMPHASIS">REQ_RIGHT_FIELD</i></span> Move right to
6626              field.</p>
6627            </li>
6628
6629            <li>
6630              <p><span class="emphasis"><i class=
6631              "EMPHASIS">REQ_UP_FIELD</i></span> Move up to
6632              field.</p>
6633            </li>
6634
6635            <li>
6636              <p><span class="emphasis"><i class=
6637              "EMPHASIS">REQ_DOWN_FIELD</i></span> Move down to
6638              field.</p>
6639            </li>
6640          </ul>
6641
6642          <p>These requests treat the list of fields on a page as
6643          cyclic; that is, REQ_NEXT_FIELD from the last field goes
6644          to the first, and REQ_PREV_FIELD from the first field
6645          goes to the last. The order of the fields for these (and
6646          the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is
6647          simply the order of the field pointers in the form array
6648          (as set up by new_form() or set_form_fields()</p>
6649
6650          <p>It is also possible to traverse the fields as if they
6651          had been sorted in screen-position order, so the sequence
6652          goes left-to-right and top-to-bottom. To do this, use the
6653          second group of four sorted-movement requests.</p>
6654
6655          <p>Finally, it is possible to move between fields using
6656          visual directions up, down, right, and left. To
6657          accomplish this, use the third group of four requests.
6658          Note, however, that the position of a form for purposes
6659          of these requests is its upper-left corner.</p>
6660
6661          <p>For example, suppose you have a multi-line field B,
6662          and two single-line fields A and C on the same line with
6663          B, with A to the left of B and C to the right of B. A
6664          REQ_MOVE_RIGHT from A will go to B only if A, B, and C
6665          all share the same first line; otherwise it will skip
6666          over B to C.</p>
6667        </div>
6668
6669        <div class="SECT3">
6670          <hr>
6671
6672          <h4 class="SECT3"><a name="INTRAFIELDNAVREQ" id=
6673          "INTRAFIELDNAVREQ">18.6.3. Intra-Field Navigation
6674          Requests</a></h4>
6675
6676          <p>These requests drive movement of the edit cursor
6677          within the currently selected field.</p>
6678
6679          <ul>
6680            <li>
6681              <p><span class="emphasis"><i class=
6682              "EMPHASIS">REQ_NEXT_CHAR</i></span> Move to next
6683              character.</p>
6684            </li>
6685
6686            <li>
6687              <p><span class="emphasis"><i class=
6688              "EMPHASIS">REQ_PREV_CHAR</i></span> Move to previous
6689              character.</p>
6690            </li>
6691
6692            <li>
6693              <p><span class="emphasis"><i class=
6694              "EMPHASIS">REQ_NEXT_LINE</i></span> Move to next
6695              line.</p>
6696            </li>
6697
6698            <li>
6699              <p><span class="emphasis"><i class=
6700              "EMPHASIS">REQ_PREV_LINE</i></span> Move to previous
6701              line.</p>
6702            </li>
6703
6704            <li>
6705              <p><span class="emphasis"><i class=
6706              "EMPHASIS">REQ_NEXT_WORD</i></span> Move to next
6707              word.</p>
6708            </li>
6709
6710            <li>
6711              <p><span class="emphasis"><i class=
6712              "EMPHASIS">REQ_PREV_WORD</i></span> Move to previous
6713              word.</p>
6714            </li>
6715
6716            <li>
6717              <p><span class="emphasis"><i class=
6718              "EMPHASIS">REQ_BEG_FIELD</i></span> Move to beginning
6719              of field.</p>
6720            </li>
6721
6722            <li>
6723              <p><span class="emphasis"><i class=
6724              "EMPHASIS">REQ_END_FIELD</i></span> Move to end of
6725              field.</p>
6726            </li>
6727
6728            <li>
6729              <p><span class="emphasis"><i class=
6730              "EMPHASIS">REQ_BEG_LINE</i></span> Move to beginning
6731              of line.</p>
6732            </li>
6733
6734            <li>
6735              <p><span class="emphasis"><i class=
6736              "EMPHASIS">REQ_END_LINE</i></span> Move to end of
6737              line.</p>
6738            </li>
6739
6740            <li>
6741              <p><span class="emphasis"><i class=
6742              "EMPHASIS">REQ_LEFT_CHAR</i></span> Move left in
6743              field.</p>
6744            </li>
6745
6746            <li>
6747              <p><span class="emphasis"><i class=
6748              "EMPHASIS">REQ_RIGHT_CHAR</i></span> Move right in
6749              field.</p>
6750            </li>
6751
6752            <li>
6753              <p><span class="emphasis"><i class=
6754              "EMPHASIS">REQ_UP_CHAR</i></span> Move up in
6755              field.</p>
6756            </li>
6757
6758            <li>
6759              <p><span class="emphasis"><i class=
6760              "EMPHASIS">REQ_DOWN_CHAR</i></span> Move down in
6761              field.</p>
6762            </li>
6763          </ul>
6764
6765          <p>Each word is separated from the previous and next
6766          characters by whitespace. The commands to move to
6767          beginning and end of line or field look for the first or
6768          last non-pad character in their ranges.</p>
6769        </div>
6770
6771        <div class="SECT3">
6772          <hr>
6773
6774          <h4 class="SECT3"><a name="SCROLLREQ" id=
6775          "SCROLLREQ">18.6.4. Scrolling Requests</a></h4>
6776
6777          <p>Fields that are dynamic and have grown and fields
6778          explicitly created with offscreen rows are scrollable.
6779          One-line fields scroll horizontally; multi-line fields
6780          scroll vertically. Most scrolling is triggered by editing
6781          and intra-field movement (the library scrolls the field
6782          to keep the cursor visible). It is possible to explicitly
6783          request scrolling with the following requests:</p>
6784
6785          <ul>
6786            <li>
6787              <p><span class="emphasis"><i class=
6788              "EMPHASIS">REQ_SCR_FLINE</i></span> Scroll vertically
6789              forward a line.</p>
6790            </li>
6791
6792            <li>
6793              <p><span class="emphasis"><i class=
6794              "EMPHASIS">REQ_SCR_BLINE</i></span> Scroll vertically
6795              backward a line.</p>
6796            </li>
6797
6798            <li>
6799              <p><span class="emphasis"><i class=
6800              "EMPHASIS">REQ_SCR_FPAGE</i></span> Scroll vertically
6801              forward a page.</p>
6802            </li>
6803
6804            <li>
6805              <p><span class="emphasis"><i class=
6806              "EMPHASIS">REQ_SCR_BPAGE</i></span> Scroll vertically
6807              backward a page.</p>
6808            </li>
6809
6810            <li>
6811              <p><span class="emphasis"><i class=
6812              "EMPHASIS">REQ_SCR_FHPAGE</i></span> Scroll
6813              vertically forward half a page.</p>
6814            </li>
6815
6816            <li>
6817              <p><span class="emphasis"><i class=
6818              "EMPHASIS">REQ_SCR_BHPAGE</i></span> Scroll
6819              vertically backward half a page.</p>
6820            </li>
6821
6822            <li>
6823              <p><span class="emphasis"><i class=
6824              "EMPHASIS">REQ_SCR_FCHAR</i></span> Scroll
6825              horizontally forward a character.</p>
6826            </li>
6827
6828            <li>
6829              <p><span class="emphasis"><i class=
6830              "EMPHASIS">REQ_SCR_BCHAR</i></span> Scroll
6831              horizontally backward a character.</p>
6832            </li>
6833
6834            <li>
6835              <p><span class="emphasis"><i class=
6836              "EMPHASIS">REQ_SCR_HFLINE</i></span> Scroll
6837              horizontally one field width forward.</p>
6838            </li>
6839
6840            <li>
6841              <p><span class="emphasis"><i class=
6842              "EMPHASIS">REQ_SCR_HBLINE</i></span> Scroll
6843              horizontally one field width backward.</p>
6844            </li>
6845
6846            <li>
6847              <p><span class="emphasis"><i class=
6848              "EMPHASIS">REQ_SCR_HFHALF</i></span> Scroll
6849              horizontally one half field width forward.</p>
6850            </li>
6851
6852            <li>
6853              <p><span class="emphasis"><i class=
6854              "EMPHASIS">REQ_SCR_HBHALF</i></span> Scroll
6855              horizontally one half field width backward.</p>
6856            </li>
6857          </ul>
6858
6859          <p>For scrolling purposes, a page of a field is the
6860          height of its visible part.</p>
6861        </div>
6862
6863        <div class="SECT3">
6864          <hr>
6865
6866          <h4 class="SECT3"><a name="EDITREQ" id="EDITREQ">18.6.5.
6867          Editing Requests</a></h4>
6868
6869          <p>When you pass the forms driver an ASCII character, it
6870          is treated as a request to add the character to the
6871          field's data buffer. Whether this is an insertion or a
6872          replacement depends on the field's edit mode (insertion
6873          is the default.</p>
6874
6875          <p>The following requests support editing the field and
6876          changing the edit mode:</p>
6877
6878          <ul>
6879            <li>
6880              <p><span class="emphasis"><i class=
6881              "EMPHASIS">REQ_INS_MODE</i></span> Set insertion
6882              mode.</p>
6883            </li>
6884
6885            <li>
6886              <p><span class="emphasis"><i class=
6887              "EMPHASIS">REQ_OVL_MODE</i></span> Set overlay
6888              mode.</p>
6889            </li>
6890
6891            <li>
6892              <p><span class="emphasis"><i class=
6893              "EMPHASIS">REQ_NEW_LINE</i></span> New line request
6894              (see below for explanation).</p>
6895            </li>
6896
6897            <li>
6898              <p><span class="emphasis"><i class=
6899              "EMPHASIS">REQ_INS_CHAR</i></span> Insert space at
6900              character location.</p>
6901            </li>
6902
6903            <li>
6904              <p><span class="emphasis"><i class=
6905              "EMPHASIS">REQ_INS_LINE</i></span> Insert blank line
6906              at character location.</p>
6907            </li>
6908
6909            <li>
6910              <p><span class="emphasis"><i class=
6911              "EMPHASIS">REQ_DEL_CHAR</i></span> Delete character
6912              at cursor.</p>
6913            </li>
6914
6915            <li>
6916              <p><span class="emphasis"><i class=
6917              "EMPHASIS">REQ_DEL_PREV</i></span> Delete previous
6918              word at cursor.</p>
6919            </li>
6920
6921            <li>
6922              <p><span class="emphasis"><i class=
6923              "EMPHASIS">REQ_DEL_LINE</i></span> Delete line at
6924              cursor.</p>
6925            </li>
6926
6927            <li>
6928              <p><span class="emphasis"><i class=
6929              "EMPHASIS">REQ_DEL_WORD</i></span> Delete word at
6930              cursor.</p>
6931            </li>
6932
6933            <li>
6934              <p><span class="emphasis"><i class=
6935              "EMPHASIS">REQ_CLR_EOL</i></span> Clear to end of
6936              line.</p>
6937            </li>
6938
6939            <li>
6940              <p><span class="emphasis"><i class=
6941              "EMPHASIS">REQ_CLR_EOF</i></span> Clear to end of
6942              field.</p>
6943            </li>
6944
6945            <li>
6946              <p><span class="emphasis"><i class=
6947              "EMPHASIS">REQ_CLR_FIELD</i></span> Clear entire
6948              field.</p>
6949            </li>
6950          </ul>
6951
6952          <p>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV
6953          requests is complicated and partly controlled by a pair
6954          of forms options. The special cases are triggered when
6955          the cursor is at the beginning of a field, or on the last
6956          line of the field.</p>
6957
6958          <p>First, we consider REQ_NEW_LINE:</p>
6959
6960          <p>The normal behavior of REQ_NEW_LINE in insert mode is
6961          to break the current line at the position of the edit
6962          cursor, inserting the portion of the current line after
6963          the cursor as a new line following the current and moving
6964          the cursor to the beginning of that new line (you may
6965          think of this as inserting a newline in the field
6966          buffer).</p>
6967
6968          <p>The normal behavior of REQ_NEW_LINE in overlay mode is
6969          to clear the current line from the position of the edit
6970          cursor to end of line. The cursor is then moved to the
6971          beginning of the next line.</p>
6972
6973          <p>However, REQ_NEW_LINE at the beginning of a field, or
6974          on the last line of a field, instead does a
6975          REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this special
6976          action is disabled.</p>
6977
6978          <p>Now, let us consider REQ_DEL_PREV:</p>
6979
6980          <p>The normal behavior of REQ_DEL_PREV is to delete the
6981          previous character. If insert mode is on, and the cursor
6982          is at the start of a line, and the text on that line will
6983          fit on the previous one, it instead appends the contents
6984          of the current line to the previous one and deletes the
6985          current line (you may think of this as deleting a newline
6986          from the field buffer).</p>
6987
6988          <p>However, REQ_DEL_PREV at the beginning of a field is
6989          instead treated as a REQ_PREV_FIELD.</p>
6990
6991          <p>If the O_BS_OVERLOAD option is off, this special
6992          action is disabled and the forms driver just returns
6993          E_REQUEST_DENIED.</p>
6994        </div>
6995
6996        <div class="SECT3">
6997          <hr>
6998
6999          <h4 class="SECT3"><a name="ORDERREQ" id=
7000          "ORDERREQ">18.6.6. Order Requests</a></h4>
7001
7002          <p>If the type of your field is ordered, and has
7003          associated functions for getting the next and previous
7004          values of the type from a given value, there are requests
7005          that can fetch that value into the field buffer:</p>
7006
7007          <ul>
7008            <li>
7009              <p><span class="emphasis"><i class=
7010              "EMPHASIS">REQ_NEXT_CHOICE</i></span> Place the
7011              successor value of the current value in the
7012              buffer.</p>
7013            </li>
7014
7015            <li>
7016              <p><span class="emphasis"><i class=
7017              "EMPHASIS">REQ_PREV_CHOICE</i></span> Place the
7018              predecessor value of the current value in the
7019              buffer.</p>
7020            </li>
7021          </ul>
7022
7023          <p>Of the built-in field types, only TYPE_ENUM has
7024          built-in successor and predecessor functions. When you
7025          define a field type of your own (see Custom Validation
7026          Types), you can associate our own ordering functions.</p>
7027        </div>
7028
7029        <div class="SECT3">
7030          <hr>
7031
7032          <h4 class="SECT3"><a name="APPLICCOMMANDS" id=
7033          "APPLICCOMMANDS">18.6.7. Application Commands</a></h4>
7034
7035          <p>Form requests are represented as integers above the
7036          curses value greater than KEY_MAX and less than or equal
7037          to the constant MAX_COMMAND. A value within this range
7038          gets ignored by form_driver(). So this can be used for
7039          any purpose by the application. It can be treated as an
7040          application specific action and take corresponding
7041          action.</p>
7042        </div>
7043      </div>
7044    </div>
7045
7046    <div class="SECT1">
7047      <hr>
7048
7049      <h2 class="SECT1"><a name="TOOLS" id="TOOLS">19. Tools and
7050      Widget Libraries</a></h2>
7051
7052      <p>Now that you have seen the capabilities of ncurses and its
7053      sister libraries, you are rolling your sleeves up and gearing
7054      for a project that heavily manipulates screen. But wait.. It
7055      can be pretty difficult to write and maintain complex GUI
7056      widgets in plain ncurses or even with the additional
7057      libraries. There are some ready-to-use tools and widget
7058      libraries that can be used instead of writing your own
7059      widgets. You can use some of them, get ideas from the code,
7060      or even extend them.</p>
7061
7062      <div class="SECT2">
7063        <hr>
7064
7065        <h3 class="SECT2"><a name="CDK" id="CDK">19.1. CDK (Curses
7066        Development Kit)</a></h3>
7067
7068        <p>In the author's words</p>
7069
7070        <p><span class="emphasis"><i class="EMPHASIS">CDK stands
7071        for 'Curses Development Kit' and it currently contains 21
7072        ready to use widgets which facilitate the speedy
7073        development of full screen curses programs.</i></span></p>
7074
7075        <p>The kit provides some useful widgets, which can be used
7076        in your programs directly. It's pretty well written and the
7077        documentation is very good. The examples in the examples
7078        directory can be a good place to start for beginners. The
7079        CDK can be downloaded from <a href=
7080        "https://invisible-island.net/cdk/" target=
7081        "_top">https://invisible-island.net/cdk/</a> . Follow the
7082        instructions in README file to install it.</p>
7083
7084        <div class="SECT3">
7085          <hr>
7086
7087          <h4 class="SECT3"><a name="WIDGETLIST" id=
7088          "WIDGETLIST">19.1.1. Widget List</a></h4>
7089
7090          <p>The following is the list of widgets provided with cdk
7091          and their description.</p>
7092          <pre class="PROGRAMLISTING">
7093Widget Type           Quick Description
7094===========================================================================
7095Alphalist             Allows a user to select from a list of words, with
7096                      the ability to narrow the search list by typing in a
7097                      few characters of the desired word.
7098Buttonbox             This creates a multiple button widget.
7099Calendar              Creates a little simple calendar widget.
7100Dialog                Prompts the user with a message, and the user
7101                      can pick an answer from the buttons provided.
7102Entry                 Allows the user to enter various types of information.
7103File Selector         A file selector built from Cdk base widgets. This
7104                      example shows how to create more complicated widgets
7105                      using the Cdk widget library.
7106Graph                 Draws a graph.
7107Histogram             Draws a histogram.
7108Item List             Creates a pop up field which allows the user to select
7109                      one of several choices in a small field. Very useful
7110                      for things like days of the week or month names.
7111Label                 Displays messages in a pop up box, or the label can be
7112                      considered part of the screen.
7113Marquee               Displays a message in a scrolling marquee.
7114Matrix                Creates a complex matrix with lots of options.
7115Menu                  Creates a pull-down menu interface.
7116Multiple Line Entry   A multiple line entry field. Very useful
7117                      for long fields. (like a description
7118                      field)
7119Radio List            Creates a radio button list.
7120Scale                 Creates a numeric scale. Used for allowing a user to
7121                      pick a numeric value and restrict them to a range of
7122                      values.
7123Scrolling List        Creates a scrolling list/menu list.
7124Scrolling Window      Creates a scrolling log file viewer. Can add
7125                      information into the window while its running.
7126                      A good widget for displaying the progress of
7127                      something. (akin to a console window)
7128Selection List        Creates a multiple option selection list.
7129Slider                Akin to the scale widget, this widget provides a
7130                      visual slide bar to represent the numeric value.
7131Template              Creates a entry field with character sensitive
7132                      positions. Used for pre-formatted fields like
7133                      dates and phone numbers.
7134Viewer                This is a file/information viewer. Very useful
7135                      when you need to display loads of information.
7136===========================================================================
7137</pre>
7138
7139          <p>A few of the widgets are modified by Thomas Dickey in
7140          recent versions.</p>
7141        </div>
7142
7143        <div class="SECT3">
7144          <hr>
7145
7146          <h4 class="SECT3"><a name="CDKATTRACT" id=
7147          "CDKATTRACT">19.1.2. Some Attractive Features</a></h4>
7148
7149          <p>Apart from making our life easier with readily usable
7150          widgets, cdk solves one frustrating problem with printing
7151          multi colored strings, justified strings elegantly.
7152          Special formatting tags can be embedded in the strings
7153          which are passed to CDK functions. For Example</p>
7154
7155          <p>If the string</p>
7156          <pre class="PROGRAMLISTING">
7157"&lt;/B/1&gt;This line should have a yellow foreground and a blue
7158background.&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="https://invisible-island.net/dialog/" target=
7208        "_top">Thomas Dickey</a>'s site.</p>
7209
7210        <p>The above-mentioned article gives a very good overview
7211        of its uses and capabilites. The man page has more details.
7212        It can be used in variety of situations. One good example
7213        is building of linux kernel in text mode. Linux kernel uses
7214        a modified version of dialog tailored for its needs.</p>
7215
7216        <p>dialog was initially designed to be used with shell
7217        scripts. If you want to use its functionality in a c
7218        program, then you can use libdialog. The documentation
7219        regarding this is sparse. Definitive reference is the
7220        dialog.h header file which comes with the library. You may
7221        need to hack here and there to get the required output. The
7222        source is easily customizable. I have used it on a number
7223        of occasions by modifying the code.</p>
7224      </div>
7225
7226      <div class="SECT2">
7227        <hr>
7228
7229        <h3 class="SECT2"><a name="PERLCURSES" id=
7230        "PERLCURSES">19.3. Perl Curses Modules CURSES::FORM and
7231        CURSES::WIDGETS</a></h3>
7232
7233        <p>The perl module Curses, Curses::Form and Curses::Widgets
7234        give access to curses from perl. If you have curses and
7235        basic perl is installed, you can get these modules from
7236        <a href="http://www.cpan.org/modules/01modules.index.html"
7237        target="_top">CPAN All Modules page</a>. Get the three
7238        zipped modules in the Curses category. Once installed you
7239        can use these modules from perl scripts like any other
7240        module. For more information on perl modules see perlmod
7241        man page. The above modules come with good documentation
7242        and they have some demo scripts to test the functionality.
7243        Though the widgets provided are very rudimentary, these
7244        modules provide good access to curses library from
7245        perl.</p>
7246
7247        <p>Some of my code examples are converted to perl by
7248        Anuradha Ratnaweera and they are available in the
7249        <tt class="LITERAL">perl</tt> directory.</p>
7250
7251        <p>For more information see man pages Curses(3) ,
7252        Curses::Form(3) and Curses::Widgets(3). These pages are
7253        installed only when the above modules are acquired and
7254        installed.</p>
7255      </div>
7256    </div>
7257
7258    <div class="SECT1">
7259      <hr>
7260
7261      <h2 class="SECT1"><a name="JUSTFORFUN" id="JUSTFORFUN">20.
7262      Just For Fun !!!</a></h2>
7263
7264      <p>This section contains few programs written by me just for
7265      fun. They don't signify a better programming practice or the
7266      best way of using ncurses. They are provided here so as to
7267      allow beginners to get ideas and add more programs to this
7268      section. If you have written a couple of nice, simple
7269      programs in curses and want them to included here, contact
7270      <a href="mailto: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
7284are no players, and no winning or losing. Once the "pieces" are placed in the
7285starting position, the rules determine everything that happens later.
7286Nevertheless, Life is full of surprises! In most cases, it is impossible to look
7287at a starting position (or pattern) and see what will happen in the future. The
7288only way to find out is to follow the rules of the game.</i></span>
7289</pre>
7290
7291        <p>This program starts with a simple inverted U pattern and
7292        shows how wonderful life works. There is a lot of room for
7293        improvement in the program. You can let the user enter
7294        pattern of his choice or even take input from a file. You
7295        can also change rules and play with a lot of variations.
7296        Search on <a href="http://www.google.com" target=
7297        "_top">google</a> for interesting information on game of
7298        life.</p>
7299
7300        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7301        JustForFun/life.c</i></span></p>
7302      </div>
7303
7304      <div class="SECT2">
7305        <hr>
7306
7307        <h3 class="SECT2"><a name="MAGIC" id="MAGIC">20.2. Magic
7308        Square</a></h3>
7309
7310        <p>Magic Square, another wonder of math, is very simple to
7311        understand but very difficult to make. In a magic square
7312        sum of the numbers in each row, each column is equal. Even
7313        diagnol sum can be equal. There are many variations which
7314        have special properties.</p>
7315
7316        <p>This program creates a simple magic square of odd
7317        order.</p>
7318
7319        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7320        JustForFun/magic.c</i></span></p>
7321      </div>
7322
7323      <div class="SECT2">
7324        <hr>
7325
7326        <h3 class="SECT2"><a name="HANOI" id="HANOI">20.3. Towers
7327        of Hanoi</a></h3>
7328
7329        <p>The famous towers of hanoi solver. The aim of the game
7330        is to move the disks on the first peg to last peg, using
7331        middle peg as a temporary stay. The catch is not to place a
7332        larger disk over a small disk at any time.</p>
7333
7334        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7335        JustForFun/hanoi.c</i></span></p>
7336      </div>
7337
7338      <div class="SECT2">
7339        <hr>
7340
7341        <h3 class="SECT2"><a name="QUEENS" id="QUEENS">20.4. Queens
7342        Puzzle</a></h3>
7343
7344        <p>The objective of the famous N-Queen puzzle is to put N
7345        queens on a N X N chess board without attacking each
7346        other.</p>
7347
7348        <p>This program solves it with a simple backtracking
7349        technique.</p>
7350
7351        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7352        JustForFun/queens.c</i></span></p>
7353      </div>
7354
7355      <div class="SECT2">
7356        <hr>
7357
7358        <h3 class="SECT2"><a name="SHUFFLE" id="SHUFFLE">20.5.
7359        Shuffle</a></h3>
7360
7361        <p>A fun game, if you have time to kill.</p>
7362
7363        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7364        JustForFun/shuffle.c</i></span></p>
7365      </div>
7366
7367      <div class="SECT2">
7368        <hr>
7369
7370        <h3 class="SECT2"><a name="TT" id="TT">20.6. Typing
7371        Tutor</a></h3>
7372
7373        <p>A simple typing tutor, I created more out of need than
7374        for ease of use. If you know how to put your fingers
7375        correctly on the keyboard, but lack practice, this can be
7376        helpful.</p>
7377
7378        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7379        JustForFun/tt.c</i></span></p>
7380      </div>
7381    </div>
7382
7383    <div class="SECT1">
7384      <hr>
7385
7386      <h2 class="SECT1"><a name="REF" id="REF">21.
7387      References</a></h2>
7388
7389      <ul>
7390        <li>
7391          <p>NCURSES man pages</p>
7392        </li>
7393
7394        <li>
7395          <p>NCURSES FAQ at <a href=
7396          "https://invisible-island.net/ncurses/ncurses.faq.html"
7397          target=
7398          "_top">https://invisible-island.net/ncurses/ncurses.faq.html</a></p>
7399        </li>
7400
7401        <li>
7402          <p>Writing programs with NCURSES by Eric Raymond and Zeyd
7403          M. Ben-Halim at <a href=
7404          "https://invisible-island.net/ncurses/ncurses-intro.html"
7405          target=
7406          "_top">https://invisible-island.net/ncurses/ncurses-intro.html</a>
7407          - somewhat obsolete. I was inspired by this document and
7408          the structure of this HOWTO follows from the original
7409          document</p>
7410        </li>
7411      </ul>
7412    </div>
7413  </div>
7414</body>
7415</html>
7416