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