1*4a1a9510SRong-En Fan<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
2*4a1a9510SRong-En Fan"http://www.w3.org/TR/html4/strict.dtd">
3*4a1a9510SRong-En Fan
4*4a1a9510SRong-En Fan<html>
5*4a1a9510SRong-En Fan<head>
6*4a1a9510SRong-En Fan  <meta name="generator" content=
7*4a1a9510SRong-En Fan  "HTML Tidy for Linux (vers 25 March 2009), see www.w3.org">
8*4a1a9510SRong-En Fan
9*4a1a9510SRong-En Fan  <title>NCURSES Programming HOWTO</title>
10*4a1a9510SRong-En Fan  <meta name="GENERATOR" content=
11*4a1a9510SRong-En Fan  "Modular DocBook HTML Stylesheet Version 1.79">
12*4a1a9510SRong-En Fan</head>
13*4a1a9510SRong-En Fan
14*4a1a9510SRong-En Fan<body class="ARTICLE" bgcolor="#FFFFFF" text="#000000" link=
15*4a1a9510SRong-En Fan"#0000FF" vlink="#840084" alink="#0000FF">
16*4a1a9510SRong-En Fan  <div class="ARTICLE">
17*4a1a9510SRong-En Fan    <div class="TITLEPAGE">
18*4a1a9510SRong-En Fan      <h1 class="TITLE"><a name="AEN2" id="AEN2">NCURSES
19*4a1a9510SRong-En Fan      Programming HOWTO</a></h1>
20*4a1a9510SRong-En Fan
21*4a1a9510SRong-En Fan      <h3 class="AUTHOR"><a name="AEN4" id="AEN4">Pradeep
22*4a1a9510SRong-En Fan      Padala</a></h3>
23*4a1a9510SRong-En Fan
24*4a1a9510SRong-En Fan      <div class="AFFILIATION">
25*4a1a9510SRong-En Fan        <div class="ADDRESS">
26*4a1a9510SRong-En Fan          <p class="ADDRESS"><code class="EMAIL">&lt;<a href=
27*4a1a9510SRong-En Fan          "mailto:[email protected]">[email protected]</a>&gt;</code></p>
28*4a1a9510SRong-En Fan        </div>
29*4a1a9510SRong-En Fan      </div>
30*4a1a9510SRong-En Fan
31*4a1a9510SRong-En Fan      <p class="PUBDATE">v1.9, 2005-06-20<br></p>
32*4a1a9510SRong-En Fan
33*4a1a9510SRong-En Fan      <div class="REVHISTORY">
34*4a1a9510SRong-En Fan        <table width="100%" border="0" summary="revisions">
35*4a1a9510SRong-En Fan          <tr>
36*4a1a9510SRong-En Fan            <th align="left" valign="top" colspan="3"><b>Revision
37*4a1a9510SRong-En Fan            History</b></th>
38*4a1a9510SRong-En Fan          </tr>
39*4a1a9510SRong-En Fan
40*4a1a9510SRong-En Fan          <tr>
41*4a1a9510SRong-En Fan            <td align="left">Revision 1.9</td>
42*4a1a9510SRong-En Fan
43*4a1a9510SRong-En Fan            <td align="left">2005-06-20</td>
44*4a1a9510SRong-En Fan
45*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
46*4a1a9510SRong-En Fan          </tr>
47*4a1a9510SRong-En Fan
48*4a1a9510SRong-En Fan          <tr>
49*4a1a9510SRong-En Fan            <td align="left" colspan="3">The license has been
50*4a1a9510SRong-En Fan            changed to the MIT-style license used by NCURSES. Note
51*4a1a9510SRong-En Fan            that the programs are also re-licensed under this.</td>
52*4a1a9510SRong-En Fan          </tr>
53*4a1a9510SRong-En Fan
54*4a1a9510SRong-En Fan          <tr>
55*4a1a9510SRong-En Fan            <td align="left">Revision 1.8</td>
56*4a1a9510SRong-En Fan
57*4a1a9510SRong-En Fan            <td align="left">2005-06-17</td>
58*4a1a9510SRong-En Fan
59*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
60*4a1a9510SRong-En Fan          </tr>
61*4a1a9510SRong-En Fan
62*4a1a9510SRong-En Fan          <tr>
63*4a1a9510SRong-En Fan            <td align="left" colspan="3">Lots of updates. Added
64*4a1a9510SRong-En Fan            references and perl examples. Changes to examples. Many
65*4a1a9510SRong-En Fan            grammatical and stylistic changes to the content.
66*4a1a9510SRong-En Fan            Changes to NCURSES history.</td>
67*4a1a9510SRong-En Fan          </tr>
68*4a1a9510SRong-En Fan
69*4a1a9510SRong-En Fan          <tr>
70*4a1a9510SRong-En Fan            <td align="left">Revision 1.7.1</td>
71*4a1a9510SRong-En Fan
72*4a1a9510SRong-En Fan            <td align="left">2002-06-25</td>
73*4a1a9510SRong-En Fan
74*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
75*4a1a9510SRong-En Fan          </tr>
76*4a1a9510SRong-En Fan
77*4a1a9510SRong-En Fan          <tr>
78*4a1a9510SRong-En Fan            <td align="left" colspan="3">Added a README file for
79*4a1a9510SRong-En Fan            building and instructions for building from
80*4a1a9510SRong-En Fan            source.</td>
81*4a1a9510SRong-En Fan          </tr>
82*4a1a9510SRong-En Fan
83*4a1a9510SRong-En Fan          <tr>
84*4a1a9510SRong-En Fan            <td align="left">Revision 1.7</td>
85*4a1a9510SRong-En Fan
86*4a1a9510SRong-En Fan            <td align="left">2002-06-25</td>
87*4a1a9510SRong-En Fan
88*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
89*4a1a9510SRong-En Fan          </tr>
90*4a1a9510SRong-En Fan
91*4a1a9510SRong-En Fan          <tr>
92*4a1a9510SRong-En Fan            <td align="left" colspan="3">Added "Other formats"
93*4a1a9510SRong-En Fan            section and made a lot of fancy changes to the
94*4a1a9510SRong-En Fan            programs. Inlining of programs is gone.</td>
95*4a1a9510SRong-En Fan          </tr>
96*4a1a9510SRong-En Fan
97*4a1a9510SRong-En Fan          <tr>
98*4a1a9510SRong-En Fan            <td align="left">Revision 1.6.1</td>
99*4a1a9510SRong-En Fan
100*4a1a9510SRong-En Fan            <td align="left">2002-02-24</td>
101*4a1a9510SRong-En Fan
102*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
103*4a1a9510SRong-En Fan          </tr>
104*4a1a9510SRong-En Fan
105*4a1a9510SRong-En Fan          <tr>
106*4a1a9510SRong-En Fan            <td align="left" colspan="3">Removed the old Changelog
107*4a1a9510SRong-En Fan            section, cleaned the makefiles</td>
108*4a1a9510SRong-En Fan          </tr>
109*4a1a9510SRong-En Fan
110*4a1a9510SRong-En Fan          <tr>
111*4a1a9510SRong-En Fan            <td align="left">Revision 1.6</td>
112*4a1a9510SRong-En Fan
113*4a1a9510SRong-En Fan            <td align="left">2002-02-16</td>
114*4a1a9510SRong-En Fan
115*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
116*4a1a9510SRong-En Fan          </tr>
117*4a1a9510SRong-En Fan
118*4a1a9510SRong-En Fan          <tr>
119*4a1a9510SRong-En Fan            <td align="left" colspan="3">Corrected a lot of
120*4a1a9510SRong-En Fan            spelling mistakes, added ACS variables section</td>
121*4a1a9510SRong-En Fan          </tr>
122*4a1a9510SRong-En Fan
123*4a1a9510SRong-En Fan          <tr>
124*4a1a9510SRong-En Fan            <td align="left">Revision 1.5</td>
125*4a1a9510SRong-En Fan
126*4a1a9510SRong-En Fan            <td align="left">2002-01-05</td>
127*4a1a9510SRong-En Fan
128*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
129*4a1a9510SRong-En Fan          </tr>
130*4a1a9510SRong-En Fan
131*4a1a9510SRong-En Fan          <tr>
132*4a1a9510SRong-En Fan            <td align="left" colspan="3">Changed structure to
133*4a1a9510SRong-En Fan            present proper TOC</td>
134*4a1a9510SRong-En Fan          </tr>
135*4a1a9510SRong-En Fan
136*4a1a9510SRong-En Fan          <tr>
137*4a1a9510SRong-En Fan            <td align="left">Revision 1.3.1</td>
138*4a1a9510SRong-En Fan
139*4a1a9510SRong-En Fan            <td align="left">2001-07-26</td>
140*4a1a9510SRong-En Fan
141*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
142*4a1a9510SRong-En Fan          </tr>
143*4a1a9510SRong-En Fan
144*4a1a9510SRong-En Fan          <tr>
145*4a1a9510SRong-En Fan            <td align="left" colspan="3">Corrected maintainers
146*4a1a9510SRong-En Fan            paragraph, Corrected stable release number</td>
147*4a1a9510SRong-En Fan          </tr>
148*4a1a9510SRong-En Fan
149*4a1a9510SRong-En Fan          <tr>
150*4a1a9510SRong-En Fan            <td align="left">Revision 1.3</td>
151*4a1a9510SRong-En Fan
152*4a1a9510SRong-En Fan            <td align="left">2001-07-24</td>
153*4a1a9510SRong-En Fan
154*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
155*4a1a9510SRong-En Fan          </tr>
156*4a1a9510SRong-En Fan
157*4a1a9510SRong-En Fan          <tr>
158*4a1a9510SRong-En Fan            <td align="left" colspan="3">Added copyright notices to
159*4a1a9510SRong-En Fan            main document (LDP license) and programs (GPL),
160*4a1a9510SRong-En Fan            Corrected printw_example.</td>
161*4a1a9510SRong-En Fan          </tr>
162*4a1a9510SRong-En Fan
163*4a1a9510SRong-En Fan          <tr>
164*4a1a9510SRong-En Fan            <td align="left">Revision 1.2</td>
165*4a1a9510SRong-En Fan
166*4a1a9510SRong-En Fan            <td align="left">2001-06-05</td>
167*4a1a9510SRong-En Fan
168*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
169*4a1a9510SRong-En Fan          </tr>
170*4a1a9510SRong-En Fan
171*4a1a9510SRong-En Fan          <tr>
172*4a1a9510SRong-En Fan            <td align="left" colspan="3">Incorporated ravi's
173*4a1a9510SRong-En Fan            changes. Mainly to introduction, menu, form, justforfun
174*4a1a9510SRong-En Fan            sections</td>
175*4a1a9510SRong-En Fan          </tr>
176*4a1a9510SRong-En Fan
177*4a1a9510SRong-En Fan          <tr>
178*4a1a9510SRong-En Fan            <td align="left">Revision 1.1</td>
179*4a1a9510SRong-En Fan
180*4a1a9510SRong-En Fan            <td align="left">2001-05-22</td>
181*4a1a9510SRong-En Fan
182*4a1a9510SRong-En Fan            <td align="left">Revised by: ppadala</td>
183*4a1a9510SRong-En Fan          </tr>
184*4a1a9510SRong-En Fan
185*4a1a9510SRong-En Fan          <tr>
186*4a1a9510SRong-En Fan            <td align="left" colspan="3">Added "a word about
187*4a1a9510SRong-En Fan            window" section, Added scanw_example.</td>
188*4a1a9510SRong-En Fan          </tr>
189*4a1a9510SRong-En Fan        </table>
190*4a1a9510SRong-En Fan      </div>
191*4a1a9510SRong-En Fan
192*4a1a9510SRong-En Fan      <div>
193*4a1a9510SRong-En Fan        <div class="ABSTRACT">
194*4a1a9510SRong-En Fan          <a name="AEN67" id="AEN67"></a>
195*4a1a9510SRong-En Fan
196*4a1a9510SRong-En Fan          <p><span class="emphasis"><i class="EMPHASIS">This
197*4a1a9510SRong-En Fan          document is intended to be an "All in One" guide for
198*4a1a9510SRong-En Fan          programming with ncurses and its sister libraries. We
199*4a1a9510SRong-En Fan          graduate from a simple "Hello World" program to more
200*4a1a9510SRong-En Fan          complex form manipulation. No prior experience in ncurses
201*4a1a9510SRong-En Fan          is assumed. Send comments to <a href=
202*4a1a9510SRong-En Fan          "mailto:[email protected]" target="_top">this
203*4a1a9510SRong-En Fan          address</a></i></span></p>
204*4a1a9510SRong-En Fan        </div>
205*4a1a9510SRong-En Fan      </div>
206*4a1a9510SRong-En Fan      <hr>
207*4a1a9510SRong-En Fan    </div>
208*4a1a9510SRong-En Fan
209*4a1a9510SRong-En Fan    <div class="TOC">
210*4a1a9510SRong-En Fan      <dl>
211*4a1a9510SRong-En Fan        <dt><b>Table of Contents</b></dt>
212*4a1a9510SRong-En Fan
213*4a1a9510SRong-En Fan        <dt>1. <a href="#INTRO">Introduction</a></dt>
214*4a1a9510SRong-En Fan
215*4a1a9510SRong-En Fan        <dd>
216*4a1a9510SRong-En Fan          <dl>
217*4a1a9510SRong-En Fan            <dt>1.1. <a href="#WHATIS">What is NCURSES?</a></dt>
218*4a1a9510SRong-En Fan
219*4a1a9510SRong-En Fan            <dt>1.2. <a href="#WHATCANWEDO">What we can do with
220*4a1a9510SRong-En Fan            NCURSES</a></dt>
221*4a1a9510SRong-En Fan
222*4a1a9510SRong-En Fan            <dt>1.3. <a href="#WHERETOGETIT">Where to get
223*4a1a9510SRong-En Fan            it</a></dt>
224*4a1a9510SRong-En Fan
225*4a1a9510SRong-En Fan            <dt>1.4. <a href="#PURPOSE">Purpose/Scope of the
226*4a1a9510SRong-En Fan            document</a></dt>
227*4a1a9510SRong-En Fan
228*4a1a9510SRong-En Fan            <dt>1.5. <a href="#ABOUTPROGRAMS">About the
229*4a1a9510SRong-En Fan            Programs</a></dt>
230*4a1a9510SRong-En Fan
231*4a1a9510SRong-En Fan            <dt>1.6. <a href="#OTHERFORMATS">Other Formats of the
232*4a1a9510SRong-En Fan            document</a></dt>
233*4a1a9510SRong-En Fan
234*4a1a9510SRong-En Fan            <dd>
235*4a1a9510SRong-En Fan              <dl>
236*4a1a9510SRong-En Fan                <dt>1.6.1. <a href="#LISTFORMATS">Readily available
237*4a1a9510SRong-En Fan                formats from tldp.org</a></dt>
238*4a1a9510SRong-En Fan
239*4a1a9510SRong-En Fan                <dt>1.6.2. <a href="#BUILDSOURCE">Building from
240*4a1a9510SRong-En Fan                source</a></dt>
241*4a1a9510SRong-En Fan              </dl>
242*4a1a9510SRong-En Fan            </dd>
243*4a1a9510SRong-En Fan
244*4a1a9510SRong-En Fan            <dt>1.7. <a href="#CREDITS">Credits</a></dt>
245*4a1a9510SRong-En Fan
246*4a1a9510SRong-En Fan            <dt>1.8. <a href="#WISHLIST">Wish List</a></dt>
247*4a1a9510SRong-En Fan
248*4a1a9510SRong-En Fan            <dt>1.9. <a href="#COPYRIGHT">Copyright</a></dt>
249*4a1a9510SRong-En Fan          </dl>
250*4a1a9510SRong-En Fan        </dd>
251*4a1a9510SRong-En Fan
252*4a1a9510SRong-En Fan        <dt>2. <a href="#HELLOWORLD">Hello World !!!</a></dt>
253*4a1a9510SRong-En Fan
254*4a1a9510SRong-En Fan        <dd>
255*4a1a9510SRong-En Fan          <dl>
256*4a1a9510SRong-En Fan            <dt>2.1. <a href="#COMPILECURSES">Compiling With the
257*4a1a9510SRong-En Fan            NCURSES Library</a></dt>
258*4a1a9510SRong-En Fan
259*4a1a9510SRong-En Fan            <dt>2.2. <a href="#DISSECTION">Dissection</a></dt>
260*4a1a9510SRong-En Fan
261*4a1a9510SRong-En Fan            <dd>
262*4a1a9510SRong-En Fan              <dl>
263*4a1a9510SRong-En Fan                <dt>2.2.1. <a href="#ABOUT-INITSCR">About
264*4a1a9510SRong-En Fan                initscr()</a></dt>
265*4a1a9510SRong-En Fan
266*4a1a9510SRong-En Fan                <dt>2.2.2. <a href="#MYST-REFRESH">The mysterious
267*4a1a9510SRong-En Fan                refresh()</a></dt>
268*4a1a9510SRong-En Fan
269*4a1a9510SRong-En Fan                <dt>2.2.3. <a href="#ABOUT-ENDWIN">About
270*4a1a9510SRong-En Fan                endwin()</a></dt>
271*4a1a9510SRong-En Fan              </dl>
272*4a1a9510SRong-En Fan            </dd>
273*4a1a9510SRong-En Fan          </dl>
274*4a1a9510SRong-En Fan        </dd>
275*4a1a9510SRong-En Fan
276*4a1a9510SRong-En Fan        <dt>3. <a href="#GORY">The Gory Details</a></dt>
277*4a1a9510SRong-En Fan
278*4a1a9510SRong-En Fan        <dt>4. <a href="#INIT">Initialization</a></dt>
279*4a1a9510SRong-En Fan
280*4a1a9510SRong-En Fan        <dd>
281*4a1a9510SRong-En Fan          <dl>
282*4a1a9510SRong-En Fan            <dt>4.1. <a href="#ABOUTINIT">Initialization
283*4a1a9510SRong-En Fan            functions</a></dt>
284*4a1a9510SRong-En Fan
285*4a1a9510SRong-En Fan            <dt>4.2. <a href="#RAWCBREAK">raw() and
286*4a1a9510SRong-En Fan            cbreak()</a></dt>
287*4a1a9510SRong-En Fan
288*4a1a9510SRong-En Fan            <dt>4.3. <a href="#ECHONOECHO">echo() and
289*4a1a9510SRong-En Fan            noecho()</a></dt>
290*4a1a9510SRong-En Fan
291*4a1a9510SRong-En Fan            <dt>4.4. <a href="#KEYPAD">keypad()</a></dt>
292*4a1a9510SRong-En Fan
293*4a1a9510SRong-En Fan            <dt>4.5. <a href="#HALFDELAY">halfdelay()</a></dt>
294*4a1a9510SRong-En Fan
295*4a1a9510SRong-En Fan            <dt>4.6. <a href="#MISCINIT">Miscellaneous
296*4a1a9510SRong-En Fan            Initialization functions</a></dt>
297*4a1a9510SRong-En Fan
298*4a1a9510SRong-En Fan            <dt>4.7. <a href="#INITEX">An Example</a></dt>
299*4a1a9510SRong-En Fan          </dl>
300*4a1a9510SRong-En Fan        </dd>
301*4a1a9510SRong-En Fan
302*4a1a9510SRong-En Fan        <dt>5. <a href="#AWORDWINDOWS">A Word about
303*4a1a9510SRong-En Fan        Windows</a></dt>
304*4a1a9510SRong-En Fan
305*4a1a9510SRong-En Fan        <dt>6. <a href="#PRINTW">Output functions</a></dt>
306*4a1a9510SRong-En Fan
307*4a1a9510SRong-En Fan        <dd>
308*4a1a9510SRong-En Fan          <dl>
309*4a1a9510SRong-En Fan            <dt>6.1. <a href="#ADDCHCLASS">addch() class of
310*4a1a9510SRong-En Fan            functions</a></dt>
311*4a1a9510SRong-En Fan
312*4a1a9510SRong-En Fan            <dt>6.2. <a href="#AEN298">mvaddch(), waddch() and
313*4a1a9510SRong-En Fan            mvwaddch()</a></dt>
314*4a1a9510SRong-En Fan
315*4a1a9510SRong-En Fan            <dt>6.3. <a href="#PRINTWCLASS">printw() class of
316*4a1a9510SRong-En Fan            functions</a></dt>
317*4a1a9510SRong-En Fan
318*4a1a9510SRong-En Fan            <dd>
319*4a1a9510SRong-En Fan              <dl>
320*4a1a9510SRong-En Fan                <dt>6.3.1. <a href="#PRINTWMVPRINTW">printw() and
321*4a1a9510SRong-En Fan                mvprintw</a></dt>
322*4a1a9510SRong-En Fan
323*4a1a9510SRong-En Fan                <dt>6.3.2. <a href="#WPRINTWMVWPRINTW">wprintw()
324*4a1a9510SRong-En Fan                and mvwprintw</a></dt>
325*4a1a9510SRong-En Fan
326*4a1a9510SRong-En Fan                <dt>6.3.3. <a href="#VWPRINTW">vw_printw()</a></dt>
327*4a1a9510SRong-En Fan
328*4a1a9510SRong-En Fan                <dt>6.3.4. <a href="#SIMPLEPRINTWEX">A Simple
329*4a1a9510SRong-En Fan                printw example</a></dt>
330*4a1a9510SRong-En Fan              </dl>
331*4a1a9510SRong-En Fan            </dd>
332*4a1a9510SRong-En Fan
333*4a1a9510SRong-En Fan            <dt>6.4. <a href="#ADDSTRCLASS">addstr() class of
334*4a1a9510SRong-En Fan            functions</a></dt>
335*4a1a9510SRong-En Fan
336*4a1a9510SRong-En Fan            <dt>6.5. <a href="#ACAUTION">A word of caution</a></dt>
337*4a1a9510SRong-En Fan          </dl>
338*4a1a9510SRong-En Fan        </dd>
339*4a1a9510SRong-En Fan
340*4a1a9510SRong-En Fan        <dt>7. <a href="#SCANW">Input functions</a></dt>
341*4a1a9510SRong-En Fan
342*4a1a9510SRong-En Fan        <dd>
343*4a1a9510SRong-En Fan          <dl>
344*4a1a9510SRong-En Fan            <dt>7.1. <a href="#GETCHCLASS">getch() class of
345*4a1a9510SRong-En Fan            functions</a></dt>
346*4a1a9510SRong-En Fan
347*4a1a9510SRong-En Fan            <dt>7.2. <a href="#SCANWCLASS">scanw() class of
348*4a1a9510SRong-En Fan            functions</a></dt>
349*4a1a9510SRong-En Fan
350*4a1a9510SRong-En Fan            <dd>
351*4a1a9510SRong-En Fan              <dl>
352*4a1a9510SRong-En Fan                <dt>7.2.1. <a href="#SCANWMVSCANW">scanw() and
353*4a1a9510SRong-En Fan                mvscanw</a></dt>
354*4a1a9510SRong-En Fan
355*4a1a9510SRong-En Fan                <dt>7.2.2. <a href="#WSCANWMVWSCANW">wscanw() and
356*4a1a9510SRong-En Fan                mvwscanw()</a></dt>
357*4a1a9510SRong-En Fan
358*4a1a9510SRong-En Fan                <dt>7.2.3. <a href="#VWSCANW">vw_scanw()</a></dt>
359*4a1a9510SRong-En Fan              </dl>
360*4a1a9510SRong-En Fan            </dd>
361*4a1a9510SRong-En Fan
362*4a1a9510SRong-En Fan            <dt>7.3. <a href="#GETSTRCLASS">getstr() class of
363*4a1a9510SRong-En Fan            functions</a></dt>
364*4a1a9510SRong-En Fan
365*4a1a9510SRong-En Fan            <dt>7.4. <a href="#GETSTREX">Some examples</a></dt>
366*4a1a9510SRong-En Fan          </dl>
367*4a1a9510SRong-En Fan        </dd>
368*4a1a9510SRong-En Fan
369*4a1a9510SRong-En Fan        <dt>8. <a href="#ATTRIB">Attributes</a></dt>
370*4a1a9510SRong-En Fan
371*4a1a9510SRong-En Fan        <dd>
372*4a1a9510SRong-En Fan          <dl>
373*4a1a9510SRong-En Fan            <dt>8.1. <a href="#ATTRIBDETAILS">The details</a></dt>
374*4a1a9510SRong-En Fan
375*4a1a9510SRong-En Fan            <dt>8.2. <a href="#ATTRONVSATTRSET">attron() vs
376*4a1a9510SRong-En Fan            attrset()</a></dt>
377*4a1a9510SRong-En Fan
378*4a1a9510SRong-En Fan            <dt>8.3. <a href="#ATTRGET">attr_get()</a></dt>
379*4a1a9510SRong-En Fan
380*4a1a9510SRong-En Fan            <dt>8.4. <a href="#ATTRFUNCS">attr_ functions</a></dt>
381*4a1a9510SRong-En Fan
382*4a1a9510SRong-En Fan            <dt>8.5. <a href="#WATTRFUNCS">wattr functions</a></dt>
383*4a1a9510SRong-En Fan
384*4a1a9510SRong-En Fan            <dt>8.6. <a href="#CHGAT">chgat() functions</a></dt>
385*4a1a9510SRong-En Fan          </dl>
386*4a1a9510SRong-En Fan        </dd>
387*4a1a9510SRong-En Fan
388*4a1a9510SRong-En Fan        <dt>9. <a href="#WINDOWS">Windows</a></dt>
389*4a1a9510SRong-En Fan
390*4a1a9510SRong-En Fan        <dd>
391*4a1a9510SRong-En Fan          <dl>
392*4a1a9510SRong-En Fan            <dt>9.1. <a href="#WINDOWBASICS">The basics</a></dt>
393*4a1a9510SRong-En Fan
394*4a1a9510SRong-En Fan            <dt>9.2. <a href="#LETBEWINDOW">Let there be a Window
395*4a1a9510SRong-En Fan            !!!</a></dt>
396*4a1a9510SRong-En Fan
397*4a1a9510SRong-En Fan            <dt>9.3. <a href="#BORDEREXEXPL">Explanation</a></dt>
398*4a1a9510SRong-En Fan
399*4a1a9510SRong-En Fan            <dt>9.4. <a href="#OTHERSTUFF">The other stuff in the
400*4a1a9510SRong-En Fan            example</a></dt>
401*4a1a9510SRong-En Fan
402*4a1a9510SRong-En Fan            <dt>9.5. <a href="#OTHERBORDERFUNCS">Other Border
403*4a1a9510SRong-En Fan            functions</a></dt>
404*4a1a9510SRong-En Fan          </dl>
405*4a1a9510SRong-En Fan        </dd>
406*4a1a9510SRong-En Fan
407*4a1a9510SRong-En Fan        <dt>10. <a href="#COLOR">Colors</a></dt>
408*4a1a9510SRong-En Fan
409*4a1a9510SRong-En Fan        <dd>
410*4a1a9510SRong-En Fan          <dl>
411*4a1a9510SRong-En Fan            <dt>10.1. <a href="#COLORBASICS">The basics</a></dt>
412*4a1a9510SRong-En Fan
413*4a1a9510SRong-En Fan            <dt>10.2. <a href="#CHANGECOLORDEFS">Changing Color
414*4a1a9510SRong-En Fan            Definitions</a></dt>
415*4a1a9510SRong-En Fan
416*4a1a9510SRong-En Fan            <dt>10.3. <a href="#COLORCONTENT">Color
417*4a1a9510SRong-En Fan            Content</a></dt>
418*4a1a9510SRong-En Fan          </dl>
419*4a1a9510SRong-En Fan        </dd>
420*4a1a9510SRong-En Fan
421*4a1a9510SRong-En Fan        <dt>11. <a href="#KEYS">Interfacing with the key
422*4a1a9510SRong-En Fan        board</a></dt>
423*4a1a9510SRong-En Fan
424*4a1a9510SRong-En Fan        <dd>
425*4a1a9510SRong-En Fan          <dl>
426*4a1a9510SRong-En Fan            <dt>11.1. <a href="#KEYSBASICS">The Basics</a></dt>
427*4a1a9510SRong-En Fan
428*4a1a9510SRong-En Fan            <dt>11.2. <a href="#SIMPLEKEYEX">A Simple Key Usage
429*4a1a9510SRong-En Fan            example</a></dt>
430*4a1a9510SRong-En Fan          </dl>
431*4a1a9510SRong-En Fan        </dd>
432*4a1a9510SRong-En Fan
433*4a1a9510SRong-En Fan        <dt>12. <a href="#MOUSE">Interfacing with the
434*4a1a9510SRong-En Fan        mouse</a></dt>
435*4a1a9510SRong-En Fan
436*4a1a9510SRong-En Fan        <dd>
437*4a1a9510SRong-En Fan          <dl>
438*4a1a9510SRong-En Fan            <dt>12.1. <a href="#MOUSEBASICS">The Basics</a></dt>
439*4a1a9510SRong-En Fan
440*4a1a9510SRong-En Fan            <dt>12.2. <a href="#GETTINGEVENTS">Getting the
441*4a1a9510SRong-En Fan            events</a></dt>
442*4a1a9510SRong-En Fan
443*4a1a9510SRong-En Fan            <dt>12.3. <a href="#MOUSETOGETHER">Putting it all
444*4a1a9510SRong-En Fan            Together</a></dt>
445*4a1a9510SRong-En Fan
446*4a1a9510SRong-En Fan            <dt>12.4. <a href="#MISCMOUSEFUNCS">Miscellaneous
447*4a1a9510SRong-En Fan            Functions</a></dt>
448*4a1a9510SRong-En Fan          </dl>
449*4a1a9510SRong-En Fan        </dd>
450*4a1a9510SRong-En Fan
451*4a1a9510SRong-En Fan        <dt>13. <a href="#SCREEN">Screen Manipulation</a></dt>
452*4a1a9510SRong-En Fan
453*4a1a9510SRong-En Fan        <dd>
454*4a1a9510SRong-En Fan          <dl>
455*4a1a9510SRong-En Fan            <dt>13.1. <a href="#GETYX">getyx() functions</a></dt>
456*4a1a9510SRong-En Fan
457*4a1a9510SRong-En Fan            <dt>13.2. <a href="#SCREENDUMP">Screen Dumping</a></dt>
458*4a1a9510SRong-En Fan
459*4a1a9510SRong-En Fan            <dt>13.3. <a href="#WINDOWDUMP">Window Dumping</a></dt>
460*4a1a9510SRong-En Fan          </dl>
461*4a1a9510SRong-En Fan        </dd>
462*4a1a9510SRong-En Fan
463*4a1a9510SRong-En Fan        <dt>14. <a href="#MISC">Miscellaneous features</a></dt>
464*4a1a9510SRong-En Fan
465*4a1a9510SRong-En Fan        <dd>
466*4a1a9510SRong-En Fan          <dl>
467*4a1a9510SRong-En Fan            <dt>14.1. <a href="#CURSSET">curs_set()</a></dt>
468*4a1a9510SRong-En Fan
469*4a1a9510SRong-En Fan            <dt>14.2. <a href="#TEMPLEAVE">Temporarily Leaving
470*4a1a9510SRong-En Fan            Curses mode</a></dt>
471*4a1a9510SRong-En Fan
472*4a1a9510SRong-En Fan            <dt>14.3. <a href="#ACSVARS">ACS_ variables</a></dt>
473*4a1a9510SRong-En Fan          </dl>
474*4a1a9510SRong-En Fan        </dd>
475*4a1a9510SRong-En Fan
476*4a1a9510SRong-En Fan        <dt>15. <a href="#OTHERLIB">Other libraries</a></dt>
477*4a1a9510SRong-En Fan
478*4a1a9510SRong-En Fan        <dt>16. <a href="#PANELS">Panel Library</a></dt>
479*4a1a9510SRong-En Fan
480*4a1a9510SRong-En Fan        <dd>
481*4a1a9510SRong-En Fan          <dl>
482*4a1a9510SRong-En Fan            <dt>16.1. <a href="#PANELBASICS">The Basics</a></dt>
483*4a1a9510SRong-En Fan
484*4a1a9510SRong-En Fan            <dt>16.2. <a href="#COMPILEPANELS">Compiling With the
485*4a1a9510SRong-En Fan            Panels Library</a></dt>
486*4a1a9510SRong-En Fan
487*4a1a9510SRong-En Fan            <dt>16.3. <a href="#PANELBROWSING">Panel Window
488*4a1a9510SRong-En Fan            Browsing</a></dt>
489*4a1a9510SRong-En Fan
490*4a1a9510SRong-En Fan            <dt>16.4. <a href="#USERPTRUSING">Using User
491*4a1a9510SRong-En Fan            Pointers</a></dt>
492*4a1a9510SRong-En Fan
493*4a1a9510SRong-En Fan            <dt>16.5. <a href="#PANELMOVERESIZE">Moving and
494*4a1a9510SRong-En Fan            Resizing Panels</a></dt>
495*4a1a9510SRong-En Fan
496*4a1a9510SRong-En Fan            <dt>16.6. <a href="#PANELSHOWHIDE">Hiding and Showing
497*4a1a9510SRong-En Fan            Panels</a></dt>
498*4a1a9510SRong-En Fan
499*4a1a9510SRong-En Fan            <dt>16.7. <a href="#PANELABOVE">panel_above() and
500*4a1a9510SRong-En Fan            panel_below() Functions</a></dt>
501*4a1a9510SRong-En Fan          </dl>
502*4a1a9510SRong-En Fan        </dd>
503*4a1a9510SRong-En Fan
504*4a1a9510SRong-En Fan        <dt>17. <a href="#MENUS">Menus Library</a></dt>
505*4a1a9510SRong-En Fan
506*4a1a9510SRong-En Fan        <dd>
507*4a1a9510SRong-En Fan          <dl>
508*4a1a9510SRong-En Fan            <dt>17.1. <a href="#MENUBASICS">The Basics</a></dt>
509*4a1a9510SRong-En Fan
510*4a1a9510SRong-En Fan            <dt>17.2. <a href="#COMPILEMENUS">Compiling With the
511*4a1a9510SRong-En Fan            Menu Library</a></dt>
512*4a1a9510SRong-En Fan
513*4a1a9510SRong-En Fan            <dt>17.3. <a href="#MENUDRIVER">Menu Driver: The work
514*4a1a9510SRong-En Fan            horse of the menu system</a></dt>
515*4a1a9510SRong-En Fan
516*4a1a9510SRong-En Fan            <dt>17.4. <a href="#MENUWINDOWS">Menu Windows</a></dt>
517*4a1a9510SRong-En Fan
518*4a1a9510SRong-En Fan            <dt>17.5. <a href="#SCROLLMENUS">Scrolling
519*4a1a9510SRong-En Fan            Menus</a></dt>
520*4a1a9510SRong-En Fan
521*4a1a9510SRong-En Fan            <dt>17.6. <a href="#MULTICOLUMN">Multi Columnar
522*4a1a9510SRong-En Fan            Menus</a></dt>
523*4a1a9510SRong-En Fan
524*4a1a9510SRong-En Fan            <dt>17.7. <a href="#MULTIVALUEMENUS">Multi Valued
525*4a1a9510SRong-En Fan            Menus</a></dt>
526*4a1a9510SRong-En Fan
527*4a1a9510SRong-En Fan            <dt>17.8. <a href="#MENUOPT">Menu Options</a></dt>
528*4a1a9510SRong-En Fan
529*4a1a9510SRong-En Fan            <dt>17.9. <a href="#MENUUSERPTR">The useful User
530*4a1a9510SRong-En Fan            Pointer</a></dt>
531*4a1a9510SRong-En Fan          </dl>
532*4a1a9510SRong-En Fan        </dd>
533*4a1a9510SRong-En Fan
534*4a1a9510SRong-En Fan        <dt>18. <a href="#FORMS">Forms Library</a></dt>
535*4a1a9510SRong-En Fan
536*4a1a9510SRong-En Fan        <dd>
537*4a1a9510SRong-En Fan          <dl>
538*4a1a9510SRong-En Fan            <dt>18.1. <a href="#FORMBASICS">The Basics</a></dt>
539*4a1a9510SRong-En Fan
540*4a1a9510SRong-En Fan            <dt>18.2. <a href="#COMPILEFORMS">Compiling With the
541*4a1a9510SRong-En Fan            Forms Library</a></dt>
542*4a1a9510SRong-En Fan
543*4a1a9510SRong-En Fan            <dt>18.3. <a href="#PLAYFIELDS">Playing with
544*4a1a9510SRong-En Fan            Fields</a></dt>
545*4a1a9510SRong-En Fan
546*4a1a9510SRong-En Fan            <dd>
547*4a1a9510SRong-En Fan              <dl>
548*4a1a9510SRong-En Fan                <dt>18.3.1. <a href="#FETCHINFO">Fetching Size and
549*4a1a9510SRong-En Fan                Location of Field</a></dt>
550*4a1a9510SRong-En Fan
551*4a1a9510SRong-En Fan                <dt>18.3.2. <a href="#MOVEFIELD">Moving the
552*4a1a9510SRong-En Fan                field</a></dt>
553*4a1a9510SRong-En Fan
554*4a1a9510SRong-En Fan                <dt>18.3.3. <a href="#JUSTIFYFIELD">Field
555*4a1a9510SRong-En Fan                Justification</a></dt>
556*4a1a9510SRong-En Fan
557*4a1a9510SRong-En Fan                <dt>18.3.4. <a href="#FIELDDISPATTRIB">Field
558*4a1a9510SRong-En Fan                Display Attributes</a></dt>
559*4a1a9510SRong-En Fan
560*4a1a9510SRong-En Fan                <dt>18.3.5. <a href="#FIELDOPTIONBITS">Field Option
561*4a1a9510SRong-En Fan                Bits</a></dt>
562*4a1a9510SRong-En Fan
563*4a1a9510SRong-En Fan                <dt>18.3.6. <a href="#FIELDSTATUS">Field
564*4a1a9510SRong-En Fan                Status</a></dt>
565*4a1a9510SRong-En Fan
566*4a1a9510SRong-En Fan                <dt>18.3.7. <a href="#FIELDUSERPTR">Field User
567*4a1a9510SRong-En Fan                Pointer</a></dt>
568*4a1a9510SRong-En Fan
569*4a1a9510SRong-En Fan                <dt>18.3.8. <a href=
570*4a1a9510SRong-En Fan                "#VARIABLESIZEFIELDS">Variable-Sized
571*4a1a9510SRong-En Fan                Fields</a></dt>
572*4a1a9510SRong-En Fan              </dl>
573*4a1a9510SRong-En Fan            </dd>
574*4a1a9510SRong-En Fan
575*4a1a9510SRong-En Fan            <dt>18.4. <a href="#FORMWINDOWS">Form Windows</a></dt>
576*4a1a9510SRong-En Fan
577*4a1a9510SRong-En Fan            <dt>18.5. <a href="#FILEDVALIDATE">Field
578*4a1a9510SRong-En Fan            Validation</a></dt>
579*4a1a9510SRong-En Fan
580*4a1a9510SRong-En Fan            <dt>18.6. <a href="#FORMDRIVER">Form Driver: The work
581*4a1a9510SRong-En Fan            horse of the forms system</a></dt>
582*4a1a9510SRong-En Fan
583*4a1a9510SRong-En Fan            <dd>
584*4a1a9510SRong-En Fan              <dl>
585*4a1a9510SRong-En Fan                <dt>18.6.1. <a href="#PAGENAVREQ">Page Navigation
586*4a1a9510SRong-En Fan                Requests</a></dt>
587*4a1a9510SRong-En Fan
588*4a1a9510SRong-En Fan                <dt>18.6.2. <a href="#INTERFIELDNAVREQ">Inter-Field
589*4a1a9510SRong-En Fan                Navigation Requests</a></dt>
590*4a1a9510SRong-En Fan
591*4a1a9510SRong-En Fan                <dt>18.6.3. <a href="#INTRAFIELDNAVREQ">Intra-Field
592*4a1a9510SRong-En Fan                Navigation Requests</a></dt>
593*4a1a9510SRong-En Fan
594*4a1a9510SRong-En Fan                <dt>18.6.4. <a href="#SCROLLREQ">Scrolling
595*4a1a9510SRong-En Fan                Requests</a></dt>
596*4a1a9510SRong-En Fan
597*4a1a9510SRong-En Fan                <dt>18.6.5. <a href="#EDITREQ">Editing
598*4a1a9510SRong-En Fan                Requests</a></dt>
599*4a1a9510SRong-En Fan
600*4a1a9510SRong-En Fan                <dt>18.6.6. <a href="#ORDERREQ">Order
601*4a1a9510SRong-En Fan                Requests</a></dt>
602*4a1a9510SRong-En Fan
603*4a1a9510SRong-En Fan                <dt>18.6.7. <a href="#APPLICCOMMANDS">Application
604*4a1a9510SRong-En Fan                Commands</a></dt>
605*4a1a9510SRong-En Fan              </dl>
606*4a1a9510SRong-En Fan            </dd>
607*4a1a9510SRong-En Fan          </dl>
608*4a1a9510SRong-En Fan        </dd>
609*4a1a9510SRong-En Fan
610*4a1a9510SRong-En Fan        <dt>19. <a href="#TOOLS">Tools and Widget
611*4a1a9510SRong-En Fan        Libraries</a></dt>
612*4a1a9510SRong-En Fan
613*4a1a9510SRong-En Fan        <dd>
614*4a1a9510SRong-En Fan          <dl>
615*4a1a9510SRong-En Fan            <dt>19.1. <a href="#CDK">CDK (Curses Development
616*4a1a9510SRong-En Fan            Kit)</a></dt>
617*4a1a9510SRong-En Fan
618*4a1a9510SRong-En Fan            <dd>
619*4a1a9510SRong-En Fan              <dl>
620*4a1a9510SRong-En Fan                <dt>19.1.1. <a href="#WIDGETLIST">Widget
621*4a1a9510SRong-En Fan                List</a></dt>
622*4a1a9510SRong-En Fan
623*4a1a9510SRong-En Fan                <dt>19.1.2. <a href="#CDKATTRACT">Some Attractive
624*4a1a9510SRong-En Fan                Features</a></dt>
625*4a1a9510SRong-En Fan
626*4a1a9510SRong-En Fan                <dt>19.1.3. <a href=
627*4a1a9510SRong-En Fan                "#CDKCONCLUSION">Conclusion</a></dt>
628*4a1a9510SRong-En Fan              </dl>
629*4a1a9510SRong-En Fan            </dd>
630*4a1a9510SRong-En Fan
631*4a1a9510SRong-En Fan            <dt>19.2. <a href="#DIALOG">The dialog</a></dt>
632*4a1a9510SRong-En Fan
633*4a1a9510SRong-En Fan            <dt>19.3. <a href="#PERLCURSES">Perl Curses Modules
634*4a1a9510SRong-En Fan            CURSES::FORM and CURSES::WIDGETS</a></dt>
635*4a1a9510SRong-En Fan          </dl>
636*4a1a9510SRong-En Fan        </dd>
637*4a1a9510SRong-En Fan
638*4a1a9510SRong-En Fan        <dt>20. <a href="#JUSTFORFUN">Just For Fun !!!</a></dt>
639*4a1a9510SRong-En Fan
640*4a1a9510SRong-En Fan        <dd>
641*4a1a9510SRong-En Fan          <dl>
642*4a1a9510SRong-En Fan            <dt>20.1. <a href="#GAMEOFLIFE">The Game of
643*4a1a9510SRong-En Fan            Life</a></dt>
644*4a1a9510SRong-En Fan
645*4a1a9510SRong-En Fan            <dt>20.2. <a href="#MAGIC">Magic Square</a></dt>
646*4a1a9510SRong-En Fan
647*4a1a9510SRong-En Fan            <dt>20.3. <a href="#HANOI">Towers of Hanoi</a></dt>
648*4a1a9510SRong-En Fan
649*4a1a9510SRong-En Fan            <dt>20.4. <a href="#QUEENS">Queens Puzzle</a></dt>
650*4a1a9510SRong-En Fan
651*4a1a9510SRong-En Fan            <dt>20.5. <a href="#SHUFFLE">Shuffle</a></dt>
652*4a1a9510SRong-En Fan
653*4a1a9510SRong-En Fan            <dt>20.6. <a href="#TT">Typing Tutor</a></dt>
654*4a1a9510SRong-En Fan          </dl>
655*4a1a9510SRong-En Fan        </dd>
656*4a1a9510SRong-En Fan
657*4a1a9510SRong-En Fan        <dt>21. <a href="#REF">References</a></dt>
658*4a1a9510SRong-En Fan      </dl>
659*4a1a9510SRong-En Fan    </div>
660*4a1a9510SRong-En Fan
661*4a1a9510SRong-En Fan    <div class="SECT1">
662*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="INTRO" id="INTRO">1.
663*4a1a9510SRong-En Fan      Introduction</a></h2>
664*4a1a9510SRong-En Fan
665*4a1a9510SRong-En Fan      <p>In the olden days of teletype terminals, terminals were
666*4a1a9510SRong-En Fan      away from computers and were connected to them through serial
667*4a1a9510SRong-En Fan      cables. The terminals could be configured by sending a series
668*4a1a9510SRong-En Fan      of bytes. All the capabilities (such as moving the cursor to
669*4a1a9510SRong-En Fan      a new location, erasing part of the screen, scrolling the
670*4a1a9510SRong-En Fan      screen, changing modes etc.) of terminals could be accessed
671*4a1a9510SRong-En Fan      through these series of bytes. These control seeuqnces are
672*4a1a9510SRong-En Fan      usually called escape sequences, because they start with an
673*4a1a9510SRong-En Fan      escape(0x1B) character. Even today, with proper emulation, we
674*4a1a9510SRong-En Fan      can send escape sequences to the emulator and achieve the
675*4a1a9510SRong-En Fan      same effect on a terminal window.</p>
676*4a1a9510SRong-En Fan
677*4a1a9510SRong-En Fan      <p>Suppose you wanted to print a line in color. Try typing
678*4a1a9510SRong-En Fan      this on your console.</p>
679*4a1a9510SRong-En Fan      <pre class="PROGRAMLISTING">
680*4a1a9510SRong-En Fanecho "^[[0;31;40mIn Color"
681*4a1a9510SRong-En Fan</pre>
682*4a1a9510SRong-En Fan
683*4a1a9510SRong-En Fan      <p>The first character is an escape character, which looks
684*4a1a9510SRong-En Fan      like two characters ^ and [. To be able to print it, you have
685*4a1a9510SRong-En Fan      to press CTRL+V and then the ESC key. All the others are
686*4a1a9510SRong-En Fan      normal printable characters. You should be able to see the
687*4a1a9510SRong-En Fan      string "In Color" in red. It stays that way and to revert
688*4a1a9510SRong-En Fan      back to the original mode type this.</p>
689*4a1a9510SRong-En Fan      <pre class="PROGRAMLISTING">
690*4a1a9510SRong-En Fanecho "^[[0;37;40m"
691*4a1a9510SRong-En Fan</pre>
692*4a1a9510SRong-En Fan
693*4a1a9510SRong-En Fan      <p>Now, what do these magic characters mean? Difficult to
694*4a1a9510SRong-En Fan      comprehend? They might even be different for different
695*4a1a9510SRong-En Fan      terminals. So the designers of UNIX invented a mechanism
696*4a1a9510SRong-En Fan      named <tt class="LITERAL">termcap</tt>. It is a file that
697*4a1a9510SRong-En Fan      lists all the capabilities of a particular terminal, along
698*4a1a9510SRong-En Fan      with the escape sequences needed to achieve a particular
699*4a1a9510SRong-En Fan      effect. In the later years, this was replaced by <tt class=
700*4a1a9510SRong-En Fan      "LITERAL">terminfo</tt>. Without delving too much into
701*4a1a9510SRong-En Fan      details, this mechanism allows application programs to query
702*4a1a9510SRong-En Fan      the terminfo database and obtain the control characters to be
703*4a1a9510SRong-En Fan      sent to a terminal or terminal emulator.</p>
704*4a1a9510SRong-En Fan
705*4a1a9510SRong-En Fan      <div class="SECT2">
706*4a1a9510SRong-En Fan        <hr>
707*4a1a9510SRong-En Fan
708*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WHATIS" id="WHATIS">1.1. What is
709*4a1a9510SRong-En Fan        NCURSES?</a></h3>
710*4a1a9510SRong-En Fan
711*4a1a9510SRong-En Fan        <p>You might be wondering, what the import of all this
712*4a1a9510SRong-En Fan        technical gibberish is. In the above scenario, every
713*4a1a9510SRong-En Fan        application program is supposed to query the terminfo and
714*4a1a9510SRong-En Fan        perform the necessary stuff (sending control characters
715*4a1a9510SRong-En Fan        etc.). It soon became difficult to manage this complexity
716*4a1a9510SRong-En Fan        and this gave birth to 'CURSES'. Curses is a pun on the
717*4a1a9510SRong-En Fan        name "cursor optimization". The Curses library forms a
718*4a1a9510SRong-En Fan        wrapper over working with raw terminal codes, and provides
719*4a1a9510SRong-En Fan        highly flexible and efficient API (Application Programming
720*4a1a9510SRong-En Fan        Interface). It provides functions to move the cursor,
721*4a1a9510SRong-En Fan        create windows, produce colors, play with mouse etc. The
722*4a1a9510SRong-En Fan        application programs need not worry about the underlying
723*4a1a9510SRong-En Fan        terminal capabilities.</p>
724*4a1a9510SRong-En Fan
725*4a1a9510SRong-En Fan        <p>So what is NCURSES? NCURSES is a clone of the original
726*4a1a9510SRong-En Fan        System V Release 4.0 (SVr4) curses. It is a freely
727*4a1a9510SRong-En Fan        distributable library, fully compatible with older version
728*4a1a9510SRong-En Fan        of curses. In short, it is a library of functions that
729*4a1a9510SRong-En Fan        manages an application's display on character-cell
730*4a1a9510SRong-En Fan        terminals. In the remainder of the document, the terms
731*4a1a9510SRong-En Fan        curses and ncurses are used interchangeably.</p>
732*4a1a9510SRong-En Fan
733*4a1a9510SRong-En Fan        <p>A detailed history of NCURSES can be found in the NEWS
734*4a1a9510SRong-En Fan        file from the source distribution. The current package is
735*4a1a9510SRong-En Fan        maintained by <a href="mailto:[email protected]" target=
736*4a1a9510SRong-En Fan        "_top">Thomas Dickey</a>. You can contact the maintainers
737*4a1a9510SRong-En Fan        at <a href="mailto:[email protected]" target=
738*4a1a9510SRong-En Fan        "_top">[email protected]</a>.</p>
739*4a1a9510SRong-En Fan      </div>
740*4a1a9510SRong-En Fan
741*4a1a9510SRong-En Fan      <div class="SECT2">
742*4a1a9510SRong-En Fan        <hr>
743*4a1a9510SRong-En Fan
744*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WHATCANWEDO" id=
745*4a1a9510SRong-En Fan        "WHATCANWEDO">1.2. What we can do with NCURSES</a></h3>
746*4a1a9510SRong-En Fan
747*4a1a9510SRong-En Fan        <p>NCURSES not only creates a wrapper over terminal
748*4a1a9510SRong-En Fan        capabilities, but also gives a robust framework to create
749*4a1a9510SRong-En Fan        nice looking UI (User Interface)s in text mode. It provides
750*4a1a9510SRong-En Fan        functions to create windows etc. Its sister libraries
751*4a1a9510SRong-En Fan        panel, menu and form provide an extension to the basic
752*4a1a9510SRong-En Fan        curses library. These libraries usually come along with
753*4a1a9510SRong-En Fan        curses. One can create applications that contain multiple
754*4a1a9510SRong-En Fan        windows, menus, panels and forms. Windows can be managed
755*4a1a9510SRong-En Fan        independently, can provide 'scrollability' and even can be
756*4a1a9510SRong-En Fan        hidden.</p>
757*4a1a9510SRong-En Fan
758*4a1a9510SRong-En Fan        <p>Menus provide the user with an easy command selection
759*4a1a9510SRong-En Fan        option. Forms allow the creation of easy-to-use data entry
760*4a1a9510SRong-En Fan        and display windows. Panels extend the capabilities of
761*4a1a9510SRong-En Fan        ncurses to deal with overlapping and stacked windows.</p>
762*4a1a9510SRong-En Fan
763*4a1a9510SRong-En Fan        <p>These are just some of the basic things we can do with
764*4a1a9510SRong-En Fan        ncurses. As we move along, We will see all the capabilities
765*4a1a9510SRong-En Fan        of these libraries.</p>
766*4a1a9510SRong-En Fan      </div>
767*4a1a9510SRong-En Fan
768*4a1a9510SRong-En Fan      <div class="SECT2">
769*4a1a9510SRong-En Fan        <hr>
770*4a1a9510SRong-En Fan
771*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WHERETOGETIT" id=
772*4a1a9510SRong-En Fan        "WHERETOGETIT">1.3. Where to get it</a></h3>
773*4a1a9510SRong-En Fan
774*4a1a9510SRong-En Fan        <p>All right, now that you know what you can do with
775*4a1a9510SRong-En Fan        ncurses, you must be rearing to get started. NCURSES is
776*4a1a9510SRong-En Fan        usually shipped with your installation. In case you don't
777*4a1a9510SRong-En Fan        have the library or want to compile it on your own, read
778*4a1a9510SRong-En Fan        on.</p>
779*4a1a9510SRong-En Fan
780*4a1a9510SRong-En Fan        <p><span class="emphasis"><i class="EMPHASIS">Compiling the
781*4a1a9510SRong-En Fan        package</i></span></p>
782*4a1a9510SRong-En Fan
783*4a1a9510SRong-En Fan        <p>NCURSES can be obtained from <a href=
784*4a1a9510SRong-En Fan        "ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz" target=
785*4a1a9510SRong-En Fan        "_top">ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</a>
786*4a1a9510SRong-En Fan        or any of the ftp sites mentioned in <a href=
787*4a1a9510SRong-En Fan        "http://www.gnu.org/order/ftp.html" target=
788*4a1a9510SRong-En Fan        "_top">http://www.gnu.org/order/ftp.html</a>.</p>
789*4a1a9510SRong-En Fan
790*4a1a9510SRong-En Fan        <p>Read the README and INSTALL files for details on to how
791*4a1a9510SRong-En Fan        to install it. It usually involves the following
792*4a1a9510SRong-En Fan        operations.</p>
793*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
794*4a1a9510SRong-En Fan    tar zxvf ncurses&lt;version&gt;.tar.gz  # unzip and untar the archive
795*4a1a9510SRong-En Fan    cd ncurses&lt;version&gt;               # cd to the directory
796*4a1a9510SRong-En Fan    ./configure                             # configure the build according to your
797*4a1a9510SRong-En Fan                                            # environment
798*4a1a9510SRong-En Fan    make                                    # make it
799*4a1a9510SRong-En Fan    su root                                 # become root
800*4a1a9510SRong-En Fan    make install                            # install it
801*4a1a9510SRong-En Fan</pre>
802*4a1a9510SRong-En Fan
803*4a1a9510SRong-En Fan        <p><span class="emphasis"><i class="EMPHASIS">Using the
804*4a1a9510SRong-En Fan        RPM</i></span></p>
805*4a1a9510SRong-En Fan
806*4a1a9510SRong-En Fan        <p>NCURSES RPM can be found and downloaded from <a href=
807*4a1a9510SRong-En Fan        "http://rpmfind.net" target="_top">http://rpmfind.net</a> .
808*4a1a9510SRong-En Fan        The RPM can be installed with the following command after
809*4a1a9510SRong-En Fan        becoming root.</p>
810*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
811*4a1a9510SRong-En Fan    rpm -i &lt;downloaded rpm&gt;
812*4a1a9510SRong-En Fan</pre>
813*4a1a9510SRong-En Fan      </div>
814*4a1a9510SRong-En Fan
815*4a1a9510SRong-En Fan      <div class="SECT2">
816*4a1a9510SRong-En Fan        <hr>
817*4a1a9510SRong-En Fan
818*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PURPOSE" id="PURPOSE">1.4.
819*4a1a9510SRong-En Fan        Purpose/Scope of the document</a></h3>
820*4a1a9510SRong-En Fan
821*4a1a9510SRong-En Fan        <p>This document is intended to be a "All in One" guide for
822*4a1a9510SRong-En Fan        programming with ncurses and its sister libraries. We
823*4a1a9510SRong-En Fan        graduate from a simple "Hello World" program to more
824*4a1a9510SRong-En Fan        complex form manipulation. No prior experience in ncurses
825*4a1a9510SRong-En Fan        is assumed. The writing is informal, but a lot of detail is
826*4a1a9510SRong-En Fan        provided for each of the examples.</p>
827*4a1a9510SRong-En Fan      </div>
828*4a1a9510SRong-En Fan
829*4a1a9510SRong-En Fan      <div class="SECT2">
830*4a1a9510SRong-En Fan        <hr>
831*4a1a9510SRong-En Fan
832*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ABOUTPROGRAMS" id=
833*4a1a9510SRong-En Fan        "ABOUTPROGRAMS">1.5. About the Programs</a></h3>
834*4a1a9510SRong-En Fan
835*4a1a9510SRong-En Fan        <p>All the programs in the document are available in zipped
836*4a1a9510SRong-En Fan        form <a href=
837*4a1a9510SRong-En Fan        "http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz"
838*4a1a9510SRong-En Fan        target="_top">here</a>. Unzip and untar it. The directory
839*4a1a9510SRong-En Fan        structure looks like this.</p>
840*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
841*4a1a9510SRong-En Fanncurses
842*4a1a9510SRong-En Fan   |
843*4a1a9510SRong-En Fan   |----&gt; JustForFun     -- just for fun programs
844*4a1a9510SRong-En Fan   |----&gt; basics         -- basic programs
845*4a1a9510SRong-En Fan   |----&gt; demo           -- output files go into this directory after make
846*4a1a9510SRong-En Fan   |          |
847*4a1a9510SRong-En Fan   |          |----&gt; exe -- exe files of all example programs
848*4a1a9510SRong-En Fan   |----&gt; forms          -- programs related to form library
849*4a1a9510SRong-En Fan   |----&gt; menus          -- programs related to menus library
850*4a1a9510SRong-En Fan   |----&gt; panels         -- programs related to panels library
851*4a1a9510SRong-En Fan   |----&gt; perl           -- perl equivalents of the examples (contributed
852*4a1a9510SRong-En Fan   |                            by Anuradha Ratnaweera)
853*4a1a9510SRong-En Fan   |----&gt; Makefile       -- the top level Makefile
854*4a1a9510SRong-En Fan   |----&gt; README         -- the top level README file. contains instructions
855*4a1a9510SRong-En Fan   |----&gt; COPYING        -- copyright notice
856*4a1a9510SRong-En Fan</pre>
857*4a1a9510SRong-En Fan
858*4a1a9510SRong-En Fan        <p>The individual directories contain the following
859*4a1a9510SRong-En Fan        files.</p>
860*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
861*4a1a9510SRong-En FanDescription of files in each directory
862*4a1a9510SRong-En Fan--------------------------------------
863*4a1a9510SRong-En FanJustForFun
864*4a1a9510SRong-En Fan    |
865*4a1a9510SRong-En Fan    |----&gt; hanoi.c   -- The Towers of Hanoi Solver
866*4a1a9510SRong-En Fan    |----&gt; life.c    -- The Game of Life demo
867*4a1a9510SRong-En Fan    |----&gt; magic.c   -- An Odd Order Magic Square builder
868*4a1a9510SRong-En Fan    |----&gt; queens.c  -- The famous N-Queens Solver
869*4a1a9510SRong-En Fan    |----&gt; shuffle.c -- A fun game, if you have time to kill
870*4a1a9510SRong-En Fan    |----&gt; tt.c      -- A very trivial typing tutor
871*4a1a9510SRong-En Fan
872*4a1a9510SRong-En Fan  basics
873*4a1a9510SRong-En Fan    |
874*4a1a9510SRong-En Fan    |----&gt; acs_vars.c            -- ACS_ variables example
875*4a1a9510SRong-En Fan    |----&gt; hello_world.c         -- Simple "Hello World" Program
876*4a1a9510SRong-En Fan    |----&gt; init_func_example.c   -- Initialization functions example
877*4a1a9510SRong-En Fan    |----&gt; key_code.c            -- Shows the scan code of the key pressed
878*4a1a9510SRong-En Fan    |----&gt; mouse_menu.c          -- A menu accessible by mouse
879*4a1a9510SRong-En Fan    |----&gt; other_border.c        -- Shows usage of other border functions apa
880*4a1a9510SRong-En Fan    |                               -- rt from box()
881*4a1a9510SRong-En Fan    |----&gt; printw_example.c      -- A very simple printw() example
882*4a1a9510SRong-En Fan    |----&gt; scanw_example.c       -- A very simple getstr() example
883*4a1a9510SRong-En Fan    |----&gt; simple_attr.c         -- A program that can print a c file with
884*4a1a9510SRong-En Fan    |                               -- comments in attribute
885*4a1a9510SRong-En Fan    |----&gt; simple_color.c        -- A simple example demonstrating colors
886*4a1a9510SRong-En Fan    |----&gt; simple_key.c          -- A menu accessible with keyboard UP, DOWN
887*4a1a9510SRong-En Fan    |                               -- arrows
888*4a1a9510SRong-En Fan    |----&gt; temp_leave.c          -- Demonstrates temporarily leaving curses mode
889*4a1a9510SRong-En Fan    |----&gt; win_border.c          -- Shows Creation of windows and borders
890*4a1a9510SRong-En Fan    |----&gt; with_chgat.c          -- chgat() usage example
891*4a1a9510SRong-En Fan
892*4a1a9510SRong-En Fan  forms
893*4a1a9510SRong-En Fan    |
894*4a1a9510SRong-En Fan    |----&gt; form_attrib.c     -- Usage of field attributes
895*4a1a9510SRong-En Fan    |----&gt; form_options.c    -- Usage of field options
896*4a1a9510SRong-En Fan    |----&gt; form_simple.c     -- A simple form example
897*4a1a9510SRong-En Fan    |----&gt; form_win.c        -- Demo of windows associated with forms
898*4a1a9510SRong-En Fan
899*4a1a9510SRong-En Fan  menus
900*4a1a9510SRong-En Fan    |
901*4a1a9510SRong-En Fan    |----&gt; menu_attrib.c     -- Usage of menu attributes
902*4a1a9510SRong-En Fan    |----&gt; menu_item_data.c  -- Usage of item_name() etc.. functions
903*4a1a9510SRong-En Fan    |----&gt; menu_multi_column.c    -- Creates multi columnar menus
904*4a1a9510SRong-En Fan    |----&gt; menu_scroll.c     -- Demonstrates scrolling capability of menus
905*4a1a9510SRong-En Fan    |----&gt; menu_simple.c     -- A simple menu accessed by arrow keys
906*4a1a9510SRong-En Fan    |----&gt; menu_toggle.c     -- Creates multi valued menus and explains
907*4a1a9510SRong-En Fan    |                           -- REQ_TOGGLE_ITEM
908*4a1a9510SRong-En Fan    |----&gt; menu_userptr.c    -- Usage of user pointer
909*4a1a9510SRong-En Fan    |----&gt; menu_win.c        -- Demo of windows associated with menus
910*4a1a9510SRong-En Fan
911*4a1a9510SRong-En Fan  panels
912*4a1a9510SRong-En Fan    |
913*4a1a9510SRong-En Fan    |----&gt; panel_browse.c    -- Panel browsing through tab. Usage of user
914*4a1a9510SRong-En Fan    |                           -- pointer
915*4a1a9510SRong-En Fan    |----&gt; panel_hide.c      -- Hiding and Un hiding of panels
916*4a1a9510SRong-En Fan    |----&gt; panel_resize.c    -- Moving and resizing of panels
917*4a1a9510SRong-En Fan    |----&gt; panel_simple.c    -- A simple panel example
918*4a1a9510SRong-En Fan
919*4a1a9510SRong-En Fan  perl
920*4a1a9510SRong-En Fan    |----&gt; 01-10.pl          -- Perl equivalents of first ten example programs
921*4a1a9510SRong-En Fan</pre>
922*4a1a9510SRong-En Fan
923*4a1a9510SRong-En Fan        <p>There is a top level Makefile included in the main
924*4a1a9510SRong-En Fan        directory. It builds all the files and puts the
925*4a1a9510SRong-En Fan        ready-to-use exes in demo/exe directory. You can also do
926*4a1a9510SRong-En Fan        selective make by going into the corresponding directory.
927*4a1a9510SRong-En Fan        Each directory contains a README file explaining the
928*4a1a9510SRong-En Fan        purpose of each c file in the directory.</p>
929*4a1a9510SRong-En Fan
930*4a1a9510SRong-En Fan        <p>For every example, I have included path name for the
931*4a1a9510SRong-En Fan        file relative to the examples directory.</p>
932*4a1a9510SRong-En Fan
933*4a1a9510SRong-En Fan        <p>If you prefer browsing individual programs, point your
934*4a1a9510SRong-En Fan        browser to <a href=
935*4a1a9510SRong-En Fan        "http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/"
936*4a1a9510SRong-En Fan        target=
937*4a1a9510SRong-En Fan        "_top">http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</a></p>
938*4a1a9510SRong-En Fan
939*4a1a9510SRong-En Fan        <p>All the programs are released under the same license
940*4a1a9510SRong-En Fan        that is used by ncurses (MIT-style). This gives you the
941*4a1a9510SRong-En Fan        ability to do pretty much anything other than claiming them
942*4a1a9510SRong-En Fan        as yours. Feel free to use them in your programs as
943*4a1a9510SRong-En Fan        appropriate.</p>
944*4a1a9510SRong-En Fan      </div>
945*4a1a9510SRong-En Fan
946*4a1a9510SRong-En Fan      <div class="SECT2">
947*4a1a9510SRong-En Fan        <hr>
948*4a1a9510SRong-En Fan
949*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="OTHERFORMATS" id=
950*4a1a9510SRong-En Fan        "OTHERFORMATS">1.6. Other Formats of the document</a></h3>
951*4a1a9510SRong-En Fan
952*4a1a9510SRong-En Fan        <p>This howto is also availabe in various other formats on
953*4a1a9510SRong-En Fan        the tldp.org site. Here are the links to other formats of
954*4a1a9510SRong-En Fan        this document.</p>
955*4a1a9510SRong-En Fan
956*4a1a9510SRong-En Fan        <div class="SECT3">
957*4a1a9510SRong-En Fan          <hr>
958*4a1a9510SRong-En Fan
959*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="LISTFORMATS" id=
960*4a1a9510SRong-En Fan          "LISTFORMATS">1.6.1. Readily available formats from
961*4a1a9510SRong-En Fan          tldp.org</a></h4>
962*4a1a9510SRong-En Fan
963*4a1a9510SRong-En Fan          <ul>
964*4a1a9510SRong-En Fan            <li>
965*4a1a9510SRong-En Fan              <p><a href=
966*4a1a9510SRong-En Fan              "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf"
967*4a1a9510SRong-En Fan              target="_top">Acrobat PDF Format</a></p>
968*4a1a9510SRong-En Fan            </li>
969*4a1a9510SRong-En Fan
970*4a1a9510SRong-En Fan            <li>
971*4a1a9510SRong-En Fan              <p><a href=
972*4a1a9510SRong-En Fan              "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz"
973*4a1a9510SRong-En Fan              target="_top">PostScript Format</a></p>
974*4a1a9510SRong-En Fan            </li>
975*4a1a9510SRong-En Fan
976*4a1a9510SRong-En Fan            <li>
977*4a1a9510SRong-En Fan              <p><a href=
978*4a1a9510SRong-En Fan              "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz"
979*4a1a9510SRong-En Fan              target="_top">In Multiple HTML pages</a></p>
980*4a1a9510SRong-En Fan            </li>
981*4a1a9510SRong-En Fan
982*4a1a9510SRong-En Fan            <li>
983*4a1a9510SRong-En Fan              <p><a href=
984*4a1a9510SRong-En Fan              "http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html"
985*4a1a9510SRong-En Fan              target="_top">In One big HTML format</a></p>
986*4a1a9510SRong-En Fan            </li>
987*4a1a9510SRong-En Fan          </ul>
988*4a1a9510SRong-En Fan        </div>
989*4a1a9510SRong-En Fan
990*4a1a9510SRong-En Fan        <div class="SECT3">
991*4a1a9510SRong-En Fan          <hr>
992*4a1a9510SRong-En Fan
993*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="BUILDSOURCE" id=
994*4a1a9510SRong-En Fan          "BUILDSOURCE">1.6.2. Building from source</a></h4>
995*4a1a9510SRong-En Fan
996*4a1a9510SRong-En Fan          <p>If above links are broken or if you want to experiment
997*4a1a9510SRong-En Fan          with sgml read on.</p>
998*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
999*4a1a9510SRong-En Fan&#13;    Get both the source and the tar,gzipped programs, available at
1000*4a1a9510SRong-En Fan        http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
1001*4a1a9510SRong-En Fan        NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml
1002*4a1a9510SRong-En Fan        http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/
1003*4a1a9510SRong-En Fan        NCURSES-HOWTO/ncurses_programs.tar.gz
1004*4a1a9510SRong-En Fan
1005*4a1a9510SRong-En Fan    Unzip ncurses_programs.tar.gz with
1006*4a1a9510SRong-En Fan    tar zxvf ncurses_programs.tar.gz
1007*4a1a9510SRong-En Fan
1008*4a1a9510SRong-En Fan    Use jade to create various formats. For example if you just want to create
1009*4a1a9510SRong-En Fan    the multiple html files, you would use
1010*4a1a9510SRong-En Fan        jade -t sgml -i html -d &lt;path to docbook html stylesheet&gt;
1011*4a1a9510SRong-En Fan        NCURSES-Programming-HOWTO.sgml
1012*4a1a9510SRong-En Fan    to get pdf, first create a single html file of the HOWTO with
1013*4a1a9510SRong-En Fan        jade -t sgml -i html -d &lt;path to docbook html stylesheet&gt; -V nochunks
1014*4a1a9510SRong-En Fan        NCURSES-Programming-HOWTO.sgml &gt; NCURSES-ONE-BIG-FILE.html
1015*4a1a9510SRong-En Fan    then use htmldoc to get pdf file with
1016*4a1a9510SRong-En Fan        htmldoc --size universal -t pdf --firstpage p1 -f &lt;output file name.pdf&gt;
1017*4a1a9510SRong-En Fan        NCURSES-ONE-BIG-FILE.html
1018*4a1a9510SRong-En Fan    for ps, you would use
1019*4a1a9510SRong-En Fan        htmldoc --size universal -t ps --firstpage p1 -f &lt;output file name.ps&gt;
1020*4a1a9510SRong-En Fan        NCURSES-ONE-BIG-FILE.html
1021*4a1a9510SRong-En Fan</pre>
1022*4a1a9510SRong-En Fan
1023*4a1a9510SRong-En Fan          <p>See <a href=
1024*4a1a9510SRong-En Fan          "http://www.tldp.org/LDP/LDP-Author-Guide/" target=
1025*4a1a9510SRong-En Fan          "_top">LDP Author guide</a> for more details. If all else
1026*4a1a9510SRong-En Fan          failes, mail me at <a href="[email protected]" target=
1027*4a1a9510SRong-En Fan          "_top">[email protected]</a></p>
1028*4a1a9510SRong-En Fan        </div>
1029*4a1a9510SRong-En Fan      </div>
1030*4a1a9510SRong-En Fan
1031*4a1a9510SRong-En Fan      <div class="SECT2">
1032*4a1a9510SRong-En Fan        <hr>
1033*4a1a9510SRong-En Fan
1034*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="CREDITS" id="CREDITS">1.7.
1035*4a1a9510SRong-En Fan        Credits</a></h3>
1036*4a1a9510SRong-En Fan
1037*4a1a9510SRong-En Fan        <p>I thank <a href="mailto:[email protected]" target=
1038*4a1a9510SRong-En Fan        "_top">Sharath</a> and Emre Akbas for helping me with few
1039*4a1a9510SRong-En Fan        sections. The introduction was initially written by
1040*4a1a9510SRong-En Fan        sharath. I rewrote it with few excerpts taken from his
1041*4a1a9510SRong-En Fan        initial work. Emre helped in writing printw and scanw
1042*4a1a9510SRong-En Fan        sections.</p>
1043*4a1a9510SRong-En Fan
1044*4a1a9510SRong-En Fan        <p>Perl equivalents of the example programs are contributed
1045*4a1a9510SRong-En Fan        by <a href="mailto:[email protected]" target=
1046*4a1a9510SRong-En Fan        "_top">Anuradha Ratnaweera</a>.</p>
1047*4a1a9510SRong-En Fan
1048*4a1a9510SRong-En Fan        <p>Then comes <a href="mailto:[email protected]"
1049*4a1a9510SRong-En Fan        target="_top">Ravi Parimi</a>, my dearest friend, who has
1050*4a1a9510SRong-En Fan        been on this project before even one line was written. He
1051*4a1a9510SRong-En Fan        constantly bombarded me with suggestions and patiently
1052*4a1a9510SRong-En Fan        reviewed the whole text. He also checked each program on
1053*4a1a9510SRong-En Fan        Linux and Solaris.</p>
1054*4a1a9510SRong-En Fan      </div>
1055*4a1a9510SRong-En Fan
1056*4a1a9510SRong-En Fan      <div class="SECT2">
1057*4a1a9510SRong-En Fan        <hr>
1058*4a1a9510SRong-En Fan
1059*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WISHLIST" id="WISHLIST">1.8.
1060*4a1a9510SRong-En Fan        Wish List</a></h3>
1061*4a1a9510SRong-En Fan
1062*4a1a9510SRong-En Fan        <p>This is the wish list, in the order of priority. If you
1063*4a1a9510SRong-En Fan        have a wish or you want to work on completing the wish,
1064*4a1a9510SRong-En Fan        mail <a href="mailto:[email protected]" target=
1065*4a1a9510SRong-En Fan        "_top">me</a>.</p>
1066*4a1a9510SRong-En Fan
1067*4a1a9510SRong-En Fan        <ul>
1068*4a1a9510SRong-En Fan          <li>
1069*4a1a9510SRong-En Fan            <p>Add examples to last parts of forms section.</p>
1070*4a1a9510SRong-En Fan          </li>
1071*4a1a9510SRong-En Fan
1072*4a1a9510SRong-En Fan          <li>
1073*4a1a9510SRong-En Fan            <p>Prepare a Demo showing all the programs and allow
1074*4a1a9510SRong-En Fan            the user to browse through description of each program.
1075*4a1a9510SRong-En Fan            Let the user compile and see the program in action. A
1076*4a1a9510SRong-En Fan            dialog based interface is preferred.</p>
1077*4a1a9510SRong-En Fan          </li>
1078*4a1a9510SRong-En Fan
1079*4a1a9510SRong-En Fan          <li>
1080*4a1a9510SRong-En Fan            <p>Add debug info. _tracef, _tracemouse stuff.</p>
1081*4a1a9510SRong-En Fan          </li>
1082*4a1a9510SRong-En Fan
1083*4a1a9510SRong-En Fan          <li>
1084*4a1a9510SRong-En Fan            <p>Accessing termcap, terminfo using functions provided
1085*4a1a9510SRong-En Fan            by ncurses package.</p>
1086*4a1a9510SRong-En Fan          </li>
1087*4a1a9510SRong-En Fan
1088*4a1a9510SRong-En Fan          <li>
1089*4a1a9510SRong-En Fan            <p>Working on two terminals simultaneously.</p>
1090*4a1a9510SRong-En Fan          </li>
1091*4a1a9510SRong-En Fan
1092*4a1a9510SRong-En Fan          <li>
1093*4a1a9510SRong-En Fan            <p>Add more stuff to miscellaneous section.</p>
1094*4a1a9510SRong-En Fan          </li>
1095*4a1a9510SRong-En Fan        </ul>
1096*4a1a9510SRong-En Fan      </div>
1097*4a1a9510SRong-En Fan
1098*4a1a9510SRong-En Fan      <div class="SECT2">
1099*4a1a9510SRong-En Fan        <hr>
1100*4a1a9510SRong-En Fan
1101*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COPYRIGHT" id="COPYRIGHT">1.9.
1102*4a1a9510SRong-En Fan        Copyright</a></h3>
1103*4a1a9510SRong-En Fan
1104*4a1a9510SRong-En Fan        <p>Copyright &copy; 2001 by Pradeep Padala.</p>
1105*4a1a9510SRong-En Fan
1106*4a1a9510SRong-En Fan        <p>Permission is hereby granted, free of charge, to any
1107*4a1a9510SRong-En Fan        person obtaining a copy of this software and associated
1108*4a1a9510SRong-En Fan        documentation files (the "Software"), to deal in the
1109*4a1a9510SRong-En Fan        Software without restriction, including without limitation
1110*4a1a9510SRong-En Fan        the rights to use, copy, modify, merge, publish,
1111*4a1a9510SRong-En Fan        distribute, distribute with modifications, sublicense,
1112*4a1a9510SRong-En Fan        and/or sell copies of the Software, and to permit persons
1113*4a1a9510SRong-En Fan        to whom the Software is furnished to do so, subject to the
1114*4a1a9510SRong-En Fan        following conditions:</p>
1115*4a1a9510SRong-En Fan
1116*4a1a9510SRong-En Fan        <p>The above copyright notice and this permission notice
1117*4a1a9510SRong-En Fan        shall be included in all copies or substantial portions of
1118*4a1a9510SRong-En Fan        the Software.</p>
1119*4a1a9510SRong-En Fan
1120*4a1a9510SRong-En Fan        <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1121*4a1a9510SRong-En Fan        ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
1122*4a1a9510SRong-En Fan        THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1123*4a1a9510SRong-En Fan        PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE
1124*4a1a9510SRong-En Fan        COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1125*4a1a9510SRong-En Fan        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1126*4a1a9510SRong-En Fan        OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1127*4a1a9510SRong-En Fan        SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
1128*4a1a9510SRong-En Fan
1129*4a1a9510SRong-En Fan        <p>Except as contained in this notice, the name(s) of the
1130*4a1a9510SRong-En Fan        above copyright holders shall not be used in advertising or
1131*4a1a9510SRong-En Fan        otherwise to promote the sale, use or other dealings in
1132*4a1a9510SRong-En Fan        this Software without prior written authorization.</p>
1133*4a1a9510SRong-En Fan      </div>
1134*4a1a9510SRong-En Fan    </div>
1135*4a1a9510SRong-En Fan
1136*4a1a9510SRong-En Fan    <div class="SECT1">
1137*4a1a9510SRong-En Fan      <hr>
1138*4a1a9510SRong-En Fan
1139*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="HELLOWORLD" id="HELLOWORLD">2.
1140*4a1a9510SRong-En Fan      Hello World !!!</a></h2>
1141*4a1a9510SRong-En Fan
1142*4a1a9510SRong-En Fan      <p>Welcome to the world of curses. Before we plunge into the
1143*4a1a9510SRong-En Fan      library and look into its various features, let's write a
1144*4a1a9510SRong-En Fan      simple program and say hello to the world.</p>
1145*4a1a9510SRong-En Fan
1146*4a1a9510SRong-En Fan      <div class="SECT2">
1147*4a1a9510SRong-En Fan        <hr>
1148*4a1a9510SRong-En Fan
1149*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COMPILECURSES" id=
1150*4a1a9510SRong-En Fan        "COMPILECURSES">2.1. Compiling With the NCURSES
1151*4a1a9510SRong-En Fan        Library</a></h3>
1152*4a1a9510SRong-En Fan
1153*4a1a9510SRong-En Fan        <p>To use ncurses library functions, you have to include
1154*4a1a9510SRong-En Fan        ncurses.h in your programs. To link the program with
1155*4a1a9510SRong-En Fan        ncurses the flag -lncurses should be added.</p>
1156*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
1157*4a1a9510SRong-En Fan    #include &lt;ncurses.h&gt;
1158*4a1a9510SRong-En Fan    .
1159*4a1a9510SRong-En Fan    .
1160*4a1a9510SRong-En Fan    .
1161*4a1a9510SRong-En Fan
1162*4a1a9510SRong-En Fan    compile and link: gcc &lt;program file&gt; -lncurses
1163*4a1a9510SRong-En Fan</pre>
1164*4a1a9510SRong-En Fan
1165*4a1a9510SRong-En Fan        <div class="EXAMPLE">
1166*4a1a9510SRong-En Fan          <a name="BHW" id="BHW"></a>
1167*4a1a9510SRong-En Fan
1168*4a1a9510SRong-En Fan          <p><b>Example 1. The Hello World !!! Program</b></p>
1169*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
1170*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
1171*4a1a9510SRong-En Fan
1172*4a1a9510SRong-En Fanint main()
1173*4a1a9510SRong-En Fan{
1174*4a1a9510SRong-En Fan        initscr();                      /* Start curses mode              */
1175*4a1a9510SRong-En Fan        printw("Hello World !!!");      /* Print Hello World              */
1176*4a1a9510SRong-En Fan        refresh();                      /* Print it on to the real screen */
1177*4a1a9510SRong-En Fan        getch();                        /* Wait for user input */
1178*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
1179*4a1a9510SRong-En Fan
1180*4a1a9510SRong-En Fan        return 0;
1181*4a1a9510SRong-En Fan}</span>
1182*4a1a9510SRong-En Fan</pre>
1183*4a1a9510SRong-En Fan        </div>
1184*4a1a9510SRong-En Fan      </div>
1185*4a1a9510SRong-En Fan
1186*4a1a9510SRong-En Fan      <div class="SECT2">
1187*4a1a9510SRong-En Fan        <hr>
1188*4a1a9510SRong-En Fan
1189*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="DISSECTION" id="DISSECTION">2.2.
1190*4a1a9510SRong-En Fan        Dissection</a></h3>
1191*4a1a9510SRong-En Fan
1192*4a1a9510SRong-En Fan        <p>The above program prints "Hello World !!!" to the screen
1193*4a1a9510SRong-En Fan        and exits. This program shows how to initialize curses and
1194*4a1a9510SRong-En Fan        do screen manipulation and end curses mode. Let's dissect
1195*4a1a9510SRong-En Fan        it line by line.</p>
1196*4a1a9510SRong-En Fan
1197*4a1a9510SRong-En Fan        <div class="SECT3">
1198*4a1a9510SRong-En Fan          <hr>
1199*4a1a9510SRong-En Fan
1200*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="ABOUT-INITSCR" id=
1201*4a1a9510SRong-En Fan          "ABOUT-INITSCR">2.2.1. About initscr()</a></h4>
1202*4a1a9510SRong-En Fan
1203*4a1a9510SRong-En Fan          <p>The function initscr() initializes the terminal in
1204*4a1a9510SRong-En Fan          curses mode. In some implementations, it clears the
1205*4a1a9510SRong-En Fan          screen and presents a blank screen. To do any screen
1206*4a1a9510SRong-En Fan          manipulation using curses package this has to be called
1207*4a1a9510SRong-En Fan          first. This function initializes the curses system and
1208*4a1a9510SRong-En Fan          allocates memory for our present window (called
1209*4a1a9510SRong-En Fan          <tt class="LITERAL">stdscr</tt>) and some other
1210*4a1a9510SRong-En Fan          data-structures. Under extreme cases this function might
1211*4a1a9510SRong-En Fan          fail due to insufficient memory to allocate memory for
1212*4a1a9510SRong-En Fan          curses library's data structures.</p>
1213*4a1a9510SRong-En Fan
1214*4a1a9510SRong-En Fan          <p>After this is done, we can do a variety of
1215*4a1a9510SRong-En Fan          initializations to customize our curses settings. These
1216*4a1a9510SRong-En Fan          details will be explained <a href="#INIT">later</a> .</p>
1217*4a1a9510SRong-En Fan        </div>
1218*4a1a9510SRong-En Fan
1219*4a1a9510SRong-En Fan        <div class="SECT3">
1220*4a1a9510SRong-En Fan          <hr>
1221*4a1a9510SRong-En Fan
1222*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="MYST-REFRESH" id=
1223*4a1a9510SRong-En Fan          "MYST-REFRESH">2.2.2. The mysterious refresh()</a></h4>
1224*4a1a9510SRong-En Fan
1225*4a1a9510SRong-En Fan          <p>The next line printw prints the string "Hello World
1226*4a1a9510SRong-En Fan          !!!" on to the screen. This function is analogous to
1227*4a1a9510SRong-En Fan          normal printf in all respects except that it prints the
1228*4a1a9510SRong-En Fan          data on a window called stdscr at the current (y,x)
1229*4a1a9510SRong-En Fan          co-ordinates. Since our present co-ordinates are at 0,0
1230*4a1a9510SRong-En Fan          the string is printed at the left hand corner of the
1231*4a1a9510SRong-En Fan          window.</p>
1232*4a1a9510SRong-En Fan
1233*4a1a9510SRong-En Fan          <p>This brings us to that mysterious refresh(). Well,
1234*4a1a9510SRong-En Fan          when we called printw the data is actually written to an
1235*4a1a9510SRong-En Fan          imaginary window, which is not updated on the screen yet.
1236*4a1a9510SRong-En Fan          The job of printw is to update a few flags and data
1237*4a1a9510SRong-En Fan          structures and write the data to a buffer corresponding
1238*4a1a9510SRong-En Fan          to stdscr. In order to show it on the screen, we need to
1239*4a1a9510SRong-En Fan          call refresh() and tell the curses system to dump the
1240*4a1a9510SRong-En Fan          contents on the screen.</p>
1241*4a1a9510SRong-En Fan
1242*4a1a9510SRong-En Fan          <p>The philosophy behind all this is to allow the
1243*4a1a9510SRong-En Fan          programmer to do multiple updates on the imaginary screen
1244*4a1a9510SRong-En Fan          or windows and do a refresh once all his screen update is
1245*4a1a9510SRong-En Fan          done. refresh() checks the window and updates only the
1246*4a1a9510SRong-En Fan          portion which has been changed. This improves performance
1247*4a1a9510SRong-En Fan          and offers greater flexibility too. But, it is sometimes
1248*4a1a9510SRong-En Fan          frustrating to beginners. A common mistake committed by
1249*4a1a9510SRong-En Fan          beginners is to forget to call refresh() after they did
1250*4a1a9510SRong-En Fan          some update through printw() class of functions. I still
1251*4a1a9510SRong-En Fan          forget to add it sometimes :-)</p>
1252*4a1a9510SRong-En Fan        </div>
1253*4a1a9510SRong-En Fan
1254*4a1a9510SRong-En Fan        <div class="SECT3">
1255*4a1a9510SRong-En Fan          <hr>
1256*4a1a9510SRong-En Fan
1257*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="ABOUT-ENDWIN" id=
1258*4a1a9510SRong-En Fan          "ABOUT-ENDWIN">2.2.3. About endwin()</a></h4>
1259*4a1a9510SRong-En Fan
1260*4a1a9510SRong-En Fan          <p>And finally don't forget to end the curses mode.
1261*4a1a9510SRong-En Fan          Otherwise your terminal might behave strangely after the
1262*4a1a9510SRong-En Fan          program quits. endwin() frees the memory taken by curses
1263*4a1a9510SRong-En Fan          sub-system and its data structures and puts the terminal
1264*4a1a9510SRong-En Fan          in normal mode. This function must be called after you
1265*4a1a9510SRong-En Fan          are done with the curses mode.</p>
1266*4a1a9510SRong-En Fan        </div>
1267*4a1a9510SRong-En Fan      </div>
1268*4a1a9510SRong-En Fan    </div>
1269*4a1a9510SRong-En Fan
1270*4a1a9510SRong-En Fan    <div class="SECT1">
1271*4a1a9510SRong-En Fan      <hr>
1272*4a1a9510SRong-En Fan
1273*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="GORY" id="GORY">3. The Gory
1274*4a1a9510SRong-En Fan      Details</a></h2>
1275*4a1a9510SRong-En Fan
1276*4a1a9510SRong-En Fan      <p>Now that we have seen how to write a simple curses program
1277*4a1a9510SRong-En Fan      let's get into the details. There are many functions that
1278*4a1a9510SRong-En Fan      help customize what you see on screen and many features which
1279*4a1a9510SRong-En Fan      can be put to full use.</p>
1280*4a1a9510SRong-En Fan
1281*4a1a9510SRong-En Fan      <p>Here we go...</p>
1282*4a1a9510SRong-En Fan    </div>
1283*4a1a9510SRong-En Fan
1284*4a1a9510SRong-En Fan    <div class="SECT1">
1285*4a1a9510SRong-En Fan      <hr>
1286*4a1a9510SRong-En Fan
1287*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="INIT" id="INIT">4.
1288*4a1a9510SRong-En Fan      Initialization</a></h2>
1289*4a1a9510SRong-En Fan
1290*4a1a9510SRong-En Fan      <p>We now know that to initialize curses system the function
1291*4a1a9510SRong-En Fan      initscr() has to be called. There are functions which can be
1292*4a1a9510SRong-En Fan      called after this initialization to customize our curses
1293*4a1a9510SRong-En Fan      session. We may ask the curses system to set the terminal in
1294*4a1a9510SRong-En Fan      raw mode or initialize color or initialize the mouse etc..
1295*4a1a9510SRong-En Fan      Let's discuss some of the functions that are normally called
1296*4a1a9510SRong-En Fan      immediately after initscr();</p>
1297*4a1a9510SRong-En Fan
1298*4a1a9510SRong-En Fan      <div class="SECT2">
1299*4a1a9510SRong-En Fan        <hr>
1300*4a1a9510SRong-En Fan
1301*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ABOUTINIT" id="ABOUTINIT">4.1.
1302*4a1a9510SRong-En Fan        Initialization functions</a></h3>
1303*4a1a9510SRong-En Fan      </div>
1304*4a1a9510SRong-En Fan
1305*4a1a9510SRong-En Fan      <div class="SECT2">
1306*4a1a9510SRong-En Fan        <hr>
1307*4a1a9510SRong-En Fan
1308*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="RAWCBREAK" id="RAWCBREAK">4.2.
1309*4a1a9510SRong-En Fan        raw() and cbreak()</a></h3>
1310*4a1a9510SRong-En Fan
1311*4a1a9510SRong-En Fan        <p>Normally the terminal driver buffers the characters a
1312*4a1a9510SRong-En Fan        user types until a new line or carriage return is
1313*4a1a9510SRong-En Fan        encountered. But most programs require that the characters
1314*4a1a9510SRong-En Fan        be available as soon as the user types them. The above two
1315*4a1a9510SRong-En Fan        functions are used to disable line buffering. The
1316*4a1a9510SRong-En Fan        difference between these two functions is in the way
1317*4a1a9510SRong-En Fan        control characters like suspend (CTRL-Z), interrupt and
1318*4a1a9510SRong-En Fan        quit (CTRL-C) are passed to the program. In the raw() mode
1319*4a1a9510SRong-En Fan        these characters are directly passed to the program without
1320*4a1a9510SRong-En Fan        generating a signal. In the <tt class=
1321*4a1a9510SRong-En Fan        "LITERAL">cbreak()</tt> mode these control characters are
1322*4a1a9510SRong-En Fan        interpreted as any other character by the terminal driver.
1323*4a1a9510SRong-En Fan        I personally prefer to use raw() as I can exercise greater
1324*4a1a9510SRong-En Fan        control over what the user does.</p>
1325*4a1a9510SRong-En Fan      </div>
1326*4a1a9510SRong-En Fan
1327*4a1a9510SRong-En Fan      <div class="SECT2">
1328*4a1a9510SRong-En Fan        <hr>
1329*4a1a9510SRong-En Fan
1330*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ECHONOECHO" id="ECHONOECHO">4.3.
1331*4a1a9510SRong-En Fan        echo() and noecho()</a></h3>
1332*4a1a9510SRong-En Fan
1333*4a1a9510SRong-En Fan        <p>These functions control the echoing of characters typed
1334*4a1a9510SRong-En Fan        by the user to the terminal. <tt class=
1335*4a1a9510SRong-En Fan        "LITERAL">noecho()</tt> switches off echoing. The reason
1336*4a1a9510SRong-En Fan        you might want to do this is to gain more control over
1337*4a1a9510SRong-En Fan        echoing or to suppress unnecessary echoing while taking
1338*4a1a9510SRong-En Fan        input from the user through the getch() etc. functions.
1339*4a1a9510SRong-En Fan        Most of the interactive programs call <tt class=
1340*4a1a9510SRong-En Fan        "LITERAL">noecho()</tt> at initialization and do the
1341*4a1a9510SRong-En Fan        echoing of characters in a controlled manner. It gives the
1342*4a1a9510SRong-En Fan        programmer the flexibility of echoing characters at any
1343*4a1a9510SRong-En Fan        place in the window without updating current (y,x)
1344*4a1a9510SRong-En Fan        co-ordinates.</p>
1345*4a1a9510SRong-En Fan      </div>
1346*4a1a9510SRong-En Fan
1347*4a1a9510SRong-En Fan      <div class="SECT2">
1348*4a1a9510SRong-En Fan        <hr>
1349*4a1a9510SRong-En Fan
1350*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="KEYPAD" id="KEYPAD">4.4.
1351*4a1a9510SRong-En Fan        keypad()</a></h3>
1352*4a1a9510SRong-En Fan
1353*4a1a9510SRong-En Fan        <p>This is my favorite initialization function. It enables
1354*4a1a9510SRong-En Fan        the reading of function keys like F1, F2, arrow keys etc.
1355*4a1a9510SRong-En Fan        Almost every interactive program enables this, as arrow
1356*4a1a9510SRong-En Fan        keys are a major part of any User Interface. Do <tt class=
1357*4a1a9510SRong-En Fan        "LITERAL">keypad(stdscr, TRUE)</tt> to enable this feature
1358*4a1a9510SRong-En Fan        for the regular screen (stdscr). You will learn more about
1359*4a1a9510SRong-En Fan        key management in later sections of this document.</p>
1360*4a1a9510SRong-En Fan      </div>
1361*4a1a9510SRong-En Fan
1362*4a1a9510SRong-En Fan      <div class="SECT2">
1363*4a1a9510SRong-En Fan        <hr>
1364*4a1a9510SRong-En Fan
1365*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="HALFDELAY" id="HALFDELAY">4.5.
1366*4a1a9510SRong-En Fan        halfdelay()</a></h3>
1367*4a1a9510SRong-En Fan
1368*4a1a9510SRong-En Fan        <p>This function, though not used very often, is a useful
1369*4a1a9510SRong-En Fan        one at times. halfdelay()is called to enable the half-delay
1370*4a1a9510SRong-En Fan        mode, which is similar to the cbreak() mode in that
1371*4a1a9510SRong-En Fan        characters typed are immediately available to program.
1372*4a1a9510SRong-En Fan        However, it waits for 'X' tenths of a second for input and
1373*4a1a9510SRong-En Fan        then returns ERR, if no input is available. 'X' is the
1374*4a1a9510SRong-En Fan        timeout value passed to the function halfdelay(). This
1375*4a1a9510SRong-En Fan        function is useful when you want to ask the user for input,
1376*4a1a9510SRong-En Fan        and if he doesn't respond with in certain time, we can do
1377*4a1a9510SRong-En Fan        some thing else. One possible example is a timeout at the
1378*4a1a9510SRong-En Fan        password prompt.</p>
1379*4a1a9510SRong-En Fan      </div>
1380*4a1a9510SRong-En Fan
1381*4a1a9510SRong-En Fan      <div class="SECT2">
1382*4a1a9510SRong-En Fan        <hr>
1383*4a1a9510SRong-En Fan
1384*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MISCINIT" id="MISCINIT">4.6.
1385*4a1a9510SRong-En Fan        Miscellaneous Initialization functions</a></h3>
1386*4a1a9510SRong-En Fan
1387*4a1a9510SRong-En Fan        <p>There are few more functions which are called at
1388*4a1a9510SRong-En Fan        initialization to customize curses behavior. They are not
1389*4a1a9510SRong-En Fan        used as extensively as those mentioned above. Some of them
1390*4a1a9510SRong-En Fan        are explained where appropriate.</p>
1391*4a1a9510SRong-En Fan      </div>
1392*4a1a9510SRong-En Fan
1393*4a1a9510SRong-En Fan      <div class="SECT2">
1394*4a1a9510SRong-En Fan        <hr>
1395*4a1a9510SRong-En Fan
1396*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="INITEX" id="INITEX">4.7. An
1397*4a1a9510SRong-En Fan        Example</a></h3>
1398*4a1a9510SRong-En Fan
1399*4a1a9510SRong-En Fan        <p>Let's write a program which will clarify the usage of
1400*4a1a9510SRong-En Fan        these functions.</p>
1401*4a1a9510SRong-En Fan
1402*4a1a9510SRong-En Fan        <div class="EXAMPLE">
1403*4a1a9510SRong-En Fan          <a name="BINFU" id="BINFU"></a>
1404*4a1a9510SRong-En Fan
1405*4a1a9510SRong-En Fan          <p><b>Example 2. Initialization Function Usage
1406*4a1a9510SRong-En Fan          example</b></p>
1407*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
1408*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
1409*4a1a9510SRong-En Fan
1410*4a1a9510SRong-En Fanint main()
1411*4a1a9510SRong-En Fan{       int ch;
1412*4a1a9510SRong-En Fan
1413*4a1a9510SRong-En Fan        initscr();                      /* Start curses mode            */
1414*4a1a9510SRong-En Fan        raw();                          /* Line buffering disabled      */
1415*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);           /* We get F1, F2 etc..          */
1416*4a1a9510SRong-En Fan        noecho();                       /* Don't echo() while we do getch */
1417*4a1a9510SRong-En Fan
1418*4a1a9510SRong-En Fan        printw("Type any character to see it in bold\n");
1419*4a1a9510SRong-En Fan        ch = getch();                   /* If raw() hadn't been called
1420*4a1a9510SRong-En Fan                                         * we have to press enter before it
1421*4a1a9510SRong-En Fan                                         * gets to the program          */
1422*4a1a9510SRong-En Fan        if(ch == KEY_F(1))              /* Without keypad enabled this will */
1423*4a1a9510SRong-En Fan                printw("F1 Key pressed");/*  not get to us either       */
1424*4a1a9510SRong-En Fan                                        /* Without noecho() some ugly escape
1425*4a1a9510SRong-En Fan                                         * charachters might have been printed
1426*4a1a9510SRong-En Fan                                         * on screen                    */
1427*4a1a9510SRong-En Fan        else
1428*4a1a9510SRong-En Fan        {       printw("The pressed key is ");
1429*4a1a9510SRong-En Fan                attron(A_BOLD);
1430*4a1a9510SRong-En Fan                printw("%c", ch);
1431*4a1a9510SRong-En Fan                attroff(A_BOLD);
1432*4a1a9510SRong-En Fan        }
1433*4a1a9510SRong-En Fan        refresh();                      /* Print it on to the real screen */
1434*4a1a9510SRong-En Fan        getch();                        /* Wait for user input */
1435*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
1436*4a1a9510SRong-En Fan
1437*4a1a9510SRong-En Fan        return 0;
1438*4a1a9510SRong-En Fan}</span>
1439*4a1a9510SRong-En Fan</pre>
1440*4a1a9510SRong-En Fan        </div>
1441*4a1a9510SRong-En Fan
1442*4a1a9510SRong-En Fan        <p>This program is self-explanatory. But I used functions
1443*4a1a9510SRong-En Fan        which aren't explained yet. The function <tt class=
1444*4a1a9510SRong-En Fan        "LITERAL">getch()</tt> is used to get a character from
1445*4a1a9510SRong-En Fan        user. It is equivalent to normal <tt class=
1446*4a1a9510SRong-En Fan        "LITERAL">getchar()</tt> except that we can disable the
1447*4a1a9510SRong-En Fan        line buffering to avoid &lt;enter&gt; after input. Look for
1448*4a1a9510SRong-En Fan        more about <tt class="LITERAL">getch()</tt>and reading keys
1449*4a1a9510SRong-En Fan        in the <a href="#KEYS">key management section</a> . The
1450*4a1a9510SRong-En Fan        functions attron and attroff are used to switch some
1451*4a1a9510SRong-En Fan        attributes on and off respectively. In the example I used
1452*4a1a9510SRong-En Fan        them to print the character in bold. These functions are
1453*4a1a9510SRong-En Fan        explained in detail later.</p>
1454*4a1a9510SRong-En Fan      </div>
1455*4a1a9510SRong-En Fan    </div>
1456*4a1a9510SRong-En Fan
1457*4a1a9510SRong-En Fan    <div class="SECT1">
1458*4a1a9510SRong-En Fan      <hr>
1459*4a1a9510SRong-En Fan
1460*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="AWORDWINDOWS" id="AWORDWINDOWS">5.
1461*4a1a9510SRong-En Fan      A Word about Windows</a></h2>
1462*4a1a9510SRong-En Fan
1463*4a1a9510SRong-En Fan      <p>Before we plunge into the myriad ncurses functions, let me
1464*4a1a9510SRong-En Fan      clear few things about windows. Windows are explained in
1465*4a1a9510SRong-En Fan      detail in following <a href="#WINDOWS">sections</a></p>
1466*4a1a9510SRong-En Fan
1467*4a1a9510SRong-En Fan      <p>A Window is an imaginary screen defined by curses system.
1468*4a1a9510SRong-En Fan      A window does not mean a bordered window which you usually
1469*4a1a9510SRong-En Fan      see on Win9X platforms. When curses is initialized, it
1470*4a1a9510SRong-En Fan      creates a default window named <tt class=
1471*4a1a9510SRong-En Fan      "LITERAL">stdscr</tt> which represents your 80x25 (or the
1472*4a1a9510SRong-En Fan      size of window in which you are running) screen. If you are
1473*4a1a9510SRong-En Fan      doing simple tasks like printing few strings, reading input
1474*4a1a9510SRong-En Fan      etc., you can safely use this single window for all of your
1475*4a1a9510SRong-En Fan      purposes. You can also create windows and call functions
1476*4a1a9510SRong-En Fan      which explicitly work on the specified window.</p>
1477*4a1a9510SRong-En Fan
1478*4a1a9510SRong-En Fan      <p>For example, if you call</p>
1479*4a1a9510SRong-En Fan      <pre class="PROGRAMLISTING">
1480*4a1a9510SRong-En Fan    printw("Hi There !!!");
1481*4a1a9510SRong-En Fan    refresh();
1482*4a1a9510SRong-En Fan</pre>
1483*4a1a9510SRong-En Fan
1484*4a1a9510SRong-En Fan      <p>It prints the string on stdscr at the present cursor
1485*4a1a9510SRong-En Fan      position. Similarly the call to refresh(), works on stdscr
1486*4a1a9510SRong-En Fan      only.</p>
1487*4a1a9510SRong-En Fan
1488*4a1a9510SRong-En Fan      <p>Say you have created <a href="#WINDOWS">windows</a> then
1489*4a1a9510SRong-En Fan      you have to call a function with a 'w' added to the usual
1490*4a1a9510SRong-En Fan      function.</p>
1491*4a1a9510SRong-En Fan      <pre class="PROGRAMLISTING">
1492*4a1a9510SRong-En Fan    wprintw(win, "Hi There !!!");
1493*4a1a9510SRong-En Fan    wrefresh(win);
1494*4a1a9510SRong-En Fan</pre>
1495*4a1a9510SRong-En Fan
1496*4a1a9510SRong-En Fan      <p>As you will see in the rest of the document, naming of
1497*4a1a9510SRong-En Fan      functions follow the same convention. For each function there
1498*4a1a9510SRong-En Fan      usually are three more functions.</p>
1499*4a1a9510SRong-En Fan      <pre class="PROGRAMLISTING">
1500*4a1a9510SRong-En Fan    printw(string);        /* Print on stdscr at present cursor position */
1501*4a1a9510SRong-En Fan    mvprintw(y, x, string);/* Move to (y, x) then print string     */
1502*4a1a9510SRong-En Fan    wprintw(win, string);  /* Print on window win at present cursor position */
1503*4a1a9510SRong-En Fan                           /* in the window */
1504*4a1a9510SRong-En Fan    mvwprintw(win, y, x, string);   /* Move to (y, x) relative to window */
1505*4a1a9510SRong-En Fan                                    /* co-ordinates and then print         */
1506*4a1a9510SRong-En Fan</pre>
1507*4a1a9510SRong-En Fan
1508*4a1a9510SRong-En Fan      <p>Usually the w-less functions are macros which expand to
1509*4a1a9510SRong-En Fan      corresponding w-function with stdscr as the window
1510*4a1a9510SRong-En Fan      parameter.</p>
1511*4a1a9510SRong-En Fan    </div>
1512*4a1a9510SRong-En Fan
1513*4a1a9510SRong-En Fan    <div class="SECT1">
1514*4a1a9510SRong-En Fan      <hr>
1515*4a1a9510SRong-En Fan
1516*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="PRINTW" id="PRINTW">6. Output
1517*4a1a9510SRong-En Fan      functions</a></h2>
1518*4a1a9510SRong-En Fan
1519*4a1a9510SRong-En Fan      <p>I guess you can't wait any more to see some action. Back
1520*4a1a9510SRong-En Fan      to our odyssey of curses functions. Now that curses is
1521*4a1a9510SRong-En Fan      initialized, let's interact with world.</p>
1522*4a1a9510SRong-En Fan
1523*4a1a9510SRong-En Fan      <p>There are three classes of functions which you can use to
1524*4a1a9510SRong-En Fan      do output on screen.</p>
1525*4a1a9510SRong-En Fan
1526*4a1a9510SRong-En Fan      <ol type="1">
1527*4a1a9510SRong-En Fan        <li>
1528*4a1a9510SRong-En Fan          <p>addch() class: Print single character with
1529*4a1a9510SRong-En Fan          attributes</p>
1530*4a1a9510SRong-En Fan        </li>
1531*4a1a9510SRong-En Fan
1532*4a1a9510SRong-En Fan        <li>
1533*4a1a9510SRong-En Fan          <p>printw() class: Print formatted output similar to
1534*4a1a9510SRong-En Fan          printf()</p>
1535*4a1a9510SRong-En Fan        </li>
1536*4a1a9510SRong-En Fan
1537*4a1a9510SRong-En Fan        <li>
1538*4a1a9510SRong-En Fan          <p>addstr() class: Print strings</p>
1539*4a1a9510SRong-En Fan        </li>
1540*4a1a9510SRong-En Fan      </ol>
1541*4a1a9510SRong-En Fan
1542*4a1a9510SRong-En Fan      <p>These functions can be used interchangeably and it's a
1543*4a1a9510SRong-En Fan      matter of style as to which class is used. Let's see each one
1544*4a1a9510SRong-En Fan      in detail.</p>
1545*4a1a9510SRong-En Fan
1546*4a1a9510SRong-En Fan      <div class="SECT2">
1547*4a1a9510SRong-En Fan        <hr>
1548*4a1a9510SRong-En Fan
1549*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ADDCHCLASS" id="ADDCHCLASS">6.1.
1550*4a1a9510SRong-En Fan        addch() class of functions</a></h3>
1551*4a1a9510SRong-En Fan
1552*4a1a9510SRong-En Fan        <p>These functions put a single character into the current
1553*4a1a9510SRong-En Fan        cursor location and advance the position of the cursor. You
1554*4a1a9510SRong-En Fan        can give the character to be printed but they usually are
1555*4a1a9510SRong-En Fan        used to print a character with some attributes. Attributes
1556*4a1a9510SRong-En Fan        are explained in detail in later <a href=
1557*4a1a9510SRong-En Fan        "#ATTRIB">sections</a> of the document. If a character is
1558*4a1a9510SRong-En Fan        associated with an attribute(bold, reverse video etc.),
1559*4a1a9510SRong-En Fan        when curses prints the character, it is printed in that
1560*4a1a9510SRong-En Fan        attribute.</p>
1561*4a1a9510SRong-En Fan
1562*4a1a9510SRong-En Fan        <p>In order to combine a character with some attributes,
1563*4a1a9510SRong-En Fan        you have two options:</p>
1564*4a1a9510SRong-En Fan
1565*4a1a9510SRong-En Fan        <ul>
1566*4a1a9510SRong-En Fan          <li>
1567*4a1a9510SRong-En Fan            <p>By OR'ing a single character with the desired
1568*4a1a9510SRong-En Fan            attribute macros. These attribute macros could be found
1569*4a1a9510SRong-En Fan            in the header file <tt class="LITERAL">ncurses.h</tt>.
1570*4a1a9510SRong-En Fan            For example, you want to print a character ch(of type
1571*4a1a9510SRong-En Fan            char) bold and underlined, you would call addch() as
1572*4a1a9510SRong-En Fan            below.</p>
1573*4a1a9510SRong-En Fan            <pre class="PROGRAMLISTING">
1574*4a1a9510SRong-En Fan    addch(ch | A_BOLD | A_UNDERLINE);
1575*4a1a9510SRong-En Fan</pre>
1576*4a1a9510SRong-En Fan          </li>
1577*4a1a9510SRong-En Fan
1578*4a1a9510SRong-En Fan          <li>
1579*4a1a9510SRong-En Fan            <p>By using functions like <tt class=
1580*4a1a9510SRong-En Fan            "LITERAL">attrset(),attron(),attroff()</tt>. These
1581*4a1a9510SRong-En Fan            functions are explained in the <a href=
1582*4a1a9510SRong-En Fan            "#ATTRIB">Attributes</a> section. Briefly, they
1583*4a1a9510SRong-En Fan            manipulate the current attributes of the given window.
1584*4a1a9510SRong-En Fan            Once set, the character printed in the window are
1585*4a1a9510SRong-En Fan            associated with the attributes until it is turned
1586*4a1a9510SRong-En Fan            off.</p>
1587*4a1a9510SRong-En Fan          </li>
1588*4a1a9510SRong-En Fan        </ul>
1589*4a1a9510SRong-En Fan
1590*4a1a9510SRong-En Fan        <p>Additionally, <tt class="LITERAL">curses</tt> provides
1591*4a1a9510SRong-En Fan        some special characters for character-based graphics. You
1592*4a1a9510SRong-En Fan        can draw tables, horizontal or vertical lines, etc. You can
1593*4a1a9510SRong-En Fan        find all avaliable characters in the header file <tt class=
1594*4a1a9510SRong-En Fan        "LITERAL">ncurses.h</tt>. Try looking for macros beginning
1595*4a1a9510SRong-En Fan        with <tt class="LITERAL">ACS_</tt> in this file.</p>
1596*4a1a9510SRong-En Fan      </div>
1597*4a1a9510SRong-En Fan
1598*4a1a9510SRong-En Fan      <div class="SECT2">
1599*4a1a9510SRong-En Fan        <hr>
1600*4a1a9510SRong-En Fan
1601*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="AEN298" id="AEN298">6.2.
1602*4a1a9510SRong-En Fan        mvaddch(), waddch() and mvwaddch()</a></h3>
1603*4a1a9510SRong-En Fan
1604*4a1a9510SRong-En Fan        <p><tt class="LITERAL">mvaddch()</tt> is used to move the
1605*4a1a9510SRong-En Fan        cursor to a given point, and then print. Thus, the
1606*4a1a9510SRong-En Fan        calls:</p>
1607*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
1608*4a1a9510SRong-En Fan    move(row,col);    /* moves the cursor to row<span class=
1609*4a1a9510SRong-En Fan"emphasis"><i class=
1610*4a1a9510SRong-En Fan"EMPHASIS">th</i></span> row and col<span class="emphasis"><i class="EMPHASIS">th</i></span> column */
1611*4a1a9510SRong-En Fan    addch(ch);
1612*4a1a9510SRong-En Fan</pre>can be replaced by
1613*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
1614*4a1a9510SRong-En Fan    mvaddch(row,col,ch);
1615*4a1a9510SRong-En Fan</pre>
1616*4a1a9510SRong-En Fan
1617*4a1a9510SRong-En Fan        <p><tt class="LITERAL">waddch()</tt> is similar to
1618*4a1a9510SRong-En Fan        <tt class="LITERAL">addch()</tt>, except that it adds a
1619*4a1a9510SRong-En Fan        character into the given window. (Note that <tt class=
1620*4a1a9510SRong-En Fan        "LITERAL">addch()</tt> adds a character into the window
1621*4a1a9510SRong-En Fan        <tt class="LITERAL">stdscr</tt>.)</p>
1622*4a1a9510SRong-En Fan
1623*4a1a9510SRong-En Fan        <p>In a similar fashion <tt class="LITERAL">mvwaddch()</tt>
1624*4a1a9510SRong-En Fan        function is used to add a character into the given window
1625*4a1a9510SRong-En Fan        at the given coordinates.</p>
1626*4a1a9510SRong-En Fan
1627*4a1a9510SRong-En Fan        <p>Now, we are familiar with the basic output function
1628*4a1a9510SRong-En Fan        <tt class="LITERAL">addch()</tt>. But, if we want to print
1629*4a1a9510SRong-En Fan        a string, it would be very annoying to print it character
1630*4a1a9510SRong-En Fan        by character. Fortunately, <tt class="LITERAL">ncurses</tt>
1631*4a1a9510SRong-En Fan        provides <tt class="LITERAL">printf</tt><span class=
1632*4a1a9510SRong-En Fan        "emphasis"><i class="EMPHASIS">-like</i></span> or
1633*4a1a9510SRong-En Fan        <tt class="LITERAL">puts</tt><span class=
1634*4a1a9510SRong-En Fan        "emphasis"><i class="EMPHASIS">-like</i></span>
1635*4a1a9510SRong-En Fan        functions.</p>
1636*4a1a9510SRong-En Fan      </div>
1637*4a1a9510SRong-En Fan
1638*4a1a9510SRong-En Fan      <div class="SECT2">
1639*4a1a9510SRong-En Fan        <hr>
1640*4a1a9510SRong-En Fan
1641*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PRINTWCLASS" id=
1642*4a1a9510SRong-En Fan        "PRINTWCLASS">6.3. printw() class of functions</a></h3>
1643*4a1a9510SRong-En Fan
1644*4a1a9510SRong-En Fan        <p>These functions are similar to <tt class=
1645*4a1a9510SRong-En Fan        "LITERAL">printf()</tt> with the added capability of
1646*4a1a9510SRong-En Fan        printing at any position on the screen.</p>
1647*4a1a9510SRong-En Fan
1648*4a1a9510SRong-En Fan        <div class="SECT3">
1649*4a1a9510SRong-En Fan          <hr>
1650*4a1a9510SRong-En Fan
1651*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="PRINTWMVPRINTW" id=
1652*4a1a9510SRong-En Fan          "PRINTWMVPRINTW">6.3.1. printw() and mvprintw</a></h4>
1653*4a1a9510SRong-En Fan
1654*4a1a9510SRong-En Fan          <p>These two functions work much like <tt class=
1655*4a1a9510SRong-En Fan          "LITERAL">printf()</tt>. <tt class=
1656*4a1a9510SRong-En Fan          "LITERAL">mvprintw()</tt> can be used to move the cursor
1657*4a1a9510SRong-En Fan          to a position and then print. If you want to move the
1658*4a1a9510SRong-En Fan          cursor first and then print using <tt class=
1659*4a1a9510SRong-En Fan          "LITERAL">printw()</tt> function, use <tt class=
1660*4a1a9510SRong-En Fan          "LITERAL">move()</tt> first and then use <tt class=
1661*4a1a9510SRong-En Fan          "LITERAL">printw()</tt> though I see no point why one
1662*4a1a9510SRong-En Fan          should avoid using <tt class="LITERAL">mvprintw()</tt>,
1663*4a1a9510SRong-En Fan          you have the flexibility to manipulate.</p>
1664*4a1a9510SRong-En Fan        </div>
1665*4a1a9510SRong-En Fan
1666*4a1a9510SRong-En Fan        <div class="SECT3">
1667*4a1a9510SRong-En Fan          <hr>
1668*4a1a9510SRong-En Fan
1669*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="WPRINTWMVWPRINTW" id=
1670*4a1a9510SRong-En Fan          "WPRINTWMVWPRINTW">6.3.2. wprintw() and
1671*4a1a9510SRong-En Fan          mvwprintw</a></h4>
1672*4a1a9510SRong-En Fan
1673*4a1a9510SRong-En Fan          <p>These two functions are similar to above two except
1674*4a1a9510SRong-En Fan          that they print in the corresponding window given as
1675*4a1a9510SRong-En Fan          argument.</p>
1676*4a1a9510SRong-En Fan        </div>
1677*4a1a9510SRong-En Fan
1678*4a1a9510SRong-En Fan        <div class="SECT3">
1679*4a1a9510SRong-En Fan          <hr>
1680*4a1a9510SRong-En Fan
1681*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="VWPRINTW" id="VWPRINTW">6.3.3.
1682*4a1a9510SRong-En Fan          vw_printw()</a></h4>
1683*4a1a9510SRong-En Fan
1684*4a1a9510SRong-En Fan          <p>This function is similar to <tt class=
1685*4a1a9510SRong-En Fan          "LITERAL">vprintf()</tt>. This can be used when variable
1686*4a1a9510SRong-En Fan          number of arguments are to be printed.</p>
1687*4a1a9510SRong-En Fan        </div>
1688*4a1a9510SRong-En Fan
1689*4a1a9510SRong-En Fan        <div class="SECT3">
1690*4a1a9510SRong-En Fan          <hr>
1691*4a1a9510SRong-En Fan
1692*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="SIMPLEPRINTWEX" id=
1693*4a1a9510SRong-En Fan          "SIMPLEPRINTWEX">6.3.4. A Simple printw example</a></h4>
1694*4a1a9510SRong-En Fan
1695*4a1a9510SRong-En Fan          <div class="EXAMPLE">
1696*4a1a9510SRong-En Fan            <a name="BPREX" id="BPREX"></a>
1697*4a1a9510SRong-En Fan
1698*4a1a9510SRong-En Fan            <p><b>Example 3. A Simple printw example</b></p>
1699*4a1a9510SRong-En Fan            <pre class="PROGRAMLISTING">
1700*4a1a9510SRong-En Fan<span class=
1701*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;                   /* ncurses.h includes stdio.h */
1702*4a1a9510SRong-En Fan#include &lt;string.h&gt;
1703*4a1a9510SRong-En Fan
1704*4a1a9510SRong-En Fanint main()
1705*4a1a9510SRong-En Fan{
1706*4a1a9510SRong-En Fan char mesg[]="Just a string";           /* message to be appeared on the screen */
1707*4a1a9510SRong-En Fan int row,col;                           /* to store the number of rows and *
1708*4a1a9510SRong-En Fan                                         * the number of colums of the screen */
1709*4a1a9510SRong-En Fan initscr();                             /* start the curses mode */
1710*4a1a9510SRong-En Fan getmaxyx(stdscr,row,col);              /* get the number of rows and columns */
1711*4a1a9510SRong-En Fan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
1712*4a1a9510SRong-En Fan                                        /* print the message at the center of the screen */
1713*4a1a9510SRong-En Fan mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col);
1714*4a1a9510SRong-En Fan printw("Try resizing your window(if possible) and then run this program again");
1715*4a1a9510SRong-En Fan refresh();
1716*4a1a9510SRong-En Fan getch();
1717*4a1a9510SRong-En Fan endwin();
1718*4a1a9510SRong-En Fan
1719*4a1a9510SRong-En Fan return 0;
1720*4a1a9510SRong-En Fan}</span>
1721*4a1a9510SRong-En Fan</pre>
1722*4a1a9510SRong-En Fan          </div>
1723*4a1a9510SRong-En Fan
1724*4a1a9510SRong-En Fan          <p>Above program demonstrates how easy it is to use
1725*4a1a9510SRong-En Fan          <tt class="LITERAL">printw</tt>. You just feed the
1726*4a1a9510SRong-En Fan          coordinates and the message to be appeared on the screen,
1727*4a1a9510SRong-En Fan          then it does what you want.</p>
1728*4a1a9510SRong-En Fan
1729*4a1a9510SRong-En Fan          <p>The above program introduces us to a new function
1730*4a1a9510SRong-En Fan          <tt class="LITERAL">getmaxyx()</tt>, a macro defined in
1731*4a1a9510SRong-En Fan          <tt class="LITERAL">ncurses.h</tt>. It gives the number
1732*4a1a9510SRong-En Fan          of columns and the number of rows in a given window.
1733*4a1a9510SRong-En Fan          <tt class="LITERAL">getmaxyx()</tt> does this by updating
1734*4a1a9510SRong-En Fan          the variables given to it. Since <tt class=
1735*4a1a9510SRong-En Fan          "LITERAL">getmaxyx()</tt> is not a function we don't pass
1736*4a1a9510SRong-En Fan          pointers to it, we just give two integer variables.</p>
1737*4a1a9510SRong-En Fan        </div>
1738*4a1a9510SRong-En Fan      </div>
1739*4a1a9510SRong-En Fan
1740*4a1a9510SRong-En Fan      <div class="SECT2">
1741*4a1a9510SRong-En Fan        <hr>
1742*4a1a9510SRong-En Fan
1743*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ADDSTRCLASS" id=
1744*4a1a9510SRong-En Fan        "ADDSTRCLASS">6.4. addstr() class of functions</a></h3>
1745*4a1a9510SRong-En Fan
1746*4a1a9510SRong-En Fan        <p><tt class="LITERAL">addstr()</tt> is used to put a
1747*4a1a9510SRong-En Fan        character string into a given window. This function is
1748*4a1a9510SRong-En Fan        similar to calling <tt class="LITERAL">addch()</tt> once
1749*4a1a9510SRong-En Fan        for each character in a given string. This is true for all
1750*4a1a9510SRong-En Fan        output functions. There are other functions from this
1751*4a1a9510SRong-En Fan        family such as <tt class=
1752*4a1a9510SRong-En Fan        "LITERAL">mvaddstr(),mvwaddstr()</tt> and <tt class=
1753*4a1a9510SRong-En Fan        "LITERAL">waddstr()</tt>, which obey the naming convention
1754*4a1a9510SRong-En Fan        of curses.(e.g. mvaddstr() is similar to the respective
1755*4a1a9510SRong-En Fan        calls move() and then addstr().) Another function of this
1756*4a1a9510SRong-En Fan        family is addnstr(), which takes an integer parameter(say
1757*4a1a9510SRong-En Fan        n) additionally. This function puts at most n characters
1758*4a1a9510SRong-En Fan        into the screen. If n is negative, then the entire string
1759*4a1a9510SRong-En Fan        will be added.</p>
1760*4a1a9510SRong-En Fan      </div>
1761*4a1a9510SRong-En Fan
1762*4a1a9510SRong-En Fan      <div class="SECT2">
1763*4a1a9510SRong-En Fan        <hr>
1764*4a1a9510SRong-En Fan
1765*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ACAUTION" id="ACAUTION">6.5. A
1766*4a1a9510SRong-En Fan        word of caution</a></h3>
1767*4a1a9510SRong-En Fan
1768*4a1a9510SRong-En Fan        <p>All these functions take y co-ordinate first and then x
1769*4a1a9510SRong-En Fan        in their arguments. A common mistake by beginners is to
1770*4a1a9510SRong-En Fan        pass x,y in that order. If you are doing too many
1771*4a1a9510SRong-En Fan        manipulations of (y,x) co-ordinates, think of dividing the
1772*4a1a9510SRong-En Fan        screen into windows and manipulate each one separately.
1773*4a1a9510SRong-En Fan        Windows are explained in the <a href="#WINDOWS">windows</a>
1774*4a1a9510SRong-En Fan        section.</p>
1775*4a1a9510SRong-En Fan      </div>
1776*4a1a9510SRong-En Fan    </div>
1777*4a1a9510SRong-En Fan
1778*4a1a9510SRong-En Fan    <div class="SECT1">
1779*4a1a9510SRong-En Fan      <hr>
1780*4a1a9510SRong-En Fan
1781*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="SCANW" id="SCANW">7. Input
1782*4a1a9510SRong-En Fan      functions</a></h2>
1783*4a1a9510SRong-En Fan
1784*4a1a9510SRong-En Fan      <p>Well, printing without taking input, is boring. Let's see
1785*4a1a9510SRong-En Fan      functions which allow us to get input from user. These
1786*4a1a9510SRong-En Fan      functions also can be divided into three categories.</p>
1787*4a1a9510SRong-En Fan
1788*4a1a9510SRong-En Fan      <ol type="1">
1789*4a1a9510SRong-En Fan        <li>
1790*4a1a9510SRong-En Fan          <p>getch() class: Get a character</p>
1791*4a1a9510SRong-En Fan        </li>
1792*4a1a9510SRong-En Fan
1793*4a1a9510SRong-En Fan        <li>
1794*4a1a9510SRong-En Fan          <p>scanw() class: Get formatted input</p>
1795*4a1a9510SRong-En Fan        </li>
1796*4a1a9510SRong-En Fan
1797*4a1a9510SRong-En Fan        <li>
1798*4a1a9510SRong-En Fan          <p>getstr() class: Get strings</p>
1799*4a1a9510SRong-En Fan        </li>
1800*4a1a9510SRong-En Fan      </ol>
1801*4a1a9510SRong-En Fan
1802*4a1a9510SRong-En Fan      <div class="SECT2">
1803*4a1a9510SRong-En Fan        <hr>
1804*4a1a9510SRong-En Fan
1805*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="GETCHCLASS" id="GETCHCLASS">7.1.
1806*4a1a9510SRong-En Fan        getch() class of functions</a></h3>
1807*4a1a9510SRong-En Fan
1808*4a1a9510SRong-En Fan        <p>These functions read a single character from the
1809*4a1a9510SRong-En Fan        terminal. But there are several subtle facts to consider.
1810*4a1a9510SRong-En Fan        For example if you don't use the function cbreak(), curses
1811*4a1a9510SRong-En Fan        will not read your input characters contiguously but will
1812*4a1a9510SRong-En Fan        begin read them only after a new line or an EOF is
1813*4a1a9510SRong-En Fan        encountered. In order to avoid this, the cbreak() function
1814*4a1a9510SRong-En Fan        must used so that characters are immediately available to
1815*4a1a9510SRong-En Fan        your program. Another widely used function is noecho(). As
1816*4a1a9510SRong-En Fan        the name suggests, when this function is set (used), the
1817*4a1a9510SRong-En Fan        characters that are keyed in by the user will not show up
1818*4a1a9510SRong-En Fan        on the screen. The two functions cbreak() and noecho() are
1819*4a1a9510SRong-En Fan        typical examples of key management. Functions of this genre
1820*4a1a9510SRong-En Fan        are explained in the <a href="#KEYS">key management
1821*4a1a9510SRong-En Fan        section</a> .</p>
1822*4a1a9510SRong-En Fan      </div>
1823*4a1a9510SRong-En Fan
1824*4a1a9510SRong-En Fan      <div class="SECT2">
1825*4a1a9510SRong-En Fan        <hr>
1826*4a1a9510SRong-En Fan
1827*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="SCANWCLASS" id="SCANWCLASS">7.2.
1828*4a1a9510SRong-En Fan        scanw() class of functions</a></h3>
1829*4a1a9510SRong-En Fan
1830*4a1a9510SRong-En Fan        <p>These functions are similar to <tt class=
1831*4a1a9510SRong-En Fan        "LITERAL">scanf()</tt> with the added capability of getting
1832*4a1a9510SRong-En Fan        the input from any location on the screen.</p>
1833*4a1a9510SRong-En Fan
1834*4a1a9510SRong-En Fan        <div class="SECT3">
1835*4a1a9510SRong-En Fan          <hr>
1836*4a1a9510SRong-En Fan
1837*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="SCANWMVSCANW" id=
1838*4a1a9510SRong-En Fan          "SCANWMVSCANW">7.2.1. scanw() and mvscanw</a></h4>
1839*4a1a9510SRong-En Fan
1840*4a1a9510SRong-En Fan          <p>The usage of these functions is similar to that of
1841*4a1a9510SRong-En Fan          <tt class="LITERAL">sscanf()</tt>, where the line to be
1842*4a1a9510SRong-En Fan          scanned is provided by <tt class="LITERAL">wgetstr()</tt>
1843*4a1a9510SRong-En Fan          function. That is, these functions call to <tt class=
1844*4a1a9510SRong-En Fan          "LITERAL">wgetstr()</tt> function(explained below) and
1845*4a1a9510SRong-En Fan          uses the resulting line for a scan.</p>
1846*4a1a9510SRong-En Fan        </div>
1847*4a1a9510SRong-En Fan
1848*4a1a9510SRong-En Fan        <div class="SECT3">
1849*4a1a9510SRong-En Fan          <hr>
1850*4a1a9510SRong-En Fan
1851*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="WSCANWMVWSCANW" id=
1852*4a1a9510SRong-En Fan          "WSCANWMVWSCANW">7.2.2. wscanw() and mvwscanw()</a></h4>
1853*4a1a9510SRong-En Fan
1854*4a1a9510SRong-En Fan          <p>These are similar to above two functions except that
1855*4a1a9510SRong-En Fan          they read from a window, which is supplied as one of the
1856*4a1a9510SRong-En Fan          arguments to these functions.</p>
1857*4a1a9510SRong-En Fan        </div>
1858*4a1a9510SRong-En Fan
1859*4a1a9510SRong-En Fan        <div class="SECT3">
1860*4a1a9510SRong-En Fan          <hr>
1861*4a1a9510SRong-En Fan
1862*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="VWSCANW" id="VWSCANW">7.2.3.
1863*4a1a9510SRong-En Fan          vw_scanw()</a></h4>
1864*4a1a9510SRong-En Fan
1865*4a1a9510SRong-En Fan          <p>This function is similar to <tt class=
1866*4a1a9510SRong-En Fan          "LITERAL">vscanf()</tt>. This can be used when a variable
1867*4a1a9510SRong-En Fan          number of arguments are to be scanned.</p>
1868*4a1a9510SRong-En Fan        </div>
1869*4a1a9510SRong-En Fan      </div>
1870*4a1a9510SRong-En Fan
1871*4a1a9510SRong-En Fan      <div class="SECT2">
1872*4a1a9510SRong-En Fan        <hr>
1873*4a1a9510SRong-En Fan
1874*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="GETSTRCLASS" id=
1875*4a1a9510SRong-En Fan        "GETSTRCLASS">7.3. getstr() class of functions</a></h3>
1876*4a1a9510SRong-En Fan
1877*4a1a9510SRong-En Fan        <p>These functions are used to get strings from the
1878*4a1a9510SRong-En Fan        terminal. In essence, this function performs the same task
1879*4a1a9510SRong-En Fan        as would be achieved by a series of calls to <tt class=
1880*4a1a9510SRong-En Fan        "LITERAL">getch()</tt> until a newline, carriage return, or
1881*4a1a9510SRong-En Fan        end-of-file is received. The resulting string of characters
1882*4a1a9510SRong-En Fan        are pointed to by <tt class="LITERAL">str</tt>, which is a
1883*4a1a9510SRong-En Fan        character pointer provided by the user.</p>
1884*4a1a9510SRong-En Fan      </div>
1885*4a1a9510SRong-En Fan
1886*4a1a9510SRong-En Fan      <div class="SECT2">
1887*4a1a9510SRong-En Fan        <hr>
1888*4a1a9510SRong-En Fan
1889*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="GETSTREX" id="GETSTREX">7.4.
1890*4a1a9510SRong-En Fan        Some examples</a></h3>
1891*4a1a9510SRong-En Fan
1892*4a1a9510SRong-En Fan        <div class="EXAMPLE">
1893*4a1a9510SRong-En Fan          <a name="BSCEX" id="BSCEX"></a>
1894*4a1a9510SRong-En Fan
1895*4a1a9510SRong-En Fan          <p><b>Example 4. A Simple scanw example</b></p>
1896*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
1897*4a1a9510SRong-En Fan<span class=
1898*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;                   /* ncurses.h includes stdio.h */
1899*4a1a9510SRong-En Fan#include &lt;string.h&gt;
1900*4a1a9510SRong-En Fan
1901*4a1a9510SRong-En Fanint main()
1902*4a1a9510SRong-En Fan{
1903*4a1a9510SRong-En Fan char mesg[]="Enter a string: ";                /* message to be appeared on the screen */
1904*4a1a9510SRong-En Fan char str[80];
1905*4a1a9510SRong-En Fan int row,col;                           /* to store the number of rows and *
1906*4a1a9510SRong-En Fan                                         * the number of colums of the screen */
1907*4a1a9510SRong-En Fan initscr();                             /* start the curses mode */
1908*4a1a9510SRong-En Fan getmaxyx(stdscr,row,col);              /* get the number of rows and columns */
1909*4a1a9510SRong-En Fan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg);
1910*4a1a9510SRong-En Fan                                /* print the message at the center of the screen */
1911*4a1a9510SRong-En Fan getstr(str);
1912*4a1a9510SRong-En Fan mvprintw(LINES - 2, 0, "You Entered: %s", str);
1913*4a1a9510SRong-En Fan getch();
1914*4a1a9510SRong-En Fan endwin();
1915*4a1a9510SRong-En Fan
1916*4a1a9510SRong-En Fan return 0;
1917*4a1a9510SRong-En Fan}</span>
1918*4a1a9510SRong-En Fan</pre>
1919*4a1a9510SRong-En Fan        </div>
1920*4a1a9510SRong-En Fan      </div>
1921*4a1a9510SRong-En Fan    </div>
1922*4a1a9510SRong-En Fan
1923*4a1a9510SRong-En Fan    <div class="SECT1">
1924*4a1a9510SRong-En Fan      <hr>
1925*4a1a9510SRong-En Fan
1926*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="ATTRIB" id="ATTRIB">8.
1927*4a1a9510SRong-En Fan      Attributes</a></h2>
1928*4a1a9510SRong-En Fan
1929*4a1a9510SRong-En Fan      <p>We have seen an example of how attributes can be used to
1930*4a1a9510SRong-En Fan      print characters with some special effects. Attributes, when
1931*4a1a9510SRong-En Fan      set prudently, can present information in an easy,
1932*4a1a9510SRong-En Fan      understandable manner. The following program takes a C file
1933*4a1a9510SRong-En Fan      as input and prints the file with comments in bold. Scan
1934*4a1a9510SRong-En Fan      through the code.</p>
1935*4a1a9510SRong-En Fan
1936*4a1a9510SRong-En Fan      <div class="EXAMPLE">
1937*4a1a9510SRong-En Fan        <a name="BSIAT" id="BSIAT"></a>
1938*4a1a9510SRong-En Fan
1939*4a1a9510SRong-En Fan        <p><b>Example 5. A Simple Attributes example</b></p>
1940*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
1941*4a1a9510SRong-En Fan<span class=
1942*4a1a9510SRong-En Fan"INLINEMEDIAOBJECT">/* pager functionality by Joseph Spainhour" &lt;[email protected]&gt; */
1943*4a1a9510SRong-En Fan#include &lt;ncurses.h&gt;
1944*4a1a9510SRong-En Fan#include &lt;stdlib.h&gt;
1945*4a1a9510SRong-En Fan
1946*4a1a9510SRong-En Fanint main(int argc, char *argv[])
1947*4a1a9510SRong-En Fan{
1948*4a1a9510SRong-En Fan  int ch, prev, row, col;
1949*4a1a9510SRong-En Fan  prev = EOF;
1950*4a1a9510SRong-En Fan  FILE *fp;
1951*4a1a9510SRong-En Fan  int y, x;
1952*4a1a9510SRong-En Fan
1953*4a1a9510SRong-En Fan  if(argc != 2)
1954*4a1a9510SRong-En Fan  {
1955*4a1a9510SRong-En Fan    printf("Usage: %s &lt;a c file name&gt;\n", argv[0]);
1956*4a1a9510SRong-En Fan    exit(1);
1957*4a1a9510SRong-En Fan  }
1958*4a1a9510SRong-En Fan  fp = fopen(argv[1], "r");
1959*4a1a9510SRong-En Fan  if(fp == NULL)
1960*4a1a9510SRong-En Fan  {
1961*4a1a9510SRong-En Fan    perror("Cannot open input file");
1962*4a1a9510SRong-En Fan    exit(1);
1963*4a1a9510SRong-En Fan  }
1964*4a1a9510SRong-En Fan  initscr();                            /* Start curses mode */
1965*4a1a9510SRong-En Fan  getmaxyx(stdscr, row, col);           /* find the boundaries of the screeen */
1966*4a1a9510SRong-En Fan  while((ch = fgetc(fp)) != EOF)        /* read the file till we reach the end */
1967*4a1a9510SRong-En Fan  {
1968*4a1a9510SRong-En Fan    getyx(stdscr, y, x);                /* get the current curser position */
1969*4a1a9510SRong-En Fan    if(y == (row - 1))                  /* are we are at the end of the screen */
1970*4a1a9510SRong-En Fan    {
1971*4a1a9510SRong-En Fan      printw("&lt;-Press Any Key-&gt;");      /* tell the user to press a key */
1972*4a1a9510SRong-En Fan      getch();
1973*4a1a9510SRong-En Fan      clear();                          /* clear the screen */
1974*4a1a9510SRong-En Fan      move(0, 0);                       /* start at the beginning of the screen */
1975*4a1a9510SRong-En Fan    }
1976*4a1a9510SRong-En Fan    if(prev == '/' &amp;&amp; ch == '*')        /* If it is / and * then only
1977*4a1a9510SRong-En Fan                                         * switch bold on */
1978*4a1a9510SRong-En Fan    {
1979*4a1a9510SRong-En Fan      attron(A_BOLD);                   /* cut bold on */
1980*4a1a9510SRong-En Fan      getyx(stdscr, y, x);              /* get the current curser position */
1981*4a1a9510SRong-En Fan      move(y, x - 1);                   /* back up one space */
1982*4a1a9510SRong-En Fan      printw("%c%c", '/', ch);          /* The actual printing is done here */
1983*4a1a9510SRong-En Fan    }
1984*4a1a9510SRong-En Fan    else
1985*4a1a9510SRong-En Fan      printw("%c", ch);
1986*4a1a9510SRong-En Fan    refresh();
1987*4a1a9510SRong-En Fan    if(prev == '*' &amp;&amp; ch == '/')
1988*4a1a9510SRong-En Fan      attroff(A_BOLD);                  /* Switch it off once we got *
1989*4a1a9510SRong-En Fan                                         * and then / */
1990*4a1a9510SRong-En Fan    prev = ch;
1991*4a1a9510SRong-En Fan  }
1992*4a1a9510SRong-En Fan  endwin();                             /* End curses mode */
1993*4a1a9510SRong-En Fan  fclose(fp);
1994*4a1a9510SRong-En Fan  return 0;
1995*4a1a9510SRong-En Fan}</span>
1996*4a1a9510SRong-En Fan</pre>
1997*4a1a9510SRong-En Fan      </div>
1998*4a1a9510SRong-En Fan
1999*4a1a9510SRong-En Fan      <p>Don't worry about all those initialization and other crap.
2000*4a1a9510SRong-En Fan      Concentrate on the while loop. It reads each character in the
2001*4a1a9510SRong-En Fan      file and searches for the pattern /*. Once it spots the
2002*4a1a9510SRong-En Fan      pattern, it switches the BOLD attribute on with <tt class=
2003*4a1a9510SRong-En Fan      "LITERAL">attron()</tt> . When we get the pattern */ it is
2004*4a1a9510SRong-En Fan      switched off by <tt class="LITERAL">attroff()</tt> .</p>
2005*4a1a9510SRong-En Fan
2006*4a1a9510SRong-En Fan      <p>The above program also introduces us to two useful
2007*4a1a9510SRong-En Fan      functions <tt class="LITERAL">getyx()</tt> and <tt class=
2008*4a1a9510SRong-En Fan      "LITERAL">move()</tt>. The first function gets the
2009*4a1a9510SRong-En Fan      co-ordinates of the present cursor into the variables y, x.
2010*4a1a9510SRong-En Fan      Since getyx() is a macro we don't have to pass pointers to
2011*4a1a9510SRong-En Fan      variables. The function <tt class="LITERAL">move()</tt> moves
2012*4a1a9510SRong-En Fan      the cursor to the co-ordinates given to it.</p>
2013*4a1a9510SRong-En Fan
2014*4a1a9510SRong-En Fan      <p>The above program is really a simple one which doesn't do
2015*4a1a9510SRong-En Fan      much. On these lines one could write a more useful program
2016*4a1a9510SRong-En Fan      which reads a C file, parses it and prints it in different
2017*4a1a9510SRong-En Fan      colors. One could even extend it to other languages as
2018*4a1a9510SRong-En Fan      well.</p>
2019*4a1a9510SRong-En Fan
2020*4a1a9510SRong-En Fan      <div class="SECT2">
2021*4a1a9510SRong-En Fan        <hr>
2022*4a1a9510SRong-En Fan
2023*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ATTRIBDETAILS" id=
2024*4a1a9510SRong-En Fan        "ATTRIBDETAILS">8.1. The details</a></h3>
2025*4a1a9510SRong-En Fan
2026*4a1a9510SRong-En Fan        <p>Let's get into more details of attributes. The functions
2027*4a1a9510SRong-En Fan        <tt class="LITERAL">attron(), attroff(), attrset()</tt> ,
2028*4a1a9510SRong-En Fan        and their sister functions <tt class=
2029*4a1a9510SRong-En Fan        "LITERAL">attr_get()</tt> etc.. can be used to switch
2030*4a1a9510SRong-En Fan        attributes on/off , get attributes and produce a colorful
2031*4a1a9510SRong-En Fan        display.</p>
2032*4a1a9510SRong-En Fan
2033*4a1a9510SRong-En Fan        <p>The functions attron and attroff take a bit-mask of
2034*4a1a9510SRong-En Fan        attributes and switch them on or off, respectively. The
2035*4a1a9510SRong-En Fan        following video attributes, which are defined in
2036*4a1a9510SRong-En Fan        &lt;curses.h&gt; can be passed to these functions.</p>
2037*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2038*4a1a9510SRong-En Fan
2039*4a1a9510SRong-En Fan    A_NORMAL        Normal display (no highlight)
2040*4a1a9510SRong-En Fan    A_STANDOUT      Best highlighting mode of the terminal.
2041*4a1a9510SRong-En Fan    A_UNDERLINE     Underlining
2042*4a1a9510SRong-En Fan    A_REVERSE       Reverse video
2043*4a1a9510SRong-En Fan    A_BLINK         Blinking
2044*4a1a9510SRong-En Fan    A_DIM           Half bright
2045*4a1a9510SRong-En Fan    A_BOLD          Extra bright or bold
2046*4a1a9510SRong-En Fan    A_PROTECT       Protected mode
2047*4a1a9510SRong-En Fan    A_INVIS         Invisible or blank mode
2048*4a1a9510SRong-En Fan    A_ALTCHARSET    Alternate character set
2049*4a1a9510SRong-En Fan    A_CHARTEXT      Bit-mask to extract a character
2050*4a1a9510SRong-En Fan    COLOR_PAIR(n)   Color-pair number n
2051*4a1a9510SRong-En Fan
2052*4a1a9510SRong-En Fan</pre>
2053*4a1a9510SRong-En Fan
2054*4a1a9510SRong-En Fan        <p>The last one is the most colorful one :-) Colors are
2055*4a1a9510SRong-En Fan        explained in the <a href="#color" target="_top">next
2056*4a1a9510SRong-En Fan        sections</a>.</p>
2057*4a1a9510SRong-En Fan
2058*4a1a9510SRong-En Fan        <p>We can OR(|) any number of above attributes to get a
2059*4a1a9510SRong-En Fan        combined effect. If you wanted reverse video with blinking
2060*4a1a9510SRong-En Fan        characters you can use</p>
2061*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2062*4a1a9510SRong-En Fan    attron(A_REVERSE | A_BLINK);
2063*4a1a9510SRong-En Fan</pre>
2064*4a1a9510SRong-En Fan      </div>
2065*4a1a9510SRong-En Fan
2066*4a1a9510SRong-En Fan      <div class="SECT2">
2067*4a1a9510SRong-En Fan        <hr>
2068*4a1a9510SRong-En Fan
2069*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ATTRONVSATTRSET" id=
2070*4a1a9510SRong-En Fan        "ATTRONVSATTRSET">8.2. attron() vs attrset()</a></h3>
2071*4a1a9510SRong-En Fan
2072*4a1a9510SRong-En Fan        <p>Then what is the difference between attron() and
2073*4a1a9510SRong-En Fan        attrset()? attrset sets the attributes of window whereas
2074*4a1a9510SRong-En Fan        attron just switches on the attribute given to it. So
2075*4a1a9510SRong-En Fan        attrset() fully overrides whatever attributes the window
2076*4a1a9510SRong-En Fan        previously had and sets it to the new attribute(s).
2077*4a1a9510SRong-En Fan        Similarly attroff() just switches off the attribute(s)
2078*4a1a9510SRong-En Fan        given to it as an argument. This gives us the flexibility
2079*4a1a9510SRong-En Fan        of managing attributes easily.But if you use them
2080*4a1a9510SRong-En Fan        carelessly you may loose track of what attributes the
2081*4a1a9510SRong-En Fan        window has and garble the display. This is especially true
2082*4a1a9510SRong-En Fan        while managing menus with colors and highlighting. So
2083*4a1a9510SRong-En Fan        decide on a consistent policy and stick to it. You can
2084*4a1a9510SRong-En Fan        always use <tt class="LITERAL">standend()</tt> which is
2085*4a1a9510SRong-En Fan        equivalent to <tt class="LITERAL">attrset(A_NORMAL)</tt>
2086*4a1a9510SRong-En Fan        which turns off all attributes and brings you to normal
2087*4a1a9510SRong-En Fan        mode.</p>
2088*4a1a9510SRong-En Fan      </div>
2089*4a1a9510SRong-En Fan
2090*4a1a9510SRong-En Fan      <div class="SECT2">
2091*4a1a9510SRong-En Fan        <hr>
2092*4a1a9510SRong-En Fan
2093*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ATTRGET" id="ATTRGET">8.3.
2094*4a1a9510SRong-En Fan        attr_get()</a></h3>
2095*4a1a9510SRong-En Fan
2096*4a1a9510SRong-En Fan        <p>The function attr_get() gets the current attributes and
2097*4a1a9510SRong-En Fan        color pair of the window. Though we might not use this as
2098*4a1a9510SRong-En Fan        often as the above functions, this is useful in scanning
2099*4a1a9510SRong-En Fan        areas of screen. Say we wanted to do some complex update on
2100*4a1a9510SRong-En Fan        screen and we are not sure what attribute each character is
2101*4a1a9510SRong-En Fan        associated with. Then this function can be used with either
2102*4a1a9510SRong-En Fan        attrset or attron to produce the desired effect.</p>
2103*4a1a9510SRong-En Fan      </div>
2104*4a1a9510SRong-En Fan
2105*4a1a9510SRong-En Fan      <div class="SECT2">
2106*4a1a9510SRong-En Fan        <hr>
2107*4a1a9510SRong-En Fan
2108*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ATTRFUNCS" id="ATTRFUNCS">8.4.
2109*4a1a9510SRong-En Fan        attr_ functions</a></h3>
2110*4a1a9510SRong-En Fan
2111*4a1a9510SRong-En Fan        <p>There are series of functions like attr_set(), attr_on
2112*4a1a9510SRong-En Fan        etc.. These are similar to above functions except that they
2113*4a1a9510SRong-En Fan        take parameters of type <tt class=
2114*4a1a9510SRong-En Fan        "LITERAL">attr_t</tt>.</p>
2115*4a1a9510SRong-En Fan      </div>
2116*4a1a9510SRong-En Fan
2117*4a1a9510SRong-En Fan      <div class="SECT2">
2118*4a1a9510SRong-En Fan        <hr>
2119*4a1a9510SRong-En Fan
2120*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WATTRFUNCS" id="WATTRFUNCS">8.5.
2121*4a1a9510SRong-En Fan        wattr functions</a></h3>
2122*4a1a9510SRong-En Fan
2123*4a1a9510SRong-En Fan        <p>For each of the above functions we have a corresponding
2124*4a1a9510SRong-En Fan        function with 'w' which operates on a particular window.
2125*4a1a9510SRong-En Fan        The above functions operate on stdscr.</p>
2126*4a1a9510SRong-En Fan      </div>
2127*4a1a9510SRong-En Fan
2128*4a1a9510SRong-En Fan      <div class="SECT2">
2129*4a1a9510SRong-En Fan        <hr>
2130*4a1a9510SRong-En Fan
2131*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="CHGAT" id="CHGAT">8.6. chgat()
2132*4a1a9510SRong-En Fan        functions</a></h3>
2133*4a1a9510SRong-En Fan
2134*4a1a9510SRong-En Fan        <p>The function chgat() is listed in the end of the man
2135*4a1a9510SRong-En Fan        page curs_attr. It actually is a useful one. This function
2136*4a1a9510SRong-En Fan        can be used to set attributes for a group of characters
2137*4a1a9510SRong-En Fan        without moving. I mean it !!! without moving the cursor :-)
2138*4a1a9510SRong-En Fan        It changes the attributes of a given number of characters
2139*4a1a9510SRong-En Fan        starting at the current cursor location.</p>
2140*4a1a9510SRong-En Fan
2141*4a1a9510SRong-En Fan        <p>We can give -1 as the character count to update till end
2142*4a1a9510SRong-En Fan        of line. If you want to change attributes of characters
2143*4a1a9510SRong-En Fan        from current position to end of line, just use this.</p>
2144*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2145*4a1a9510SRong-En Fan    chgat(-1, A_REVERSE, 0, NULL);
2146*4a1a9510SRong-En Fan</pre>
2147*4a1a9510SRong-En Fan
2148*4a1a9510SRong-En Fan        <p>This function is useful when changing attributes for
2149*4a1a9510SRong-En Fan        characters that are already on the screen. Move to the
2150*4a1a9510SRong-En Fan        character from which you want to change and change the
2151*4a1a9510SRong-En Fan        attribute.</p>
2152*4a1a9510SRong-En Fan
2153*4a1a9510SRong-En Fan        <p>Other functions wchgat(), mvchgat(), wchgat() behave
2154*4a1a9510SRong-En Fan        similarly except that the w functions operate on the
2155*4a1a9510SRong-En Fan        particular window. The mv functions first move the cursor
2156*4a1a9510SRong-En Fan        then perform the work given to them. Actually chgat is a
2157*4a1a9510SRong-En Fan        macro which is replaced by a wchgat() with stdscr as the
2158*4a1a9510SRong-En Fan        window. Most of the "w-less" functions are macros.</p>
2159*4a1a9510SRong-En Fan
2160*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2161*4a1a9510SRong-En Fan          <a name="BWICH" id="BWICH"></a>
2162*4a1a9510SRong-En Fan
2163*4a1a9510SRong-En Fan          <p><b>Example 6. Chgat() Usage example</b></p>
2164*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2165*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2166*4a1a9510SRong-En Fan
2167*4a1a9510SRong-En Fanint main(int argc, char *argv[])
2168*4a1a9510SRong-En Fan{       initscr();                      /* Start curses mode            */
2169*4a1a9510SRong-En Fan        start_color();                  /* Start color functionality    */
2170*4a1a9510SRong-En Fan
2171*4a1a9510SRong-En Fan        init_pair(1, COLOR_CYAN, COLOR_BLACK);
2172*4a1a9510SRong-En Fan        printw("A Big string which i didn't care to type fully ");
2173*4a1a9510SRong-En Fan        mvchgat(0, 0, -1, A_BLINK, 1, NULL);
2174*4a1a9510SRong-En Fan        /*
2175*4a1a9510SRong-En Fan         * First two parameters specify the position at which to start
2176*4a1a9510SRong-En Fan         * Third parameter number of characters to update. -1 means till
2177*4a1a9510SRong-En Fan         * end of line
2178*4a1a9510SRong-En Fan         * Forth parameter is the normal attribute you wanted to give
2179*4a1a9510SRong-En Fan         * to the charcter
2180*4a1a9510SRong-En Fan         * Fifth is the color index. It is the index given during init_pair()
2181*4a1a9510SRong-En Fan         * use 0 if you didn't want color
2182*4a1a9510SRong-En Fan         * Sixth one is always NULL
2183*4a1a9510SRong-En Fan         */
2184*4a1a9510SRong-En Fan        refresh();
2185*4a1a9510SRong-En Fan        getch();
2186*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
2187*4a1a9510SRong-En Fan        return 0;
2188*4a1a9510SRong-En Fan}</span>
2189*4a1a9510SRong-En Fan</pre>
2190*4a1a9510SRong-En Fan        </div>
2191*4a1a9510SRong-En Fan
2192*4a1a9510SRong-En Fan        <p>This example also introduces us to the color world of
2193*4a1a9510SRong-En Fan        curses. Colors will be explained in detail later. Use 0 for
2194*4a1a9510SRong-En Fan        no color.</p>
2195*4a1a9510SRong-En Fan      </div>
2196*4a1a9510SRong-En Fan    </div>
2197*4a1a9510SRong-En Fan
2198*4a1a9510SRong-En Fan    <div class="SECT1">
2199*4a1a9510SRong-En Fan      <hr>
2200*4a1a9510SRong-En Fan
2201*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="WINDOWS" id="WINDOWS">9.
2202*4a1a9510SRong-En Fan      Windows</a></h2>
2203*4a1a9510SRong-En Fan
2204*4a1a9510SRong-En Fan      <p>Windows form the most important concept in curses. You
2205*4a1a9510SRong-En Fan      have seen the standard window stdscr above where all the
2206*4a1a9510SRong-En Fan      functions implicitly operated on this window. Now to make
2207*4a1a9510SRong-En Fan      design even a simplest GUI, you need to resort to windows.
2208*4a1a9510SRong-En Fan      The main reason you may want to use windows is to manipulate
2209*4a1a9510SRong-En Fan      parts of the screen separately, for better efficiency, by
2210*4a1a9510SRong-En Fan      updating only the windows that need to be changed and for a
2211*4a1a9510SRong-En Fan      better design. I would say the last reason is the most
2212*4a1a9510SRong-En Fan      important in going for windows. You should always strive for
2213*4a1a9510SRong-En Fan      a better and easy-to-manage design in your programs. If you
2214*4a1a9510SRong-En Fan      are writing big, complex GUIs this is of pivotal importance
2215*4a1a9510SRong-En Fan      before you start doing anything.</p>
2216*4a1a9510SRong-En Fan
2217*4a1a9510SRong-En Fan      <div class="SECT2">
2218*4a1a9510SRong-En Fan        <hr>
2219*4a1a9510SRong-En Fan
2220*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WINDOWBASICS" id=
2221*4a1a9510SRong-En Fan        "WINDOWBASICS">9.1. The basics</a></h3>
2222*4a1a9510SRong-En Fan
2223*4a1a9510SRong-En Fan        <p>A Window can be created by calling the function
2224*4a1a9510SRong-En Fan        <tt class="LITERAL">newwin()</tt>. It doesn't create any
2225*4a1a9510SRong-En Fan        thing on the screen actually. It allocates memory for a
2226*4a1a9510SRong-En Fan        structure to manipulate the window and updates the
2227*4a1a9510SRong-En Fan        structure with data regarding the window like it's size,
2228*4a1a9510SRong-En Fan        beginy, beginx etc.. Hence in curses, a window is just an
2229*4a1a9510SRong-En Fan        abstraction of an imaginary window, which can be
2230*4a1a9510SRong-En Fan        manipulated independent of other parts of screen. The
2231*4a1a9510SRong-En Fan        function newwin() returns a pointer to structure WINDOW,
2232*4a1a9510SRong-En Fan        which can be passed to window related functions like
2233*4a1a9510SRong-En Fan        wprintw() etc.. Finally the window can be destroyed with
2234*4a1a9510SRong-En Fan        delwin(). It will deallocate the memory associated with the
2235*4a1a9510SRong-En Fan        window structure.</p>
2236*4a1a9510SRong-En Fan      </div>
2237*4a1a9510SRong-En Fan
2238*4a1a9510SRong-En Fan      <div class="SECT2">
2239*4a1a9510SRong-En Fan        <hr>
2240*4a1a9510SRong-En Fan
2241*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="LETBEWINDOW" id=
2242*4a1a9510SRong-En Fan        "LETBEWINDOW">9.2. Let there be a Window !!!</a></h3>
2243*4a1a9510SRong-En Fan
2244*4a1a9510SRong-En Fan        <p>What fun is it, if a window is created and we can't see
2245*4a1a9510SRong-En Fan        it. So the fun part begins by displaying the window. The
2246*4a1a9510SRong-En Fan        function <tt class="LITERAL">box()</tt> can be used to draw
2247*4a1a9510SRong-En Fan        a border around the window. Let's explore these functions
2248*4a1a9510SRong-En Fan        in more detail in this example.</p>
2249*4a1a9510SRong-En Fan
2250*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2251*4a1a9510SRong-En Fan          <a name="BWIBO" id="BWIBO"></a>
2252*4a1a9510SRong-En Fan
2253*4a1a9510SRong-En Fan          <p><b>Example 7. Window Border example</b></p>
2254*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2255*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2256*4a1a9510SRong-En Fan
2257*4a1a9510SRong-En Fan
2258*4a1a9510SRong-En FanWINDOW *create_newwin(int height, int width, int starty, int startx);
2259*4a1a9510SRong-En Fanvoid destroy_win(WINDOW *local_win);
2260*4a1a9510SRong-En Fan
2261*4a1a9510SRong-En Fanint main(int argc, char *argv[])
2262*4a1a9510SRong-En Fan{       WINDOW *my_win;
2263*4a1a9510SRong-En Fan        int startx, starty, width, height;
2264*4a1a9510SRong-En Fan        int ch;
2265*4a1a9510SRong-En Fan
2266*4a1a9510SRong-En Fan        initscr();                      /* Start curses mode            */
2267*4a1a9510SRong-En Fan        cbreak();                       /* Line buffering disabled, Pass on
2268*4a1a9510SRong-En Fan                                         * everty thing to me           */
2269*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);           /* I need that nifty F1         */
2270*4a1a9510SRong-En Fan
2271*4a1a9510SRong-En Fan        height = 3;
2272*4a1a9510SRong-En Fan        width = 10;
2273*4a1a9510SRong-En Fan        starty = (LINES - height) / 2;  /* Calculating for a center placement */
2274*4a1a9510SRong-En Fan        startx = (COLS - width) / 2;    /* of the window                */
2275*4a1a9510SRong-En Fan        printw("Press F1 to exit");
2276*4a1a9510SRong-En Fan        refresh();
2277*4a1a9510SRong-En Fan        my_win = create_newwin(height, width, starty, startx);
2278*4a1a9510SRong-En Fan
2279*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
2280*4a1a9510SRong-En Fan        {       switch(ch)
2281*4a1a9510SRong-En Fan                {       case KEY_LEFT:
2282*4a1a9510SRong-En Fan                                destroy_win(my_win);
2283*4a1a9510SRong-En Fan                                my_win = create_newwin(height, width, starty,--startx);
2284*4a1a9510SRong-En Fan                                break;
2285*4a1a9510SRong-En Fan                        case KEY_RIGHT:
2286*4a1a9510SRong-En Fan                                destroy_win(my_win);
2287*4a1a9510SRong-En Fan                                my_win = create_newwin(height, width, starty,++startx);
2288*4a1a9510SRong-En Fan                                break;
2289*4a1a9510SRong-En Fan                        case KEY_UP:
2290*4a1a9510SRong-En Fan                                destroy_win(my_win);
2291*4a1a9510SRong-En Fan                                my_win = create_newwin(height, width, --starty,startx);
2292*4a1a9510SRong-En Fan                                break;
2293*4a1a9510SRong-En Fan                        case KEY_DOWN:
2294*4a1a9510SRong-En Fan                                destroy_win(my_win);
2295*4a1a9510SRong-En Fan                                my_win = create_newwin(height, width, ++starty,startx);
2296*4a1a9510SRong-En Fan                                break;
2297*4a1a9510SRong-En Fan                }
2298*4a1a9510SRong-En Fan        }
2299*4a1a9510SRong-En Fan
2300*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
2301*4a1a9510SRong-En Fan        return 0;
2302*4a1a9510SRong-En Fan}
2303*4a1a9510SRong-En Fan
2304*4a1a9510SRong-En FanWINDOW *create_newwin(int height, int width, int starty, int startx)
2305*4a1a9510SRong-En Fan{       WINDOW *local_win;
2306*4a1a9510SRong-En Fan
2307*4a1a9510SRong-En Fan        local_win = newwin(height, width, starty, startx);
2308*4a1a9510SRong-En Fan        box(local_win, 0 , 0);          /* 0, 0 gives default characters
2309*4a1a9510SRong-En Fan                                         * for the vertical and horizontal
2310*4a1a9510SRong-En Fan                                         * lines                        */
2311*4a1a9510SRong-En Fan        wrefresh(local_win);            /* Show that box                */
2312*4a1a9510SRong-En Fan
2313*4a1a9510SRong-En Fan        return local_win;
2314*4a1a9510SRong-En Fan}
2315*4a1a9510SRong-En Fan
2316*4a1a9510SRong-En Fanvoid destroy_win(WINDOW *local_win)
2317*4a1a9510SRong-En Fan{
2318*4a1a9510SRong-En Fan        /* box(local_win, ' ', ' '); : This won't produce the desired
2319*4a1a9510SRong-En Fan         * result of erasing the window. It will leave it's four corners
2320*4a1a9510SRong-En Fan         * and so an ugly remnant of window.
2321*4a1a9510SRong-En Fan         */
2322*4a1a9510SRong-En Fan        wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
2323*4a1a9510SRong-En Fan        /* The parameters taken are
2324*4a1a9510SRong-En Fan         * 1. win: the window on which to operate
2325*4a1a9510SRong-En Fan         * 2. ls: character to be used for the left side of the window
2326*4a1a9510SRong-En Fan         * 3. rs: character to be used for the right side of the window
2327*4a1a9510SRong-En Fan         * 4. ts: character to be used for the top side of the window
2328*4a1a9510SRong-En Fan         * 5. bs: character to be used for the bottom side of the window
2329*4a1a9510SRong-En Fan         * 6. tl: character to be used for the top left corner of the window
2330*4a1a9510SRong-En Fan         * 7. tr: character to be used for the top right corner of the window
2331*4a1a9510SRong-En Fan         * 8. bl: character to be used for the bottom left corner of the window
2332*4a1a9510SRong-En Fan         * 9. br: character to be used for the bottom right corner of the window
2333*4a1a9510SRong-En Fan         */
2334*4a1a9510SRong-En Fan        wrefresh(local_win);
2335*4a1a9510SRong-En Fan        delwin(local_win);
2336*4a1a9510SRong-En Fan}</span>
2337*4a1a9510SRong-En Fan</pre>
2338*4a1a9510SRong-En Fan        </div>
2339*4a1a9510SRong-En Fan      </div>
2340*4a1a9510SRong-En Fan
2341*4a1a9510SRong-En Fan      <div class="SECT2">
2342*4a1a9510SRong-En Fan        <hr>
2343*4a1a9510SRong-En Fan
2344*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="BORDEREXEXPL" id=
2345*4a1a9510SRong-En Fan        "BORDEREXEXPL">9.3. Explanation</a></h3>
2346*4a1a9510SRong-En Fan
2347*4a1a9510SRong-En Fan        <p>Don't scream. I know it's a big example. But I have to
2348*4a1a9510SRong-En Fan        explain some important things here :-). This program
2349*4a1a9510SRong-En Fan        creates a rectangular window that can be moved with left,
2350*4a1a9510SRong-En Fan        right, up, down arrow keys. It repeatedly creates and
2351*4a1a9510SRong-En Fan        destroys windows as user press a key. Don't go beyond the
2352*4a1a9510SRong-En Fan        screen limits. Checking for those limits is left as an
2353*4a1a9510SRong-En Fan        exercise for the reader. Let's dissect it by line by
2354*4a1a9510SRong-En Fan        line.</p>
2355*4a1a9510SRong-En Fan
2356*4a1a9510SRong-En Fan        <p>The <tt class="LITERAL">create_newwin()</tt> function
2357*4a1a9510SRong-En Fan        creates a window with <tt class="LITERAL">newwin()</tt> and
2358*4a1a9510SRong-En Fan        displays a border around it with box. The function
2359*4a1a9510SRong-En Fan        <tt class="LITERAL">destroy_win()</tt> first erases the
2360*4a1a9510SRong-En Fan        window from screen by painting a border with ' ' character
2361*4a1a9510SRong-En Fan        and then calling <tt class="LITERAL">delwin()</tt> to
2362*4a1a9510SRong-En Fan        deallocate memory related to it. Depending on the key the
2363*4a1a9510SRong-En Fan        user presses, starty or startx is changed and a new window
2364*4a1a9510SRong-En Fan        is created.</p>
2365*4a1a9510SRong-En Fan
2366*4a1a9510SRong-En Fan        <p>In the destroy_win, as you can see, I used wborder
2367*4a1a9510SRong-En Fan        instead of box. The reason is written in the comments (You
2368*4a1a9510SRong-En Fan        missed it. I know. Read the code :-)). wborder draws a
2369*4a1a9510SRong-En Fan        border around the window with the characters given to it as
2370*4a1a9510SRong-En Fan        the 4 corner points and the 4 lines. To put it clearly, if
2371*4a1a9510SRong-En Fan        you have called wborder as below:</p>
2372*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2373*4a1a9510SRong-En Fan    wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
2374*4a1a9510SRong-En Fan</pre>
2375*4a1a9510SRong-En Fan
2376*4a1a9510SRong-En Fan        <p>it produces some thing like</p>
2377*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2378*4a1a9510SRong-En Fan    +------------+
2379*4a1a9510SRong-En Fan    |            |
2380*4a1a9510SRong-En Fan    |            |
2381*4a1a9510SRong-En Fan    |            |
2382*4a1a9510SRong-En Fan    |            |
2383*4a1a9510SRong-En Fan    |            |
2384*4a1a9510SRong-En Fan    |            |
2385*4a1a9510SRong-En Fan    +------------+
2386*4a1a9510SRong-En Fan</pre>
2387*4a1a9510SRong-En Fan      </div>
2388*4a1a9510SRong-En Fan
2389*4a1a9510SRong-En Fan      <div class="SECT2">
2390*4a1a9510SRong-En Fan        <hr>
2391*4a1a9510SRong-En Fan
2392*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="OTHERSTUFF" id="OTHERSTUFF">9.4.
2393*4a1a9510SRong-En Fan        The other stuff in the example</a></h3>
2394*4a1a9510SRong-En Fan
2395*4a1a9510SRong-En Fan        <p>You can also see in the above examples, that I have used
2396*4a1a9510SRong-En Fan        the variables COLS, LINES which are initialized to the
2397*4a1a9510SRong-En Fan        screen sizes after initscr(). They can be useful in finding
2398*4a1a9510SRong-En Fan        screen dimensions and finding the center co-ordinate of the
2399*4a1a9510SRong-En Fan        screen as above. The function <tt class=
2400*4a1a9510SRong-En Fan        "LITERAL">getch()</tt> as usual gets the key from keyboard
2401*4a1a9510SRong-En Fan        and according to the key it does the corresponding work.
2402*4a1a9510SRong-En Fan        This type of switch- case is very common in any GUI based
2403*4a1a9510SRong-En Fan        programs.</p>
2404*4a1a9510SRong-En Fan      </div>
2405*4a1a9510SRong-En Fan
2406*4a1a9510SRong-En Fan      <div class="SECT2">
2407*4a1a9510SRong-En Fan        <hr>
2408*4a1a9510SRong-En Fan
2409*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="OTHERBORDERFUNCS" id=
2410*4a1a9510SRong-En Fan        "OTHERBORDERFUNCS">9.5. Other Border functions</a></h3>
2411*4a1a9510SRong-En Fan
2412*4a1a9510SRong-En Fan        <p>Above program is grossly inefficient in that with each
2413*4a1a9510SRong-En Fan        press of a key, a window is destroyed and another is
2414*4a1a9510SRong-En Fan        created. So let's write a more efficient program which uses
2415*4a1a9510SRong-En Fan        other border related functions.</p>
2416*4a1a9510SRong-En Fan
2417*4a1a9510SRong-En Fan        <p>The following program uses <tt class=
2418*4a1a9510SRong-En Fan        "LITERAL">mvhline()</tt> and <tt class=
2419*4a1a9510SRong-En Fan        "LITERAL">mvvline()</tt> to achieve similar effect. These
2420*4a1a9510SRong-En Fan        two functions are simple. They create a horizontal or
2421*4a1a9510SRong-En Fan        vertical line of the specified length at the specified
2422*4a1a9510SRong-En Fan        position.</p>
2423*4a1a9510SRong-En Fan
2424*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2425*4a1a9510SRong-En Fan          <a name="BOTBO" id="BOTBO"></a>
2426*4a1a9510SRong-En Fan
2427*4a1a9510SRong-En Fan          <p><b>Example 8. More border functions</b></p>
2428*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2429*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2430*4a1a9510SRong-En Fan
2431*4a1a9510SRong-En Fantypedef struct _win_border_struct {
2432*4a1a9510SRong-En Fan        chtype  ls, rs, ts, bs,
2433*4a1a9510SRong-En Fan                tl, tr, bl, br;
2434*4a1a9510SRong-En Fan}WIN_BORDER;
2435*4a1a9510SRong-En Fan
2436*4a1a9510SRong-En Fantypedef struct _WIN_struct {
2437*4a1a9510SRong-En Fan
2438*4a1a9510SRong-En Fan        int startx, starty;
2439*4a1a9510SRong-En Fan        int height, width;
2440*4a1a9510SRong-En Fan        WIN_BORDER border;
2441*4a1a9510SRong-En Fan}WIN;
2442*4a1a9510SRong-En Fan
2443*4a1a9510SRong-En Fanvoid init_win_params(WIN *p_win);
2444*4a1a9510SRong-En Fanvoid print_win_params(WIN *p_win);
2445*4a1a9510SRong-En Fanvoid create_box(WIN *win, bool flag);
2446*4a1a9510SRong-En Fan
2447*4a1a9510SRong-En Fanint main(int argc, char *argv[])
2448*4a1a9510SRong-En Fan{       WIN win;
2449*4a1a9510SRong-En Fan        int ch;
2450*4a1a9510SRong-En Fan
2451*4a1a9510SRong-En Fan        initscr();                      /* Start curses mode            */
2452*4a1a9510SRong-En Fan        start_color();                  /* Start the color functionality */
2453*4a1a9510SRong-En Fan        cbreak();                       /* Line buffering disabled, Pass on
2454*4a1a9510SRong-En Fan                                         * everty thing to me           */
2455*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);           /* I need that nifty F1         */
2456*4a1a9510SRong-En Fan        noecho();
2457*4a1a9510SRong-En Fan        init_pair(1, COLOR_CYAN, COLOR_BLACK);
2458*4a1a9510SRong-En Fan
2459*4a1a9510SRong-En Fan        /* Initialize the window parameters */
2460*4a1a9510SRong-En Fan        init_win_params(&amp;win);
2461*4a1a9510SRong-En Fan        print_win_params(&amp;win);
2462*4a1a9510SRong-En Fan
2463*4a1a9510SRong-En Fan        attron(COLOR_PAIR(1));
2464*4a1a9510SRong-En Fan        printw("Press F1 to exit");
2465*4a1a9510SRong-En Fan        refresh();
2466*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(1));
2467*4a1a9510SRong-En Fan
2468*4a1a9510SRong-En Fan        create_box(&amp;win, TRUE);
2469*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
2470*4a1a9510SRong-En Fan        {       switch(ch)
2471*4a1a9510SRong-En Fan                {       case KEY_LEFT:
2472*4a1a9510SRong-En Fan                                create_box(&amp;win, FALSE);
2473*4a1a9510SRong-En Fan                                --win.startx;
2474*4a1a9510SRong-En Fan                                create_box(&amp;win, TRUE);
2475*4a1a9510SRong-En Fan                                break;
2476*4a1a9510SRong-En Fan                        case KEY_RIGHT:
2477*4a1a9510SRong-En Fan                                create_box(&amp;win, FALSE);
2478*4a1a9510SRong-En Fan                                ++win.startx;
2479*4a1a9510SRong-En Fan                                create_box(&amp;win, TRUE);
2480*4a1a9510SRong-En Fan                                break;
2481*4a1a9510SRong-En Fan                        case KEY_UP:
2482*4a1a9510SRong-En Fan                                create_box(&amp;win, FALSE);
2483*4a1a9510SRong-En Fan                                --win.starty;
2484*4a1a9510SRong-En Fan                                create_box(&amp;win, TRUE);
2485*4a1a9510SRong-En Fan                                break;
2486*4a1a9510SRong-En Fan                        case KEY_DOWN:
2487*4a1a9510SRong-En Fan                                create_box(&amp;win, FALSE);
2488*4a1a9510SRong-En Fan                                ++win.starty;
2489*4a1a9510SRong-En Fan                                create_box(&amp;win, TRUE);
2490*4a1a9510SRong-En Fan                                break;
2491*4a1a9510SRong-En Fan                }
2492*4a1a9510SRong-En Fan        }
2493*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
2494*4a1a9510SRong-En Fan        return 0;
2495*4a1a9510SRong-En Fan}
2496*4a1a9510SRong-En Fanvoid init_win_params(WIN *p_win)
2497*4a1a9510SRong-En Fan{
2498*4a1a9510SRong-En Fan        p_win-&gt;height = 3;
2499*4a1a9510SRong-En Fan        p_win-&gt;width = 10;
2500*4a1a9510SRong-En Fan        p_win-&gt;starty = (LINES - p_win-&gt;height)/2;
2501*4a1a9510SRong-En Fan        p_win-&gt;startx = (COLS - p_win-&gt;width)/2;
2502*4a1a9510SRong-En Fan
2503*4a1a9510SRong-En Fan        p_win-&gt;border.ls = '|';
2504*4a1a9510SRong-En Fan        p_win-&gt;border.rs = '|';
2505*4a1a9510SRong-En Fan        p_win-&gt;border.ts = '-';
2506*4a1a9510SRong-En Fan        p_win-&gt;border.bs = '-';
2507*4a1a9510SRong-En Fan        p_win-&gt;border.tl = '+';
2508*4a1a9510SRong-En Fan        p_win-&gt;border.tr = '+';
2509*4a1a9510SRong-En Fan        p_win-&gt;border.bl = '+';
2510*4a1a9510SRong-En Fan        p_win-&gt;border.br = '+';
2511*4a1a9510SRong-En Fan
2512*4a1a9510SRong-En Fan}
2513*4a1a9510SRong-En Fanvoid print_win_params(WIN *p_win)
2514*4a1a9510SRong-En Fan{
2515*4a1a9510SRong-En Fan#ifdef _DEBUG
2516*4a1a9510SRong-En Fan        mvprintw(25, 0, "%d %d %d %d", p_win-&gt;startx, p_win-&gt;starty,
2517*4a1a9510SRong-En Fan                                p_win-&gt;width, p_win-&gt;height);
2518*4a1a9510SRong-En Fan        refresh();
2519*4a1a9510SRong-En Fan#endif
2520*4a1a9510SRong-En Fan}
2521*4a1a9510SRong-En Fanvoid create_box(WIN *p_win, bool flag)
2522*4a1a9510SRong-En Fan{       int i, j;
2523*4a1a9510SRong-En Fan        int x, y, w, h;
2524*4a1a9510SRong-En Fan
2525*4a1a9510SRong-En Fan        x = p_win-&gt;startx;
2526*4a1a9510SRong-En Fan        y = p_win-&gt;starty;
2527*4a1a9510SRong-En Fan        w = p_win-&gt;width;
2528*4a1a9510SRong-En Fan        h = p_win-&gt;height;
2529*4a1a9510SRong-En Fan
2530*4a1a9510SRong-En Fan        if(flag == TRUE)
2531*4a1a9510SRong-En Fan        {       mvaddch(y, x, p_win-&gt;border.tl);
2532*4a1a9510SRong-En Fan                mvaddch(y, x + w, p_win-&gt;border.tr);
2533*4a1a9510SRong-En Fan                mvaddch(y + h, x, p_win-&gt;border.bl);
2534*4a1a9510SRong-En Fan                mvaddch(y + h, x + w, p_win-&gt;border.br);
2535*4a1a9510SRong-En Fan                mvhline(y, x + 1, p_win-&gt;border.ts, w - 1);
2536*4a1a9510SRong-En Fan                mvhline(y + h, x + 1, p_win-&gt;border.bs, w - 1);
2537*4a1a9510SRong-En Fan                mvvline(y + 1, x, p_win-&gt;border.ls, h - 1);
2538*4a1a9510SRong-En Fan                mvvline(y + 1, x + w, p_win-&gt;border.rs, h - 1);
2539*4a1a9510SRong-En Fan
2540*4a1a9510SRong-En Fan        }
2541*4a1a9510SRong-En Fan        else
2542*4a1a9510SRong-En Fan                for(j = y; j &lt;= y + h; ++j)
2543*4a1a9510SRong-En Fan                        for(i = x; i &lt;= x + w; ++i)
2544*4a1a9510SRong-En Fan                                mvaddch(j, i, ' ');
2545*4a1a9510SRong-En Fan
2546*4a1a9510SRong-En Fan        refresh();
2547*4a1a9510SRong-En Fan
2548*4a1a9510SRong-En Fan}</span>
2549*4a1a9510SRong-En Fan</pre>
2550*4a1a9510SRong-En Fan        </div>
2551*4a1a9510SRong-En Fan      </div>
2552*4a1a9510SRong-En Fan    </div>
2553*4a1a9510SRong-En Fan
2554*4a1a9510SRong-En Fan    <div class="SECT1">
2555*4a1a9510SRong-En Fan      <hr>
2556*4a1a9510SRong-En Fan
2557*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="COLOR" id="COLOR">10.
2558*4a1a9510SRong-En Fan      Colors</a></h2>
2559*4a1a9510SRong-En Fan
2560*4a1a9510SRong-En Fan      <div class="SECT2">
2561*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COLORBASICS" id=
2562*4a1a9510SRong-En Fan        "COLORBASICS">10.1. The basics</a></h3>
2563*4a1a9510SRong-En Fan
2564*4a1a9510SRong-En Fan        <p>Life seems dull with no colors. Curses has a nice
2565*4a1a9510SRong-En Fan        mechanism to handle colors. Let's get into the thick of the
2566*4a1a9510SRong-En Fan        things with a small program.</p>
2567*4a1a9510SRong-En Fan
2568*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2569*4a1a9510SRong-En Fan          <a name="BSICO" id="BSICO"></a>
2570*4a1a9510SRong-En Fan
2571*4a1a9510SRong-En Fan          <p><b>Example 9. A Simple Color example</b></p>
2572*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2573*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2574*4a1a9510SRong-En Fan
2575*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
2576*4a1a9510SRong-En Fanint main(int argc, char *argv[])
2577*4a1a9510SRong-En Fan{       initscr();                      /* Start curses mode            */
2578*4a1a9510SRong-En Fan        if(has_colors() == FALSE)
2579*4a1a9510SRong-En Fan        {       endwin();
2580*4a1a9510SRong-En Fan                printf("Your terminal does not support color\n");
2581*4a1a9510SRong-En Fan                exit(1);
2582*4a1a9510SRong-En Fan        }
2583*4a1a9510SRong-En Fan        start_color();                  /* Start color                  */
2584*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
2585*4a1a9510SRong-En Fan
2586*4a1a9510SRong-En Fan        attron(COLOR_PAIR(1));
2587*4a1a9510SRong-En Fan        print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ...");
2588*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(1));
2589*4a1a9510SRong-En Fan        getch();
2590*4a1a9510SRong-En Fan        endwin();
2591*4a1a9510SRong-En Fan}
2592*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string)
2593*4a1a9510SRong-En Fan{       int length, x, y;
2594*4a1a9510SRong-En Fan        float temp;
2595*4a1a9510SRong-En Fan
2596*4a1a9510SRong-En Fan        if(win == NULL)
2597*4a1a9510SRong-En Fan                win = stdscr;
2598*4a1a9510SRong-En Fan        getyx(win, y, x);
2599*4a1a9510SRong-En Fan        if(startx != 0)
2600*4a1a9510SRong-En Fan                x = startx;
2601*4a1a9510SRong-En Fan        if(starty != 0)
2602*4a1a9510SRong-En Fan                y = starty;
2603*4a1a9510SRong-En Fan        if(width == 0)
2604*4a1a9510SRong-En Fan                width = 80;
2605*4a1a9510SRong-En Fan
2606*4a1a9510SRong-En Fan        length = strlen(string);
2607*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
2608*4a1a9510SRong-En Fan        x = startx + (int)temp;
2609*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
2610*4a1a9510SRong-En Fan        refresh();
2611*4a1a9510SRong-En Fan}
2612*4a1a9510SRong-En Fan</span>
2613*4a1a9510SRong-En Fan</pre>
2614*4a1a9510SRong-En Fan        </div>
2615*4a1a9510SRong-En Fan
2616*4a1a9510SRong-En Fan        <p>As you can see, to start using color, you should first
2617*4a1a9510SRong-En Fan        call the function <tt class="LITERAL">start_color()</tt>.
2618*4a1a9510SRong-En Fan        After that, you can use color capabilities of your
2619*4a1a9510SRong-En Fan        terminals using various functions. To find out whether a
2620*4a1a9510SRong-En Fan        terminal has color capabilities or not, you can use
2621*4a1a9510SRong-En Fan        <tt class="LITERAL">has_colors()</tt> function, which
2622*4a1a9510SRong-En Fan        returns FALSE if the terminal does not support color.</p>
2623*4a1a9510SRong-En Fan
2624*4a1a9510SRong-En Fan        <p>Curses initializes all the colors supported by terminal
2625*4a1a9510SRong-En Fan        when start_color() is called. These can be accessed by the
2626*4a1a9510SRong-En Fan        define constants like <tt class="LITERAL">COLOR_BLACK</tt>
2627*4a1a9510SRong-En Fan        etc. Now to actually start using colors, you have to define
2628*4a1a9510SRong-En Fan        pairs. Colors are always used in pairs. That means you have
2629*4a1a9510SRong-En Fan        to use the function <tt class="LITERAL">init_pair()</tt> to
2630*4a1a9510SRong-En Fan        define the foreground and background for the pair number
2631*4a1a9510SRong-En Fan        you give. After that that pair number can be used as a
2632*4a1a9510SRong-En Fan        normal attribute with <tt class=
2633*4a1a9510SRong-En Fan        "LITERAL">COLOR_PAIR()</tt>function. This may seem to be
2634*4a1a9510SRong-En Fan        cumbersome at first. But this elegant solution allows us to
2635*4a1a9510SRong-En Fan        manage color pairs very easily. To appreciate it, you have
2636*4a1a9510SRong-En Fan        to look into the the source code of "dialog", a utility for
2637*4a1a9510SRong-En Fan        displaying dialog boxes from shell scripts. The developers
2638*4a1a9510SRong-En Fan        have defined foreground and background combinations for all
2639*4a1a9510SRong-En Fan        the colors they might need and initialized at the
2640*4a1a9510SRong-En Fan        beginning. This makes it very easy to set attributes just
2641*4a1a9510SRong-En Fan        by accessing a pair which we already have defined as a
2642*4a1a9510SRong-En Fan        constant.</p>
2643*4a1a9510SRong-En Fan
2644*4a1a9510SRong-En Fan        <p>The following colors are defined in <tt class=
2645*4a1a9510SRong-En Fan        "LITERAL">curses.h</tt>. You can use these as parameters
2646*4a1a9510SRong-En Fan        for various color functions.</p>
2647*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2648*4a1a9510SRong-En Fan        COLOR_BLACK   0
2649*4a1a9510SRong-En Fan        COLOR_RED     1
2650*4a1a9510SRong-En Fan        COLOR_GREEN   2
2651*4a1a9510SRong-En Fan        COLOR_YELLOW  3
2652*4a1a9510SRong-En Fan        COLOR_BLUE    4
2653*4a1a9510SRong-En Fan        COLOR_MAGENTA 5
2654*4a1a9510SRong-En Fan        COLOR_CYAN    6
2655*4a1a9510SRong-En Fan        COLOR_WHITE   7
2656*4a1a9510SRong-En Fan</pre>
2657*4a1a9510SRong-En Fan      </div>
2658*4a1a9510SRong-En Fan
2659*4a1a9510SRong-En Fan      <div class="SECT2">
2660*4a1a9510SRong-En Fan        <hr>
2661*4a1a9510SRong-En Fan
2662*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="CHANGECOLORDEFS" id=
2663*4a1a9510SRong-En Fan        "CHANGECOLORDEFS">10.2. Changing Color Definitions</a></h3>
2664*4a1a9510SRong-En Fan
2665*4a1a9510SRong-En Fan        <p>The function <tt class="LITERAL">init_color()</tt>can be
2666*4a1a9510SRong-En Fan        used to change the rgb values for the colors defined by
2667*4a1a9510SRong-En Fan        curses initially. Say you wanted to lighten the intensity
2668*4a1a9510SRong-En Fan        of red color by a minuscule. Then you can use this function
2669*4a1a9510SRong-En Fan        as</p>
2670*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2671*4a1a9510SRong-En Fan    init_color(COLOR_RED, 700, 0, 0);
2672*4a1a9510SRong-En Fan    /* param 1     : color name
2673*4a1a9510SRong-En Fan     * param 2, 3, 4 : rgb content min = 0, max = 1000 */
2674*4a1a9510SRong-En Fan</pre>
2675*4a1a9510SRong-En Fan
2676*4a1a9510SRong-En Fan        <p>If your terminal cannot change the color definitions,
2677*4a1a9510SRong-En Fan        the function returns ERR. The function <tt class=
2678*4a1a9510SRong-En Fan        "LITERAL">can_change_color()</tt> can be used to find out
2679*4a1a9510SRong-En Fan        whether the terminal has the capability of changing color
2680*4a1a9510SRong-En Fan        content or not. The rgb content is scaled from 0 to 1000.
2681*4a1a9510SRong-En Fan        Initially RED color is defined with content 1000(r), 0(g),
2682*4a1a9510SRong-En Fan        0(b).</p>
2683*4a1a9510SRong-En Fan      </div>
2684*4a1a9510SRong-En Fan
2685*4a1a9510SRong-En Fan      <div class="SECT2">
2686*4a1a9510SRong-En Fan        <hr>
2687*4a1a9510SRong-En Fan
2688*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COLORCONTENT" id=
2689*4a1a9510SRong-En Fan        "COLORCONTENT">10.3. Color Content</a></h3>
2690*4a1a9510SRong-En Fan
2691*4a1a9510SRong-En Fan        <p>The functions <tt class="LITERAL">color_content()</tt>
2692*4a1a9510SRong-En Fan        and <tt class="LITERAL">pair_content()</tt> can be used to
2693*4a1a9510SRong-En Fan        find the color content and foreground, background
2694*4a1a9510SRong-En Fan        combination for the pair.</p>
2695*4a1a9510SRong-En Fan      </div>
2696*4a1a9510SRong-En Fan    </div>
2697*4a1a9510SRong-En Fan
2698*4a1a9510SRong-En Fan    <div class="SECT1">
2699*4a1a9510SRong-En Fan      <hr>
2700*4a1a9510SRong-En Fan
2701*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="KEYS" id="KEYS">11. Interfacing
2702*4a1a9510SRong-En Fan      with the key board</a></h2>
2703*4a1a9510SRong-En Fan
2704*4a1a9510SRong-En Fan      <div class="SECT2">
2705*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="KEYSBASICS" id=
2706*4a1a9510SRong-En Fan        "KEYSBASICS">11.1. The Basics</a></h3>
2707*4a1a9510SRong-En Fan
2708*4a1a9510SRong-En Fan        <p>No GUI is complete without a strong user interface and
2709*4a1a9510SRong-En Fan        to interact with the user, a curses program should be
2710*4a1a9510SRong-En Fan        sensitive to key presses or the mouse actions done by the
2711*4a1a9510SRong-En Fan        user. Let's deal with the keys first.</p>
2712*4a1a9510SRong-En Fan
2713*4a1a9510SRong-En Fan        <p>As you have seen in almost all of the above examples,
2714*4a1a9510SRong-En Fan        it's very easy to get key input from the user. A simple way
2715*4a1a9510SRong-En Fan        of getting key presses is to use <tt class=
2716*4a1a9510SRong-En Fan        "LITERAL">getch()</tt> function. The cbreak mode should be
2717*4a1a9510SRong-En Fan        enabled to read keys when you are interested in reading
2718*4a1a9510SRong-En Fan        individual key hits rather than complete lines of text
2719*4a1a9510SRong-En Fan        (which usually end with a carriage return). keypad should
2720*4a1a9510SRong-En Fan        be enabled to get the Functions keys, arrow keys etc. See
2721*4a1a9510SRong-En Fan        the initialization section for details.</p>
2722*4a1a9510SRong-En Fan
2723*4a1a9510SRong-En Fan        <p><tt class="LITERAL">getch()</tt> returns an integer
2724*4a1a9510SRong-En Fan        corresponding to the key pressed. If it is a normal
2725*4a1a9510SRong-En Fan        character, the integer value will be equivalent to the
2726*4a1a9510SRong-En Fan        character. Otherwise it returns a number which can be
2727*4a1a9510SRong-En Fan        matched with the constants defined in <tt class=
2728*4a1a9510SRong-En Fan        "LITERAL">curses.h</tt>. For example if the user presses
2729*4a1a9510SRong-En Fan        F1, the integer returned is 265. This can be checked using
2730*4a1a9510SRong-En Fan        the macro KEY_F() defined in curses.h. This makes reading
2731*4a1a9510SRong-En Fan        keys portable and easy to manage.</p>
2732*4a1a9510SRong-En Fan
2733*4a1a9510SRong-En Fan        <p>For example, if you call getch() like this</p>
2734*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2735*4a1a9510SRong-En Fan    int ch;
2736*4a1a9510SRong-En Fan
2737*4a1a9510SRong-En Fan    ch = getch();
2738*4a1a9510SRong-En Fan</pre>
2739*4a1a9510SRong-En Fan
2740*4a1a9510SRong-En Fan        <p>getch() will wait for the user to press a key, (unless
2741*4a1a9510SRong-En Fan        you specified a timeout) and when user presses a key, the
2742*4a1a9510SRong-En Fan        corresponding integer is returned. Then you can check the
2743*4a1a9510SRong-En Fan        value returned with the constants defined in curses.h to
2744*4a1a9510SRong-En Fan        match against the keys you want.</p>
2745*4a1a9510SRong-En Fan
2746*4a1a9510SRong-En Fan        <p>The following code piece will do that job.</p>
2747*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2748*4a1a9510SRong-En Fan    if(ch == KEY_LEFT)
2749*4a1a9510SRong-En Fan        printw("Left arrow is pressed\n");
2750*4a1a9510SRong-En Fan</pre>
2751*4a1a9510SRong-En Fan
2752*4a1a9510SRong-En Fan        <p>Let's write a small program which creates a menu which
2753*4a1a9510SRong-En Fan        can be navigated by up and down arrows.</p>
2754*4a1a9510SRong-En Fan      </div>
2755*4a1a9510SRong-En Fan
2756*4a1a9510SRong-En Fan      <div class="SECT2">
2757*4a1a9510SRong-En Fan        <hr>
2758*4a1a9510SRong-En Fan
2759*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="SIMPLEKEYEX" id=
2760*4a1a9510SRong-En Fan        "SIMPLEKEYEX">11.2. A Simple Key Usage example</a></h3>
2761*4a1a9510SRong-En Fan
2762*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2763*4a1a9510SRong-En Fan          <a name="BSIKE" id="BSIKE"></a>
2764*4a1a9510SRong-En Fan
2765*4a1a9510SRong-En Fan          <p><b>Example 10. A Simple Key Usage example</b></p>
2766*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2767*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;stdio.h&gt;
2768*4a1a9510SRong-En Fan#include &lt;ncurses.h&gt;
2769*4a1a9510SRong-En Fan
2770*4a1a9510SRong-En Fan#define WIDTH 30
2771*4a1a9510SRong-En Fan#define HEIGHT 10
2772*4a1a9510SRong-En Fan
2773*4a1a9510SRong-En Fanint startx = 0;
2774*4a1a9510SRong-En Fanint starty = 0;
2775*4a1a9510SRong-En Fan
2776*4a1a9510SRong-En Fanchar *choices[] = {
2777*4a1a9510SRong-En Fan                        "Choice 1",
2778*4a1a9510SRong-En Fan                        "Choice 2",
2779*4a1a9510SRong-En Fan                        "Choice 3",
2780*4a1a9510SRong-En Fan                        "Choice 4",
2781*4a1a9510SRong-En Fan                        "Exit",
2782*4a1a9510SRong-En Fan                  };
2783*4a1a9510SRong-En Fanint n_choices = sizeof(choices) / sizeof(char *);
2784*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight);
2785*4a1a9510SRong-En Fan
2786*4a1a9510SRong-En Fanint main()
2787*4a1a9510SRong-En Fan{       WINDOW *menu_win;
2788*4a1a9510SRong-En Fan        int highlight = 1;
2789*4a1a9510SRong-En Fan        int choice = 0;
2790*4a1a9510SRong-En Fan        int c;
2791*4a1a9510SRong-En Fan
2792*4a1a9510SRong-En Fan        initscr();
2793*4a1a9510SRong-En Fan        clear();
2794*4a1a9510SRong-En Fan        noecho();
2795*4a1a9510SRong-En Fan        cbreak();       /* Line buffering disabled. pass on everything */
2796*4a1a9510SRong-En Fan        startx = (80 - WIDTH) / 2;
2797*4a1a9510SRong-En Fan        starty = (24 - HEIGHT) / 2;
2798*4a1a9510SRong-En Fan
2799*4a1a9510SRong-En Fan        menu_win = newwin(HEIGHT, WIDTH, starty, startx);
2800*4a1a9510SRong-En Fan        keypad(menu_win, TRUE);
2801*4a1a9510SRong-En Fan        mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
2802*4a1a9510SRong-En Fan        refresh();
2803*4a1a9510SRong-En Fan        print_menu(menu_win, highlight);
2804*4a1a9510SRong-En Fan        while(1)
2805*4a1a9510SRong-En Fan        {       c = wgetch(menu_win);
2806*4a1a9510SRong-En Fan                switch(c)
2807*4a1a9510SRong-En Fan                {       case KEY_UP:
2808*4a1a9510SRong-En Fan                                if(highlight == 1)
2809*4a1a9510SRong-En Fan                                        highlight = n_choices;
2810*4a1a9510SRong-En Fan                                else
2811*4a1a9510SRong-En Fan                                        --highlight;
2812*4a1a9510SRong-En Fan                                break;
2813*4a1a9510SRong-En Fan                        case KEY_DOWN:
2814*4a1a9510SRong-En Fan                                if(highlight == n_choices)
2815*4a1a9510SRong-En Fan                                        highlight = 1;
2816*4a1a9510SRong-En Fan                                else
2817*4a1a9510SRong-En Fan                                        ++highlight;
2818*4a1a9510SRong-En Fan                                break;
2819*4a1a9510SRong-En Fan                        case 10:
2820*4a1a9510SRong-En Fan                                choice = highlight;
2821*4a1a9510SRong-En Fan                                break;
2822*4a1a9510SRong-En Fan                        default:
2823*4a1a9510SRong-En Fan                                mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
2824*4a1a9510SRong-En Fan                                refresh();
2825*4a1a9510SRong-En Fan                                break;
2826*4a1a9510SRong-En Fan                }
2827*4a1a9510SRong-En Fan                print_menu(menu_win, highlight);
2828*4a1a9510SRong-En Fan                if(choice != 0) /* User did a choice come out of the infinite loop */
2829*4a1a9510SRong-En Fan                        break;
2830*4a1a9510SRong-En Fan        }
2831*4a1a9510SRong-En Fan        mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]);
2832*4a1a9510SRong-En Fan        clrtoeol();
2833*4a1a9510SRong-En Fan        refresh();
2834*4a1a9510SRong-En Fan        endwin();
2835*4a1a9510SRong-En Fan        return 0;
2836*4a1a9510SRong-En Fan}
2837*4a1a9510SRong-En Fan
2838*4a1a9510SRong-En Fan
2839*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight)
2840*4a1a9510SRong-En Fan{
2841*4a1a9510SRong-En Fan        int x, y, i;
2842*4a1a9510SRong-En Fan
2843*4a1a9510SRong-En Fan        x = 2;
2844*4a1a9510SRong-En Fan        y = 2;
2845*4a1a9510SRong-En Fan        box(menu_win, 0, 0);
2846*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
2847*4a1a9510SRong-En Fan        {       if(highlight == i + 1) /* High light the present choice */
2848*4a1a9510SRong-En Fan                {       wattron(menu_win, A_REVERSE);
2849*4a1a9510SRong-En Fan                        mvwprintw(menu_win, y, x, "%s", choices[i]);
2850*4a1a9510SRong-En Fan                        wattroff(menu_win, A_REVERSE);
2851*4a1a9510SRong-En Fan                }
2852*4a1a9510SRong-En Fan                else
2853*4a1a9510SRong-En Fan                        mvwprintw(menu_win, y, x, "%s", choices[i]);
2854*4a1a9510SRong-En Fan                ++y;
2855*4a1a9510SRong-En Fan        }
2856*4a1a9510SRong-En Fan        wrefresh(menu_win);
2857*4a1a9510SRong-En Fan}
2858*4a1a9510SRong-En Fan</span>
2859*4a1a9510SRong-En Fan</pre>
2860*4a1a9510SRong-En Fan        </div>
2861*4a1a9510SRong-En Fan      </div>
2862*4a1a9510SRong-En Fan    </div>
2863*4a1a9510SRong-En Fan
2864*4a1a9510SRong-En Fan    <div class="SECT1">
2865*4a1a9510SRong-En Fan      <hr>
2866*4a1a9510SRong-En Fan
2867*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="MOUSE" id="MOUSE">12. Interfacing
2868*4a1a9510SRong-En Fan      with the mouse</a></h2>
2869*4a1a9510SRong-En Fan
2870*4a1a9510SRong-En Fan      <p>Now that you have seen how to get keys, lets do the same
2871*4a1a9510SRong-En Fan      thing from mouse. Usually each UI allows the user to interact
2872*4a1a9510SRong-En Fan      with both keyboard and mouse.</p>
2873*4a1a9510SRong-En Fan
2874*4a1a9510SRong-En Fan      <div class="SECT2">
2875*4a1a9510SRong-En Fan        <hr>
2876*4a1a9510SRong-En Fan
2877*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MOUSEBASICS" id=
2878*4a1a9510SRong-En Fan        "MOUSEBASICS">12.1. The Basics</a></h3>
2879*4a1a9510SRong-En Fan
2880*4a1a9510SRong-En Fan        <p>Before you do any thing else, the events you want to
2881*4a1a9510SRong-En Fan        receive have to be enabled with <tt class=
2882*4a1a9510SRong-En Fan        "LITERAL">mousemask()</tt>.</p>
2883*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2884*4a1a9510SRong-En Fan    mousemask(  mmask_t newmask,    /* The events you want to listen to */
2885*4a1a9510SRong-En Fan                mmask_t *oldmask)    /* The old events mask                */
2886*4a1a9510SRong-En Fan</pre>
2887*4a1a9510SRong-En Fan
2888*4a1a9510SRong-En Fan        <p>The first parameter to above function is a bit mask of
2889*4a1a9510SRong-En Fan        events you would like to listen. By default, all the events
2890*4a1a9510SRong-En Fan        are turned off. The bit mask <tt class=
2891*4a1a9510SRong-En Fan        "LITERAL">ALL_MOUSE_EVENTS</tt> can be used to get all the
2892*4a1a9510SRong-En Fan        events.</p>
2893*4a1a9510SRong-En Fan
2894*4a1a9510SRong-En Fan        <p>The following are all the event masks:</p>
2895*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2896*4a1a9510SRong-En Fan    Name            Description
2897*4a1a9510SRong-En Fan       ---------------------------------------------------------------------
2898*4a1a9510SRong-En Fan       BUTTON1_PRESSED          mouse button 1 down
2899*4a1a9510SRong-En Fan       BUTTON1_RELEASED         mouse button 1 up
2900*4a1a9510SRong-En Fan       BUTTON1_CLICKED          mouse button 1 clicked
2901*4a1a9510SRong-En Fan       BUTTON1_DOUBLE_CLICKED   mouse button 1 double clicked
2902*4a1a9510SRong-En Fan       BUTTON1_TRIPLE_CLICKED   mouse button 1 triple clicked
2903*4a1a9510SRong-En Fan       BUTTON2_PRESSED          mouse button 2 down
2904*4a1a9510SRong-En Fan       BUTTON2_RELEASED         mouse button 2 up
2905*4a1a9510SRong-En Fan       BUTTON2_CLICKED          mouse button 2 clicked
2906*4a1a9510SRong-En Fan       BUTTON2_DOUBLE_CLICKED   mouse button 2 double clicked
2907*4a1a9510SRong-En Fan       BUTTON2_TRIPLE_CLICKED   mouse button 2 triple clicked
2908*4a1a9510SRong-En Fan       BUTTON3_PRESSED          mouse button 3 down
2909*4a1a9510SRong-En Fan       BUTTON3_RELEASED         mouse button 3 up
2910*4a1a9510SRong-En Fan       BUTTON3_CLICKED          mouse button 3 clicked
2911*4a1a9510SRong-En Fan       BUTTON3_DOUBLE_CLICKED   mouse button 3 double clicked
2912*4a1a9510SRong-En Fan       BUTTON3_TRIPLE_CLICKED   mouse button 3 triple clicked
2913*4a1a9510SRong-En Fan       BUTTON4_PRESSED          mouse button 4 down
2914*4a1a9510SRong-En Fan       BUTTON4_RELEASED         mouse button 4 up
2915*4a1a9510SRong-En Fan       BUTTON4_CLICKED          mouse button 4 clicked
2916*4a1a9510SRong-En Fan       BUTTON4_DOUBLE_CLICKED   mouse button 4 double clicked
2917*4a1a9510SRong-En Fan       BUTTON4_TRIPLE_CLICKED   mouse button 4 triple clicked
2918*4a1a9510SRong-En Fan       BUTTON_SHIFT             shift was down during button state change
2919*4a1a9510SRong-En Fan       BUTTON_CTRL              control was down during button state change
2920*4a1a9510SRong-En Fan       BUTTON_ALT               alt was down during button state change
2921*4a1a9510SRong-En Fan       ALL_MOUSE_EVENTS         report all button state changes
2922*4a1a9510SRong-En Fan       REPORT_MOUSE_POSITION    report mouse movement
2923*4a1a9510SRong-En Fan</pre>
2924*4a1a9510SRong-En Fan      </div>
2925*4a1a9510SRong-En Fan
2926*4a1a9510SRong-En Fan      <div class="SECT2">
2927*4a1a9510SRong-En Fan        <hr>
2928*4a1a9510SRong-En Fan
2929*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="GETTINGEVENTS" id=
2930*4a1a9510SRong-En Fan        "GETTINGEVENTS">12.2. Getting the events</a></h3>
2931*4a1a9510SRong-En Fan
2932*4a1a9510SRong-En Fan        <p>Once a class of mouse events have been enabled, getch()
2933*4a1a9510SRong-En Fan        class of functions return KEY_MOUSE every time some mouse
2934*4a1a9510SRong-En Fan        event happens. Then the mouse event can be retrieved with
2935*4a1a9510SRong-En Fan        <tt class="LITERAL">getmouse()</tt>.</p>
2936*4a1a9510SRong-En Fan
2937*4a1a9510SRong-En Fan        <p>The code approximately looks like this:</p>
2938*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2939*4a1a9510SRong-En Fan    MEVENT event;
2940*4a1a9510SRong-En Fan
2941*4a1a9510SRong-En Fan    ch = getch();
2942*4a1a9510SRong-En Fan    if(ch == KEY_MOUSE)
2943*4a1a9510SRong-En Fan        if(getmouse(&amp;event) == OK)
2944*4a1a9510SRong-En Fan            .    /* Do some thing with the event */
2945*4a1a9510SRong-En Fan            .
2946*4a1a9510SRong-En Fan            .
2947*4a1a9510SRong-En Fan</pre>
2948*4a1a9510SRong-En Fan
2949*4a1a9510SRong-En Fan        <p>getmouse() returns the event into the pointer given to
2950*4a1a9510SRong-En Fan        it. It's a structure which contains</p>
2951*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2952*4a1a9510SRong-En Fan    typedef struct
2953*4a1a9510SRong-En Fan    {
2954*4a1a9510SRong-En Fan        short id;         /* ID to distinguish multiple devices */
2955*4a1a9510SRong-En Fan        int x, y, z;      /* event coordinates */
2956*4a1a9510SRong-En Fan        mmask_t bstate;   /* button state bits */
2957*4a1a9510SRong-En Fan    }
2958*4a1a9510SRong-En Fan</pre>
2959*4a1a9510SRong-En Fan
2960*4a1a9510SRong-En Fan        <p>The <tt class="LITERAL">bstate</tt> is the main variable
2961*4a1a9510SRong-En Fan        we are interested in. It tells the button state of the
2962*4a1a9510SRong-En Fan        mouse.</p>
2963*4a1a9510SRong-En Fan
2964*4a1a9510SRong-En Fan        <p>Then with a code snippet like the following, we can find
2965*4a1a9510SRong-En Fan        out what happened.</p>
2966*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
2967*4a1a9510SRong-En Fan    if(event.bstate &amp; BUTTON1_PRESSED)
2968*4a1a9510SRong-En Fan        printw("Left Button Pressed");
2969*4a1a9510SRong-En Fan</pre>
2970*4a1a9510SRong-En Fan      </div>
2971*4a1a9510SRong-En Fan
2972*4a1a9510SRong-En Fan      <div class="SECT2">
2973*4a1a9510SRong-En Fan        <hr>
2974*4a1a9510SRong-En Fan
2975*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MOUSETOGETHER" id=
2976*4a1a9510SRong-En Fan        "MOUSETOGETHER">12.3. Putting it all Together</a></h3>
2977*4a1a9510SRong-En Fan
2978*4a1a9510SRong-En Fan        <p>That's pretty much interfacing with mouse. Let's create
2979*4a1a9510SRong-En Fan        the same menu and enable mouse interaction. To make things
2980*4a1a9510SRong-En Fan        simpler, key handling is removed.</p>
2981*4a1a9510SRong-En Fan
2982*4a1a9510SRong-En Fan        <div class="EXAMPLE">
2983*4a1a9510SRong-En Fan          <a name="BMOME" id="BMOME"></a>
2984*4a1a9510SRong-En Fan
2985*4a1a9510SRong-En Fan          <p><b>Example 11. Access the menu with mouse !!!</b></p>
2986*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
2987*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
2988*4a1a9510SRong-En Fan
2989*4a1a9510SRong-En Fan#define WIDTH 30
2990*4a1a9510SRong-En Fan#define HEIGHT 10
2991*4a1a9510SRong-En Fan
2992*4a1a9510SRong-En Fanint startx = 0;
2993*4a1a9510SRong-En Fanint starty = 0;
2994*4a1a9510SRong-En Fan
2995*4a1a9510SRong-En Fanchar *choices[] = {     "Choice 1",
2996*4a1a9510SRong-En Fan                        "Choice 2",
2997*4a1a9510SRong-En Fan                        "Choice 3",
2998*4a1a9510SRong-En Fan                        "Choice 4",
2999*4a1a9510SRong-En Fan                        "Exit",
3000*4a1a9510SRong-En Fan                  };
3001*4a1a9510SRong-En Fan
3002*4a1a9510SRong-En Fanint n_choices = sizeof(choices) / sizeof(char *);
3003*4a1a9510SRong-En Fan
3004*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight);
3005*4a1a9510SRong-En Fanvoid report_choice(int mouse_x, int mouse_y, int *p_choice);
3006*4a1a9510SRong-En Fan
3007*4a1a9510SRong-En Fanint main()
3008*4a1a9510SRong-En Fan{       int c, choice = 0;
3009*4a1a9510SRong-En Fan        WINDOW *menu_win;
3010*4a1a9510SRong-En Fan        MEVENT event;
3011*4a1a9510SRong-En Fan
3012*4a1a9510SRong-En Fan        /* Initialize curses */
3013*4a1a9510SRong-En Fan        initscr();
3014*4a1a9510SRong-En Fan        clear();
3015*4a1a9510SRong-En Fan        noecho();
3016*4a1a9510SRong-En Fan        cbreak();       //Line buffering disabled. pass on everything
3017*4a1a9510SRong-En Fan
3018*4a1a9510SRong-En Fan        /* Try to put the window in the middle of screen */
3019*4a1a9510SRong-En Fan        startx = (80 - WIDTH) / 2;
3020*4a1a9510SRong-En Fan        starty = (24 - HEIGHT) / 2;
3021*4a1a9510SRong-En Fan
3022*4a1a9510SRong-En Fan        attron(A_REVERSE);
3023*4a1a9510SRong-En Fan        mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
3024*4a1a9510SRong-En Fan        refresh();
3025*4a1a9510SRong-En Fan        attroff(A_REVERSE);
3026*4a1a9510SRong-En Fan
3027*4a1a9510SRong-En Fan        /* Print the menu for the first time */
3028*4a1a9510SRong-En Fan        menu_win = newwin(HEIGHT, WIDTH, starty, startx);
3029*4a1a9510SRong-En Fan        print_menu(menu_win, 1);
3030*4a1a9510SRong-En Fan        /* Get all the mouse events */
3031*4a1a9510SRong-En Fan        mousemask(ALL_MOUSE_EVENTS, NULL);
3032*4a1a9510SRong-En Fan
3033*4a1a9510SRong-En Fan        while(1)
3034*4a1a9510SRong-En Fan        {       c = wgetch(menu_win);
3035*4a1a9510SRong-En Fan                switch(c)
3036*4a1a9510SRong-En Fan                {       case KEY_MOUSE:
3037*4a1a9510SRong-En Fan                        if(getmouse(&amp;event) == OK)
3038*4a1a9510SRong-En Fan                        {       /* When the user clicks left mouse button */
3039*4a1a9510SRong-En Fan                                if(event.bstate &amp; BUTTON1_PRESSED)
3040*4a1a9510SRong-En Fan                                {       report_choice(event.x + 1, event.y + 1, &amp;choice);
3041*4a1a9510SRong-En Fan                                        if(choice == -1) //Exit chosen
3042*4a1a9510SRong-En Fan                                                goto end;
3043*4a1a9510SRong-En Fan                                        mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
3044*4a1a9510SRong-En Fan                                        refresh();
3045*4a1a9510SRong-En Fan                                }
3046*4a1a9510SRong-En Fan                        }
3047*4a1a9510SRong-En Fan                        print_menu(menu_win, choice);
3048*4a1a9510SRong-En Fan                        break;
3049*4a1a9510SRong-En Fan                }
3050*4a1a9510SRong-En Fan        }
3051*4a1a9510SRong-En Fanend:
3052*4a1a9510SRong-En Fan        endwin();
3053*4a1a9510SRong-En Fan        return 0;
3054*4a1a9510SRong-En Fan}
3055*4a1a9510SRong-En Fan
3056*4a1a9510SRong-En Fan
3057*4a1a9510SRong-En Fanvoid print_menu(WINDOW *menu_win, int highlight)
3058*4a1a9510SRong-En Fan{
3059*4a1a9510SRong-En Fan        int x, y, i;
3060*4a1a9510SRong-En Fan
3061*4a1a9510SRong-En Fan        x = 2;
3062*4a1a9510SRong-En Fan        y = 2;
3063*4a1a9510SRong-En Fan        box(menu_win, 0, 0);
3064*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
3065*4a1a9510SRong-En Fan        {       if(highlight == i + 1)
3066*4a1a9510SRong-En Fan                {       wattron(menu_win, A_REVERSE);
3067*4a1a9510SRong-En Fan                        mvwprintw(menu_win, y, x, "%s", choices[i]);
3068*4a1a9510SRong-En Fan                        wattroff(menu_win, A_REVERSE);
3069*4a1a9510SRong-En Fan                }
3070*4a1a9510SRong-En Fan                else
3071*4a1a9510SRong-En Fan                        mvwprintw(menu_win, y, x, "%s", choices[i]);
3072*4a1a9510SRong-En Fan                ++y;
3073*4a1a9510SRong-En Fan        }
3074*4a1a9510SRong-En Fan        wrefresh(menu_win);
3075*4a1a9510SRong-En Fan}
3076*4a1a9510SRong-En Fan
3077*4a1a9510SRong-En Fan/* Report the choice according to mouse position */
3078*4a1a9510SRong-En Fanvoid report_choice(int mouse_x, int mouse_y, int *p_choice)
3079*4a1a9510SRong-En Fan{       int i,j, choice;
3080*4a1a9510SRong-En Fan
3081*4a1a9510SRong-En Fan        i = startx + 2;
3082*4a1a9510SRong-En Fan        j = starty + 3;
3083*4a1a9510SRong-En Fan
3084*4a1a9510SRong-En Fan        for(choice = 0; choice &lt; n_choices; ++choice)
3085*4a1a9510SRong-En Fan                if(mouse_y == j + choice &amp;&amp; mouse_x &gt;= i &amp;&amp; mouse_x &lt;= i + strlen(choices[choice]))
3086*4a1a9510SRong-En Fan                {       if(choice == n_choices - 1)
3087*4a1a9510SRong-En Fan                                *p_choice = -1;
3088*4a1a9510SRong-En Fan                        else
3089*4a1a9510SRong-En Fan                                *p_choice = choice + 1;
3090*4a1a9510SRong-En Fan                        break;
3091*4a1a9510SRong-En Fan                }
3092*4a1a9510SRong-En Fan}</span>
3093*4a1a9510SRong-En Fan</pre>
3094*4a1a9510SRong-En Fan        </div>
3095*4a1a9510SRong-En Fan      </div>
3096*4a1a9510SRong-En Fan
3097*4a1a9510SRong-En Fan      <div class="SECT2">
3098*4a1a9510SRong-En Fan        <hr>
3099*4a1a9510SRong-En Fan
3100*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MISCMOUSEFUNCS" id=
3101*4a1a9510SRong-En Fan        "MISCMOUSEFUNCS">12.4. Miscellaneous Functions</a></h3>
3102*4a1a9510SRong-En Fan
3103*4a1a9510SRong-En Fan        <p>The functions mouse_trafo() and wmouse_trafo() can be
3104*4a1a9510SRong-En Fan        used to convert to mouse co-ordinates to screen relative
3105*4a1a9510SRong-En Fan        co-ordinates. See curs_mouse(3X) man page for details.</p>
3106*4a1a9510SRong-En Fan
3107*4a1a9510SRong-En Fan        <p>The mouseinterval function sets the maximum time (in
3108*4a1a9510SRong-En Fan        thousands of a second) that can elapse between press and
3109*4a1a9510SRong-En Fan        release events in order for them to be recognized as a
3110*4a1a9510SRong-En Fan        click. This function returns the previous interval value.
3111*4a1a9510SRong-En Fan        The default is one fifth of a second.</p>
3112*4a1a9510SRong-En Fan      </div>
3113*4a1a9510SRong-En Fan    </div>
3114*4a1a9510SRong-En Fan
3115*4a1a9510SRong-En Fan    <div class="SECT1">
3116*4a1a9510SRong-En Fan      <hr>
3117*4a1a9510SRong-En Fan
3118*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="SCREEN" id="SCREEN">13. Screen
3119*4a1a9510SRong-En Fan      Manipulation</a></h2>
3120*4a1a9510SRong-En Fan
3121*4a1a9510SRong-En Fan      <p>In this section, we will look into some functions, which
3122*4a1a9510SRong-En Fan      allow us to manage the screen efficiently and to write some
3123*4a1a9510SRong-En Fan      fancy programs. This is especially important in writing
3124*4a1a9510SRong-En Fan      games.</p>
3125*4a1a9510SRong-En Fan
3126*4a1a9510SRong-En Fan      <div class="SECT2">
3127*4a1a9510SRong-En Fan        <hr>
3128*4a1a9510SRong-En Fan
3129*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="GETYX" id="GETYX">13.1. getyx()
3130*4a1a9510SRong-En Fan        functions</a></h3>
3131*4a1a9510SRong-En Fan
3132*4a1a9510SRong-En Fan        <p>The function <tt class="LITERAL">getyx()</tt> can be
3133*4a1a9510SRong-En Fan        used to find out the present cursor co-ordinates. It will
3134*4a1a9510SRong-En Fan        fill the values of x and y co-ordinates in the arguments
3135*4a1a9510SRong-En Fan        given to it. Since getyx() is a macro you don't have to
3136*4a1a9510SRong-En Fan        pass the address of the variables. It can be called as</p>
3137*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
3138*4a1a9510SRong-En Fan    getyx(win, y, x);
3139*4a1a9510SRong-En Fan    /* win: window pointer
3140*4a1a9510SRong-En Fan     *   y, x: y, x co-ordinates will be put into this variables
3141*4a1a9510SRong-En Fan     */
3142*4a1a9510SRong-En Fan</pre>
3143*4a1a9510SRong-En Fan
3144*4a1a9510SRong-En Fan        <p>The function getparyx() gets the beginning co-ordinates
3145*4a1a9510SRong-En Fan        of the sub window relative to the main window. This is some
3146*4a1a9510SRong-En Fan        times useful to update a sub window. When designing fancy
3147*4a1a9510SRong-En Fan        stuff like writing multiple menus, it becomes difficult to
3148*4a1a9510SRong-En Fan        store the menu positions, their first option co-ordinates
3149*4a1a9510SRong-En Fan        etc. A simple solution to this problem, is to create menus
3150*4a1a9510SRong-En Fan        in sub windows and later find the starting co-ordinates of
3151*4a1a9510SRong-En Fan        the menus by using getparyx().</p>
3152*4a1a9510SRong-En Fan
3153*4a1a9510SRong-En Fan        <p>The functions getbegyx() and getmaxyx() store current
3154*4a1a9510SRong-En Fan        window's beginning and maximum co-ordinates. These
3155*4a1a9510SRong-En Fan        functions are useful in the same way as above in managing
3156*4a1a9510SRong-En Fan        the windows and sub windows effectively.</p>
3157*4a1a9510SRong-En Fan      </div>
3158*4a1a9510SRong-En Fan
3159*4a1a9510SRong-En Fan      <div class="SECT2">
3160*4a1a9510SRong-En Fan        <hr>
3161*4a1a9510SRong-En Fan
3162*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="SCREENDUMP" id=
3163*4a1a9510SRong-En Fan        "SCREENDUMP">13.2. Screen Dumping</a></h3>
3164*4a1a9510SRong-En Fan
3165*4a1a9510SRong-En Fan        <p>While writing games, some times it becomes necessary to
3166*4a1a9510SRong-En Fan        store the state of the screen and restore it back to the
3167*4a1a9510SRong-En Fan        same state. The function scr_dump() can be used to dump the
3168*4a1a9510SRong-En Fan        screen contents to a file given as an argument. Later it
3169*4a1a9510SRong-En Fan        can be restored by scr_restore function. These two simple
3170*4a1a9510SRong-En Fan        functions can be used effectively to maintain a fast moving
3171*4a1a9510SRong-En Fan        game with changing scenarios.</p>
3172*4a1a9510SRong-En Fan      </div>
3173*4a1a9510SRong-En Fan
3174*4a1a9510SRong-En Fan      <div class="SECT2">
3175*4a1a9510SRong-En Fan        <hr>
3176*4a1a9510SRong-En Fan
3177*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="WINDOWDUMP" id=
3178*4a1a9510SRong-En Fan        "WINDOWDUMP">13.3. Window Dumping</a></h3>
3179*4a1a9510SRong-En Fan
3180*4a1a9510SRong-En Fan        <p>To store and restore windows, the functions <tt class=
3181*4a1a9510SRong-En Fan        "LITERAL">putwin()</tt> and <tt class=
3182*4a1a9510SRong-En Fan        "LITERAL">getwin()</tt> can be used. <tt class=
3183*4a1a9510SRong-En Fan        "LITERAL">putwin()</tt> puts the present window state into
3184*4a1a9510SRong-En Fan        a file, which can be later restored by <tt class=
3185*4a1a9510SRong-En Fan        "LITERAL">getwin()</tt>.</p>
3186*4a1a9510SRong-En Fan
3187*4a1a9510SRong-En Fan        <p>The function <tt class="LITERAL">copywin()</tt> can be
3188*4a1a9510SRong-En Fan        used to copy a window completely onto another window. It
3189*4a1a9510SRong-En Fan        takes the source and destination windows as parameters and
3190*4a1a9510SRong-En Fan        according to the rectangle specified, it copies the
3191*4a1a9510SRong-En Fan        rectangular region from source to destination window. It's
3192*4a1a9510SRong-En Fan        last parameter specifies whether to overwrite or just
3193*4a1a9510SRong-En Fan        overlay the contents on to the destination window. If this
3194*4a1a9510SRong-En Fan        argument is true, then the copying is non-destructive.</p>
3195*4a1a9510SRong-En Fan      </div>
3196*4a1a9510SRong-En Fan    </div>
3197*4a1a9510SRong-En Fan
3198*4a1a9510SRong-En Fan    <div class="SECT1">
3199*4a1a9510SRong-En Fan      <hr>
3200*4a1a9510SRong-En Fan
3201*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="MISC" id="MISC">14. Miscellaneous
3202*4a1a9510SRong-En Fan      features</a></h2>
3203*4a1a9510SRong-En Fan
3204*4a1a9510SRong-En Fan      <p>Now you know enough features to write a good curses
3205*4a1a9510SRong-En Fan      program, with all bells and whistles. There are some
3206*4a1a9510SRong-En Fan      miscellaneous functions which are useful in various cases.
3207*4a1a9510SRong-En Fan      Let's go headlong into some of those.</p>
3208*4a1a9510SRong-En Fan
3209*4a1a9510SRong-En Fan      <div class="SECT2">
3210*4a1a9510SRong-En Fan        <hr>
3211*4a1a9510SRong-En Fan
3212*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="CURSSET" id="CURSSET">14.1.
3213*4a1a9510SRong-En Fan        curs_set()</a></h3>
3214*4a1a9510SRong-En Fan
3215*4a1a9510SRong-En Fan        <p>This function can be used to make the cursor invisible.
3216*4a1a9510SRong-En Fan        The parameter to this function should be</p>
3217*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
3218*4a1a9510SRong-En Fan    0 : invisible      or
3219*4a1a9510SRong-En Fan    1 : normal    or
3220*4a1a9510SRong-En Fan    2 : very visible.
3221*4a1a9510SRong-En Fan</pre>
3222*4a1a9510SRong-En Fan      </div>
3223*4a1a9510SRong-En Fan
3224*4a1a9510SRong-En Fan      <div class="SECT2">
3225*4a1a9510SRong-En Fan        <hr>
3226*4a1a9510SRong-En Fan
3227*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="TEMPLEAVE" id="TEMPLEAVE">14.2.
3228*4a1a9510SRong-En Fan        Temporarily Leaving Curses mode</a></h3>
3229*4a1a9510SRong-En Fan
3230*4a1a9510SRong-En Fan        <p>Some times you may want to get back to cooked mode
3231*4a1a9510SRong-En Fan        (normal line buffering mode) temporarily. In such a case
3232*4a1a9510SRong-En Fan        you will first need to save the tty modes with a call to
3233*4a1a9510SRong-En Fan        <tt class="LITERAL">def_prog_mode()</tt> and then call
3234*4a1a9510SRong-En Fan        <tt class="LITERAL">endwin()</tt> to end the curses mode.
3235*4a1a9510SRong-En Fan        This will leave you in the original tty mode. To get back
3236*4a1a9510SRong-En Fan        to curses once you are done, call <tt class=
3237*4a1a9510SRong-En Fan        "LITERAL">reset_prog_mode()</tt> . This function returns
3238*4a1a9510SRong-En Fan        the tty to the state stored by <tt class=
3239*4a1a9510SRong-En Fan        "LITERAL">def_prog_mode()</tt>. Then do refresh(), and you
3240*4a1a9510SRong-En Fan        are back to the curses mode. Here is an example showing the
3241*4a1a9510SRong-En Fan        sequence of things to be done.</p>
3242*4a1a9510SRong-En Fan
3243*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3244*4a1a9510SRong-En Fan          <a name="BTELE" id="BTELE"></a>
3245*4a1a9510SRong-En Fan
3246*4a1a9510SRong-En Fan          <p><b>Example 12. Temporarily Leaving Curses Mode</b></p>
3247*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
3248*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
3249*4a1a9510SRong-En Fan
3250*4a1a9510SRong-En Fanint main()
3251*4a1a9510SRong-En Fan{
3252*4a1a9510SRong-En Fan        initscr();                      /* Start curses mode              */
3253*4a1a9510SRong-En Fan        printw("Hello World !!!\n");    /* Print Hello World              */
3254*4a1a9510SRong-En Fan        refresh();                      /* Print it on to the real screen */
3255*4a1a9510SRong-En Fan        def_prog_mode();                /* Save the tty modes             */
3256*4a1a9510SRong-En Fan        endwin();                       /* End curses mode temporarily    */
3257*4a1a9510SRong-En Fan        system("/bin/sh");              /* Do whatever you like in cooked mode */
3258*4a1a9510SRong-En Fan        reset_prog_mode();              /* Return to the previous tty mode*/
3259*4a1a9510SRong-En Fan                                        /* stored by def_prog_mode()      */
3260*4a1a9510SRong-En Fan        refresh();                      /* Do refresh() to restore the    */
3261*4a1a9510SRong-En Fan                                        /* Screen contents                */
3262*4a1a9510SRong-En Fan        printw("Another String\n");     /* Back to curses use the full    */
3263*4a1a9510SRong-En Fan        refresh();                      /* capabilities of curses         */
3264*4a1a9510SRong-En Fan        endwin();                       /* End curses mode                */
3265*4a1a9510SRong-En Fan
3266*4a1a9510SRong-En Fan        return 0;
3267*4a1a9510SRong-En Fan}</span>
3268*4a1a9510SRong-En Fan</pre>
3269*4a1a9510SRong-En Fan        </div>
3270*4a1a9510SRong-En Fan      </div>
3271*4a1a9510SRong-En Fan
3272*4a1a9510SRong-En Fan      <div class="SECT2">
3273*4a1a9510SRong-En Fan        <hr>
3274*4a1a9510SRong-En Fan
3275*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="ACSVARS" id="ACSVARS">14.3. ACS_
3276*4a1a9510SRong-En Fan        variables</a></h3>
3277*4a1a9510SRong-En Fan
3278*4a1a9510SRong-En Fan        <p>If you have ever programmed in DOS, you know about those
3279*4a1a9510SRong-En Fan        nifty characters in extended character set. They are
3280*4a1a9510SRong-En Fan        printable only on some terminals. NCURSES functions like
3281*4a1a9510SRong-En Fan        <tt class="LITERAL">box()</tt> use these characters. All
3282*4a1a9510SRong-En Fan        these variables start with ACS meaning alternative
3283*4a1a9510SRong-En Fan        character set. You might have noticed me using these
3284*4a1a9510SRong-En Fan        characters in some of the programs above. Here's an example
3285*4a1a9510SRong-En Fan        showing all the characters.</p>
3286*4a1a9510SRong-En Fan
3287*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3288*4a1a9510SRong-En Fan          <a name="BACSVARS" id="BACSVARS"></a>
3289*4a1a9510SRong-En Fan
3290*4a1a9510SRong-En Fan          <p><b>Example 13. ACS Variables Example</b></p>
3291*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
3292*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;ncurses.h&gt;
3293*4a1a9510SRong-En Fan
3294*4a1a9510SRong-En Fanint main()
3295*4a1a9510SRong-En Fan{
3296*4a1a9510SRong-En Fan        initscr();
3297*4a1a9510SRong-En Fan
3298*4a1a9510SRong-En Fan        printw("Upper left corner           "); addch(ACS_ULCORNER); printw("\n");
3299*4a1a9510SRong-En Fan        printw("Lower left corner           "); addch(ACS_LLCORNER); printw("\n");
3300*4a1a9510SRong-En Fan        printw("Lower right corner          "); addch(ACS_LRCORNER); printw("\n");
3301*4a1a9510SRong-En Fan        printw("Tee pointing right          "); addch(ACS_LTEE); printw("\n");
3302*4a1a9510SRong-En Fan        printw("Tee pointing left           "); addch(ACS_RTEE); printw("\n");
3303*4a1a9510SRong-En Fan        printw("Tee pointing up             "); addch(ACS_BTEE); printw("\n");
3304*4a1a9510SRong-En Fan        printw("Tee pointing down           "); addch(ACS_TTEE); printw("\n");
3305*4a1a9510SRong-En Fan        printw("Horizontal line             "); addch(ACS_HLINE); printw("\n");
3306*4a1a9510SRong-En Fan        printw("Vertical line               "); addch(ACS_VLINE); printw("\n");
3307*4a1a9510SRong-En Fan        printw("Large Plus or cross over    "); addch(ACS_PLUS); printw("\n");
3308*4a1a9510SRong-En Fan        printw("Scan Line 1                 "); addch(ACS_S1); printw("\n");
3309*4a1a9510SRong-En Fan        printw("Scan Line 3                 "); addch(ACS_S3); printw("\n");
3310*4a1a9510SRong-En Fan        printw("Scan Line 7                 "); addch(ACS_S7); printw("\n");
3311*4a1a9510SRong-En Fan        printw("Scan Line 9                 "); addch(ACS_S9); printw("\n");
3312*4a1a9510SRong-En Fan        printw("Diamond                     "); addch(ACS_DIAMOND); printw("\n");
3313*4a1a9510SRong-En Fan        printw("Checker board (stipple)     "); addch(ACS_CKBOARD); printw("\n");
3314*4a1a9510SRong-En Fan        printw("Degree Symbol               "); addch(ACS_DEGREE); printw("\n");
3315*4a1a9510SRong-En Fan        printw("Plus/Minus Symbol           "); addch(ACS_PLMINUS); printw("\n");
3316*4a1a9510SRong-En Fan        printw("Bullet                      "); addch(ACS_BULLET); printw("\n");
3317*4a1a9510SRong-En Fan        printw("Arrow Pointing Left         "); addch(ACS_LARROW); printw("\n");
3318*4a1a9510SRong-En Fan        printw("Arrow Pointing Right        "); addch(ACS_RARROW); printw("\n");
3319*4a1a9510SRong-En Fan        printw("Arrow Pointing Down         "); addch(ACS_DARROW); printw("\n");
3320*4a1a9510SRong-En Fan        printw("Arrow Pointing Up           "); addch(ACS_UARROW); printw("\n");
3321*4a1a9510SRong-En Fan        printw("Board of squares            "); addch(ACS_BOARD); printw("\n");
3322*4a1a9510SRong-En Fan        printw("Lantern Symbol              "); addch(ACS_LANTERN); printw("\n");
3323*4a1a9510SRong-En Fan        printw("Solid Square Block          "); addch(ACS_BLOCK); printw("\n");
3324*4a1a9510SRong-En Fan        printw("Less/Equal sign             "); addch(ACS_LEQUAL); printw("\n");
3325*4a1a9510SRong-En Fan        printw("Greater/Equal sign          "); addch(ACS_GEQUAL); printw("\n");
3326*4a1a9510SRong-En Fan        printw("Pi                          "); addch(ACS_PI); printw("\n");
3327*4a1a9510SRong-En Fan        printw("Not equal                   "); addch(ACS_NEQUAL); printw("\n");
3328*4a1a9510SRong-En Fan        printw("UK pound sign               "); addch(ACS_STERLING); printw("\n");
3329*4a1a9510SRong-En Fan
3330*4a1a9510SRong-En Fan        refresh();
3331*4a1a9510SRong-En Fan        getch();
3332*4a1a9510SRong-En Fan        endwin();
3333*4a1a9510SRong-En Fan
3334*4a1a9510SRong-En Fan        return 0;
3335*4a1a9510SRong-En Fan}</span>
3336*4a1a9510SRong-En Fan</pre>
3337*4a1a9510SRong-En Fan        </div>
3338*4a1a9510SRong-En Fan      </div>
3339*4a1a9510SRong-En Fan    </div>
3340*4a1a9510SRong-En Fan
3341*4a1a9510SRong-En Fan    <div class="SECT1">
3342*4a1a9510SRong-En Fan      <hr>
3343*4a1a9510SRong-En Fan
3344*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="OTHERLIB" id="OTHERLIB">15. Other
3345*4a1a9510SRong-En Fan      libraries</a></h2>
3346*4a1a9510SRong-En Fan
3347*4a1a9510SRong-En Fan      <p>Apart from the curses library, there are few text mode
3348*4a1a9510SRong-En Fan      libraries, which provide more functionality and a lot of
3349*4a1a9510SRong-En Fan      features. The following sections explain three standard
3350*4a1a9510SRong-En Fan      libraries which are usually distributed along with
3351*4a1a9510SRong-En Fan      curses.</p>
3352*4a1a9510SRong-En Fan    </div>
3353*4a1a9510SRong-En Fan
3354*4a1a9510SRong-En Fan    <div class="SECT1">
3355*4a1a9510SRong-En Fan      <hr>
3356*4a1a9510SRong-En Fan
3357*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="PANELS" id="PANELS">16. Panel
3358*4a1a9510SRong-En Fan      Library</a></h2>
3359*4a1a9510SRong-En Fan
3360*4a1a9510SRong-En Fan      <p>Now that you are proficient in curses, you wanted to do
3361*4a1a9510SRong-En Fan      some thing big. You created a lot of overlapping windows to
3362*4a1a9510SRong-En Fan      give a professional windows-type look. Unfortunately, it soon
3363*4a1a9510SRong-En Fan      becomes difficult to manage these. The multiple refreshes,
3364*4a1a9510SRong-En Fan      updates plunge you into a nightmare. The overlapping windows
3365*4a1a9510SRong-En Fan      create blotches, whenever you forget to refresh the windows
3366*4a1a9510SRong-En Fan      in the proper order.</p>
3367*4a1a9510SRong-En Fan
3368*4a1a9510SRong-En Fan      <p>Don't despair. There's an elegant solution provided in
3369*4a1a9510SRong-En Fan      panels library. In the words of developers of ncurses</p>
3370*4a1a9510SRong-En Fan
3371*4a1a9510SRong-En Fan      <p><span class="emphasis"><i class="EMPHASIS">When your
3372*4a1a9510SRong-En Fan      interface design is such that windows may dive deeper into
3373*4a1a9510SRong-En Fan      the visibility stack or pop to the top at runtime, the
3374*4a1a9510SRong-En Fan      resulting book-keeping can be tedious and difficult to get
3375*4a1a9510SRong-En Fan      right. Hence the panels library.</i></span></p>
3376*4a1a9510SRong-En Fan
3377*4a1a9510SRong-En Fan      <p>If you have lot of overlapping windows, then panels
3378*4a1a9510SRong-En Fan      library is the way to go. It obviates the need of doing
3379*4a1a9510SRong-En Fan      series of wnoutrefresh(), doupdate() and relieves the burden
3380*4a1a9510SRong-En Fan      of doing it correctly(bottom up). The library maintains
3381*4a1a9510SRong-En Fan      information about the order of windows, their overlapping and
3382*4a1a9510SRong-En Fan      update the screen properly. So why wait? Let's take a close
3383*4a1a9510SRong-En Fan      peek into panels.</p>
3384*4a1a9510SRong-En Fan
3385*4a1a9510SRong-En Fan      <div class="SECT2">
3386*4a1a9510SRong-En Fan        <hr>
3387*4a1a9510SRong-En Fan
3388*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PANELBASICS" id=
3389*4a1a9510SRong-En Fan        "PANELBASICS">16.1. The Basics</a></h3>
3390*4a1a9510SRong-En Fan
3391*4a1a9510SRong-En Fan        <p>Panel object is a window that is implicitly treated as
3392*4a1a9510SRong-En Fan        part of a deck including all other panel objects. The deck
3393*4a1a9510SRong-En Fan        is treated as a stack with the top panel being completely
3394*4a1a9510SRong-En Fan        visible and the other panels may or may not be obscured
3395*4a1a9510SRong-En Fan        according to their positions. So the basic idea is to
3396*4a1a9510SRong-En Fan        create a stack of overlapping panels and use panels library
3397*4a1a9510SRong-En Fan        to display them correctly. There is a function similar to
3398*4a1a9510SRong-En Fan        refresh() which, when called , displays panels in the
3399*4a1a9510SRong-En Fan        correct order. Functions are provided to hide or show
3400*4a1a9510SRong-En Fan        panels, move panels, change its size etc.. The overlapping
3401*4a1a9510SRong-En Fan        problem is managed by the panels library during all the
3402*4a1a9510SRong-En Fan        calls to these functions.</p>
3403*4a1a9510SRong-En Fan
3404*4a1a9510SRong-En Fan        <p>The general flow of a panel program goes like this:</p>
3405*4a1a9510SRong-En Fan
3406*4a1a9510SRong-En Fan        <ol type="1">
3407*4a1a9510SRong-En Fan          <li>
3408*4a1a9510SRong-En Fan            <p>Create the windows (with newwin()) to be attached to
3409*4a1a9510SRong-En Fan            the panels.</p>
3410*4a1a9510SRong-En Fan          </li>
3411*4a1a9510SRong-En Fan
3412*4a1a9510SRong-En Fan          <li>
3413*4a1a9510SRong-En Fan            <p>Create panels with the chosen visibility order.
3414*4a1a9510SRong-En Fan            Stack them up according to the desired visibility. The
3415*4a1a9510SRong-En Fan            function new_panel() is used to created panels.</p>
3416*4a1a9510SRong-En Fan          </li>
3417*4a1a9510SRong-En Fan
3418*4a1a9510SRong-En Fan          <li>
3419*4a1a9510SRong-En Fan            <p>Call update_panels() to write the panels to the
3420*4a1a9510SRong-En Fan            virtual screen in correct visibility order. Do a
3421*4a1a9510SRong-En Fan            doupdate() to show it on the screen.</p>
3422*4a1a9510SRong-En Fan          </li>
3423*4a1a9510SRong-En Fan
3424*4a1a9510SRong-En Fan          <li>
3425*4a1a9510SRong-En Fan            <p>Mainpulate the panels with show_panel(),
3426*4a1a9510SRong-En Fan            hide_panel(), move_panel() etc. Make use of helper
3427*4a1a9510SRong-En Fan            functions like panel_hidden() and panel_window(). Make
3428*4a1a9510SRong-En Fan            use of user pointer to store custom data for a panel.
3429*4a1a9510SRong-En Fan            Use the functions set_panel_userptr() and
3430*4a1a9510SRong-En Fan            panel_userptr() to set and get the user pointer for a
3431*4a1a9510SRong-En Fan            panel.</p>
3432*4a1a9510SRong-En Fan          </li>
3433*4a1a9510SRong-En Fan
3434*4a1a9510SRong-En Fan          <li>
3435*4a1a9510SRong-En Fan            <p>When you are done with the panel use del_panel() to
3436*4a1a9510SRong-En Fan            delete the panel.</p>
3437*4a1a9510SRong-En Fan          </li>
3438*4a1a9510SRong-En Fan        </ol>
3439*4a1a9510SRong-En Fan
3440*4a1a9510SRong-En Fan        <p>Let's make the concepts clear, with some programs. The
3441*4a1a9510SRong-En Fan        following is a simple program which creates 3 overlapping
3442*4a1a9510SRong-En Fan        panels and shows them on the screen.</p>
3443*4a1a9510SRong-En Fan      </div>
3444*4a1a9510SRong-En Fan
3445*4a1a9510SRong-En Fan      <div class="SECT2">
3446*4a1a9510SRong-En Fan        <hr>
3447*4a1a9510SRong-En Fan
3448*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COMPILEPANELS" id=
3449*4a1a9510SRong-En Fan        "COMPILEPANELS">16.2. Compiling With the Panels
3450*4a1a9510SRong-En Fan        Library</a></h3>
3451*4a1a9510SRong-En Fan
3452*4a1a9510SRong-En Fan        <p>To use panels library functions, you have to include
3453*4a1a9510SRong-En Fan        panel.h and to link the program with panels library the
3454*4a1a9510SRong-En Fan        flag -lpanel should be added along with -lncurses in that
3455*4a1a9510SRong-En Fan        order.</p>
3456*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
3457*4a1a9510SRong-En Fan    #include &lt;panel.h&gt;
3458*4a1a9510SRong-En Fan    .
3459*4a1a9510SRong-En Fan    .
3460*4a1a9510SRong-En Fan    .
3461*4a1a9510SRong-En Fan
3462*4a1a9510SRong-En Fan    compile and link: gcc &lt;program file&gt; -lpanel -lncurses
3463*4a1a9510SRong-En Fan</pre>
3464*4a1a9510SRong-En Fan
3465*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3466*4a1a9510SRong-En Fan          <a name="PPASI" id="PPASI"></a>
3467*4a1a9510SRong-En Fan
3468*4a1a9510SRong-En Fan          <p><b>Example 14. Panel basics</b></p>
3469*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
3470*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3471*4a1a9510SRong-En Fan
3472*4a1a9510SRong-En Fanint main()
3473*4a1a9510SRong-En Fan{       WINDOW *my_wins[3];
3474*4a1a9510SRong-En Fan        PANEL  *my_panels[3];
3475*4a1a9510SRong-En Fan        int lines = 10, cols = 40, y = 2, x = 4, i;
3476*4a1a9510SRong-En Fan
3477*4a1a9510SRong-En Fan        initscr();
3478*4a1a9510SRong-En Fan        cbreak();
3479*4a1a9510SRong-En Fan        noecho();
3480*4a1a9510SRong-En Fan
3481*4a1a9510SRong-En Fan        /* Create windows for the panels */
3482*4a1a9510SRong-En Fan        my_wins[0] = newwin(lines, cols, y, x);
3483*4a1a9510SRong-En Fan        my_wins[1] = newwin(lines, cols, y + 1, x + 5);
3484*4a1a9510SRong-En Fan        my_wins[2] = newwin(lines, cols, y + 2, x + 10);
3485*4a1a9510SRong-En Fan
3486*4a1a9510SRong-En Fan        /*
3487*4a1a9510SRong-En Fan         * Create borders around the windows so that you can see the effect
3488*4a1a9510SRong-En Fan         * of panels
3489*4a1a9510SRong-En Fan         */
3490*4a1a9510SRong-En Fan        for(i = 0; i &lt; 3; ++i)
3491*4a1a9510SRong-En Fan                box(my_wins[i], 0, 0);
3492*4a1a9510SRong-En Fan
3493*4a1a9510SRong-En Fan        /* Attach a panel to each window */     /* Order is bottom up */
3494*4a1a9510SRong-En Fan        my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3495*4a1a9510SRong-En Fan        my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3496*4a1a9510SRong-En Fan        my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3497*4a1a9510SRong-En Fan
3498*4a1a9510SRong-En Fan        /* Update the stacking order. 2nd panel will be on top */
3499*4a1a9510SRong-En Fan        update_panels();
3500*4a1a9510SRong-En Fan
3501*4a1a9510SRong-En Fan        /* Show it on the screen */
3502*4a1a9510SRong-En Fan        doupdate();
3503*4a1a9510SRong-En Fan
3504*4a1a9510SRong-En Fan        getch();
3505*4a1a9510SRong-En Fan        endwin();
3506*4a1a9510SRong-En Fan}
3507*4a1a9510SRong-En Fan</span>
3508*4a1a9510SRong-En Fan</pre>
3509*4a1a9510SRong-En Fan        </div>
3510*4a1a9510SRong-En Fan
3511*4a1a9510SRong-En Fan        <p>As you can see, above program follows a simple flow as
3512*4a1a9510SRong-En Fan        explained. The windows are created with newwin() and then
3513*4a1a9510SRong-En Fan        they are attached to panels with new_panel(). As we attach
3514*4a1a9510SRong-En Fan        one panel after another, the stack of panels gets updated.
3515*4a1a9510SRong-En Fan        To put them on screen update_panels() and doupdate() are
3516*4a1a9510SRong-En Fan        called.</p>
3517*4a1a9510SRong-En Fan      </div>
3518*4a1a9510SRong-En Fan
3519*4a1a9510SRong-En Fan      <div class="SECT2">
3520*4a1a9510SRong-En Fan        <hr>
3521*4a1a9510SRong-En Fan
3522*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PANELBROWSING" id=
3523*4a1a9510SRong-En Fan        "PANELBROWSING">16.3. Panel Window Browsing</a></h3>
3524*4a1a9510SRong-En Fan
3525*4a1a9510SRong-En Fan        <p>A slightly complicated example is given below. This
3526*4a1a9510SRong-En Fan        program creates 3 windows which can be cycled through using
3527*4a1a9510SRong-En Fan        tab. Have a look at the code.</p>
3528*4a1a9510SRong-En Fan
3529*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3530*4a1a9510SRong-En Fan          <a name="PPABR" id="PPABR"></a>
3531*4a1a9510SRong-En Fan
3532*4a1a9510SRong-En Fan          <p><b>Example 15. Panel Window Browsing Example</b></p>
3533*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
3534*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3535*4a1a9510SRong-En Fan
3536*4a1a9510SRong-En Fan#define NLINES 10
3537*4a1a9510SRong-En Fan#define NCOLS 40
3538*4a1a9510SRong-En Fan
3539*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n);
3540*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color);
3541*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3542*4a1a9510SRong-En Fan
3543*4a1a9510SRong-En Fanint main()
3544*4a1a9510SRong-En Fan{       WINDOW *my_wins[3];
3545*4a1a9510SRong-En Fan        PANEL  *my_panels[3];
3546*4a1a9510SRong-En Fan        PANEL  *top;
3547*4a1a9510SRong-En Fan        int ch;
3548*4a1a9510SRong-En Fan
3549*4a1a9510SRong-En Fan        /* Initialize curses */
3550*4a1a9510SRong-En Fan        initscr();
3551*4a1a9510SRong-En Fan        start_color();
3552*4a1a9510SRong-En Fan        cbreak();
3553*4a1a9510SRong-En Fan        noecho();
3554*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
3555*4a1a9510SRong-En Fan
3556*4a1a9510SRong-En Fan        /* Initialize all the colors */
3557*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
3558*4a1a9510SRong-En Fan        init_pair(2, COLOR_GREEN, COLOR_BLACK);
3559*4a1a9510SRong-En Fan        init_pair(3, COLOR_BLUE, COLOR_BLACK);
3560*4a1a9510SRong-En Fan        init_pair(4, COLOR_CYAN, COLOR_BLACK);
3561*4a1a9510SRong-En Fan
3562*4a1a9510SRong-En Fan        init_wins(my_wins, 3);
3563*4a1a9510SRong-En Fan
3564*4a1a9510SRong-En Fan        /* Attach a panel to each window */     /* Order is bottom up */
3565*4a1a9510SRong-En Fan        my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3566*4a1a9510SRong-En Fan        my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3567*4a1a9510SRong-En Fan        my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3568*4a1a9510SRong-En Fan
3569*4a1a9510SRong-En Fan        /* Set up the user pointers to the next panel */
3570*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[0], my_panels[1]);
3571*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[1], my_panels[2]);
3572*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[2], my_panels[0]);
3573*4a1a9510SRong-En Fan
3574*4a1a9510SRong-En Fan        /* Update the stacking order. 2nd panel will be on top */
3575*4a1a9510SRong-En Fan        update_panels();
3576*4a1a9510SRong-En Fan
3577*4a1a9510SRong-En Fan        /* Show it on the screen */
3578*4a1a9510SRong-En Fan        attron(COLOR_PAIR(4));
3579*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3580*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(4));
3581*4a1a9510SRong-En Fan        doupdate();
3582*4a1a9510SRong-En Fan
3583*4a1a9510SRong-En Fan        top = my_panels[2];
3584*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
3585*4a1a9510SRong-En Fan        {       switch(ch)
3586*4a1a9510SRong-En Fan                {       case 9:
3587*4a1a9510SRong-En Fan                                top = (PANEL *)panel_userptr(top);
3588*4a1a9510SRong-En Fan                                top_panel(top);
3589*4a1a9510SRong-En Fan                                break;
3590*4a1a9510SRong-En Fan                }
3591*4a1a9510SRong-En Fan                update_panels();
3592*4a1a9510SRong-En Fan                doupdate();
3593*4a1a9510SRong-En Fan        }
3594*4a1a9510SRong-En Fan        endwin();
3595*4a1a9510SRong-En Fan        return 0;
3596*4a1a9510SRong-En Fan}
3597*4a1a9510SRong-En Fan
3598*4a1a9510SRong-En Fan/* Put all the windows */
3599*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n)
3600*4a1a9510SRong-En Fan{       int x, y, i;
3601*4a1a9510SRong-En Fan        char label[80];
3602*4a1a9510SRong-En Fan
3603*4a1a9510SRong-En Fan        y = 2;
3604*4a1a9510SRong-En Fan        x = 10;
3605*4a1a9510SRong-En Fan        for(i = 0; i &lt; n; ++i)
3606*4a1a9510SRong-En Fan        {       wins[i] = newwin(NLINES, NCOLS, y, x);
3607*4a1a9510SRong-En Fan                sprintf(label, "Window Number %d", i + 1);
3608*4a1a9510SRong-En Fan                win_show(wins[i], label, i + 1);
3609*4a1a9510SRong-En Fan                y += 3;
3610*4a1a9510SRong-En Fan                x += 7;
3611*4a1a9510SRong-En Fan        }
3612*4a1a9510SRong-En Fan}
3613*4a1a9510SRong-En Fan
3614*4a1a9510SRong-En Fan/* Show the window with a border and a label */
3615*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color)
3616*4a1a9510SRong-En Fan{       int startx, starty, height, width;
3617*4a1a9510SRong-En Fan
3618*4a1a9510SRong-En Fan        getbegyx(win, starty, startx);
3619*4a1a9510SRong-En Fan        getmaxyx(win, height, width);
3620*4a1a9510SRong-En Fan
3621*4a1a9510SRong-En Fan        box(win, 0, 0);
3622*4a1a9510SRong-En Fan        mvwaddch(win, 2, 0, ACS_LTEE);
3623*4a1a9510SRong-En Fan        mvwhline(win, 2, 1, ACS_HLINE, width - 2);
3624*4a1a9510SRong-En Fan        mvwaddch(win, 2, width - 1, ACS_RTEE);
3625*4a1a9510SRong-En Fan
3626*4a1a9510SRong-En Fan        print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3627*4a1a9510SRong-En Fan}
3628*4a1a9510SRong-En Fan
3629*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3630*4a1a9510SRong-En Fan{       int length, x, y;
3631*4a1a9510SRong-En Fan        float temp;
3632*4a1a9510SRong-En Fan
3633*4a1a9510SRong-En Fan        if(win == NULL)
3634*4a1a9510SRong-En Fan                win = stdscr;
3635*4a1a9510SRong-En Fan        getyx(win, y, x);
3636*4a1a9510SRong-En Fan        if(startx != 0)
3637*4a1a9510SRong-En Fan                x = startx;
3638*4a1a9510SRong-En Fan        if(starty != 0)
3639*4a1a9510SRong-En Fan                y = starty;
3640*4a1a9510SRong-En Fan        if(width == 0)
3641*4a1a9510SRong-En Fan                width = 80;
3642*4a1a9510SRong-En Fan
3643*4a1a9510SRong-En Fan        length = strlen(string);
3644*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
3645*4a1a9510SRong-En Fan        x = startx + (int)temp;
3646*4a1a9510SRong-En Fan        wattron(win, color);
3647*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
3648*4a1a9510SRong-En Fan        wattroff(win, color);
3649*4a1a9510SRong-En Fan        refresh();
3650*4a1a9510SRong-En Fan}</span>
3651*4a1a9510SRong-En Fan</pre>
3652*4a1a9510SRong-En Fan        </div>
3653*4a1a9510SRong-En Fan      </div>
3654*4a1a9510SRong-En Fan
3655*4a1a9510SRong-En Fan      <div class="SECT2">
3656*4a1a9510SRong-En Fan        <hr>
3657*4a1a9510SRong-En Fan
3658*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="USERPTRUSING" id=
3659*4a1a9510SRong-En Fan        "USERPTRUSING">16.4. Using User Pointers</a></h3>
3660*4a1a9510SRong-En Fan
3661*4a1a9510SRong-En Fan        <p>In the above example I used user pointers to find out
3662*4a1a9510SRong-En Fan        the next window in the cycle. We can attach custom
3663*4a1a9510SRong-En Fan        information to the panel by specifying a user pointer,
3664*4a1a9510SRong-En Fan        which can point to any information you want to store. In
3665*4a1a9510SRong-En Fan        this case I stored the pointer to the next panel in the
3666*4a1a9510SRong-En Fan        cycle. User pointer for a panel can be set with the
3667*4a1a9510SRong-En Fan        function <tt class="LITERAL">set_panel_userptr()</tt>. It
3668*4a1a9510SRong-En Fan        can be accessed using the function <tt class=
3669*4a1a9510SRong-En Fan        "LITERAL">panel_userptr()</tt> which will return the user
3670*4a1a9510SRong-En Fan        pointer for the panel given as argument. After finding the
3671*4a1a9510SRong-En Fan        next panel in the cycle It's brought to the top by the
3672*4a1a9510SRong-En Fan        function top_panel(). This function brings the panel given
3673*4a1a9510SRong-En Fan        as argument to the top of the panel stack.</p>
3674*4a1a9510SRong-En Fan      </div>
3675*4a1a9510SRong-En Fan
3676*4a1a9510SRong-En Fan      <div class="SECT2">
3677*4a1a9510SRong-En Fan        <hr>
3678*4a1a9510SRong-En Fan
3679*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PANELMOVERESIZE" id=
3680*4a1a9510SRong-En Fan        "PANELMOVERESIZE">16.5. Moving and Resizing Panels</a></h3>
3681*4a1a9510SRong-En Fan
3682*4a1a9510SRong-En Fan        <p>The function <tt class="LITERAL">move_panel()</tt> can
3683*4a1a9510SRong-En Fan        be used to move a panel to the desired location. It does
3684*4a1a9510SRong-En Fan        not change the position of the panel in the stack. Make
3685*4a1a9510SRong-En Fan        sure that you use move_panel() instead mvwin() on the
3686*4a1a9510SRong-En Fan        window associated with the panel.</p>
3687*4a1a9510SRong-En Fan
3688*4a1a9510SRong-En Fan        <p>Resizing a panel is slightly complex. There is no
3689*4a1a9510SRong-En Fan        straight forward function just to resize the window
3690*4a1a9510SRong-En Fan        associated with a panel. A solution to resize a panel is to
3691*4a1a9510SRong-En Fan        create a new window with the desired sizes, change the
3692*4a1a9510SRong-En Fan        window associated with the panel using replace_panel().
3693*4a1a9510SRong-En Fan        Don't forget to delete the old window. The window
3694*4a1a9510SRong-En Fan        associated with a panel can be found by using the function
3695*4a1a9510SRong-En Fan        panel_window().</p>
3696*4a1a9510SRong-En Fan
3697*4a1a9510SRong-En Fan        <p>The following program shows these concepts, in
3698*4a1a9510SRong-En Fan        supposedly simple program. You can cycle through the window
3699*4a1a9510SRong-En Fan        with &lt;TAB&gt; as usual. To resize or move the active
3700*4a1a9510SRong-En Fan        panel press 'r' for resize 'm' for moving. Then use arrow
3701*4a1a9510SRong-En Fan        keys to resize or move it to the desired way and press
3702*4a1a9510SRong-En Fan        enter to end your resizing or moving. This example makes
3703*4a1a9510SRong-En Fan        use of user data to get the required data to do the
3704*4a1a9510SRong-En Fan        operations.</p>
3705*4a1a9510SRong-En Fan
3706*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3707*4a1a9510SRong-En Fan          <a name="PPARE" id="PPARE"></a>
3708*4a1a9510SRong-En Fan
3709*4a1a9510SRong-En Fan          <p><b>Example 16. Panel Moving and Resizing
3710*4a1a9510SRong-En Fan          example</b></p>
3711*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
3712*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
3713*4a1a9510SRong-En Fan
3714*4a1a9510SRong-En Fantypedef struct _PANEL_DATA {
3715*4a1a9510SRong-En Fan        int x, y, w, h;
3716*4a1a9510SRong-En Fan        char label[80];
3717*4a1a9510SRong-En Fan        int label_color;
3718*4a1a9510SRong-En Fan        PANEL *next;
3719*4a1a9510SRong-En Fan}PANEL_DATA;
3720*4a1a9510SRong-En Fan
3721*4a1a9510SRong-En Fan#define NLINES 10
3722*4a1a9510SRong-En Fan#define NCOLS 40
3723*4a1a9510SRong-En Fan
3724*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n);
3725*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color);
3726*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
3727*4a1a9510SRong-En Fanvoid set_user_ptrs(PANEL **panels, int n);
3728*4a1a9510SRong-En Fan
3729*4a1a9510SRong-En Fanint main()
3730*4a1a9510SRong-En Fan{       WINDOW *my_wins[3];
3731*4a1a9510SRong-En Fan        PANEL  *my_panels[3];
3732*4a1a9510SRong-En Fan        PANEL_DATA  *top;
3733*4a1a9510SRong-En Fan        PANEL *stack_top;
3734*4a1a9510SRong-En Fan        WINDOW *temp_win, *old_win;
3735*4a1a9510SRong-En Fan        int ch;
3736*4a1a9510SRong-En Fan        int newx, newy, neww, newh;
3737*4a1a9510SRong-En Fan        int size = FALSE, move = FALSE;
3738*4a1a9510SRong-En Fan
3739*4a1a9510SRong-En Fan        /* Initialize curses */
3740*4a1a9510SRong-En Fan        initscr();
3741*4a1a9510SRong-En Fan        start_color();
3742*4a1a9510SRong-En Fan        cbreak();
3743*4a1a9510SRong-En Fan        noecho();
3744*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
3745*4a1a9510SRong-En Fan
3746*4a1a9510SRong-En Fan        /* Initialize all the colors */
3747*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
3748*4a1a9510SRong-En Fan        init_pair(2, COLOR_GREEN, COLOR_BLACK);
3749*4a1a9510SRong-En Fan        init_pair(3, COLOR_BLUE, COLOR_BLACK);
3750*4a1a9510SRong-En Fan        init_pair(4, COLOR_CYAN, COLOR_BLACK);
3751*4a1a9510SRong-En Fan
3752*4a1a9510SRong-En Fan        init_wins(my_wins, 3);
3753*4a1a9510SRong-En Fan
3754*4a1a9510SRong-En Fan        /* Attach a panel to each window */     /* Order is bottom up */
3755*4a1a9510SRong-En Fan        my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
3756*4a1a9510SRong-En Fan        my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
3757*4a1a9510SRong-En Fan        my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
3758*4a1a9510SRong-En Fan
3759*4a1a9510SRong-En Fan        set_user_ptrs(my_panels, 3);
3760*4a1a9510SRong-En Fan        /* Update the stacking order. 2nd panel will be on top */
3761*4a1a9510SRong-En Fan        update_panels();
3762*4a1a9510SRong-En Fan
3763*4a1a9510SRong-En Fan        /* Show it on the screen */
3764*4a1a9510SRong-En Fan        attron(COLOR_PAIR(4));
3765*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3766*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3767*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(4));
3768*4a1a9510SRong-En Fan        doupdate();
3769*4a1a9510SRong-En Fan
3770*4a1a9510SRong-En Fan        stack_top = my_panels[2];
3771*4a1a9510SRong-En Fan        top = (PANEL_DATA *)panel_userptr(stack_top);
3772*4a1a9510SRong-En Fan        newx = top-&gt;x;
3773*4a1a9510SRong-En Fan        newy = top-&gt;y;
3774*4a1a9510SRong-En Fan        neww = top-&gt;w;
3775*4a1a9510SRong-En Fan        newh = top-&gt;h;
3776*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
3777*4a1a9510SRong-En Fan        {       switch(ch)
3778*4a1a9510SRong-En Fan                {       case 9:         /* Tab */
3779*4a1a9510SRong-En Fan                                top = (PANEL_DATA *)panel_userptr(stack_top);
3780*4a1a9510SRong-En Fan                                top_panel(top-&gt;next);
3781*4a1a9510SRong-En Fan                                stack_top = top-&gt;next;
3782*4a1a9510SRong-En Fan                                top = (PANEL_DATA *)panel_userptr(stack_top);
3783*4a1a9510SRong-En Fan                                newx = top-&gt;x;
3784*4a1a9510SRong-En Fan                                newy = top-&gt;y;
3785*4a1a9510SRong-En Fan                                neww = top-&gt;w;
3786*4a1a9510SRong-En Fan                                newh = top-&gt;h;
3787*4a1a9510SRong-En Fan                                break;
3788*4a1a9510SRong-En Fan                        case 'r':       /* Re-Size*/
3789*4a1a9510SRong-En Fan                                size = TRUE;
3790*4a1a9510SRong-En Fan                                attron(COLOR_PAIR(4));
3791*4a1a9510SRong-En Fan                                mvprintw(LINES - 4, 0, "Entered Resizing :Use Arrow Keys to resize and press &lt;ENTER&gt; to end resizing");
3792*4a1a9510SRong-En Fan                                refresh();
3793*4a1a9510SRong-En Fan                                attroff(COLOR_PAIR(4));
3794*4a1a9510SRong-En Fan                                break;
3795*4a1a9510SRong-En Fan                        case 'm':       /* Move */
3796*4a1a9510SRong-En Fan                                attron(COLOR_PAIR(4));
3797*4a1a9510SRong-En Fan                                mvprintw(LINES - 4, 0, "Entered Moving: Use Arrow Keys to Move and press &lt;ENTER&gt; to end moving");
3798*4a1a9510SRong-En Fan                                refresh();
3799*4a1a9510SRong-En Fan                                attroff(COLOR_PAIR(4));
3800*4a1a9510SRong-En Fan                                move = TRUE;
3801*4a1a9510SRong-En Fan                                break;
3802*4a1a9510SRong-En Fan                        case KEY_LEFT:
3803*4a1a9510SRong-En Fan                                if(size == TRUE)
3804*4a1a9510SRong-En Fan                                {       --newx;
3805*4a1a9510SRong-En Fan                                        ++neww;
3806*4a1a9510SRong-En Fan                                }
3807*4a1a9510SRong-En Fan                                if(move == TRUE)
3808*4a1a9510SRong-En Fan                                        --newx;
3809*4a1a9510SRong-En Fan                                break;
3810*4a1a9510SRong-En Fan                        case KEY_RIGHT:
3811*4a1a9510SRong-En Fan                                if(size == TRUE)
3812*4a1a9510SRong-En Fan                                {       ++newx;
3813*4a1a9510SRong-En Fan                                        --neww;
3814*4a1a9510SRong-En Fan                                }
3815*4a1a9510SRong-En Fan                                if(move == TRUE)
3816*4a1a9510SRong-En Fan                                        ++newx;
3817*4a1a9510SRong-En Fan                                break;
3818*4a1a9510SRong-En Fan                        case KEY_UP:
3819*4a1a9510SRong-En Fan                                if(size == TRUE)
3820*4a1a9510SRong-En Fan                                {       --newy;
3821*4a1a9510SRong-En Fan                                        ++newh;
3822*4a1a9510SRong-En Fan                                }
3823*4a1a9510SRong-En Fan                                if(move == TRUE)
3824*4a1a9510SRong-En Fan                                        --newy;
3825*4a1a9510SRong-En Fan                                break;
3826*4a1a9510SRong-En Fan                        case KEY_DOWN:
3827*4a1a9510SRong-En Fan                                if(size == TRUE)
3828*4a1a9510SRong-En Fan                                {       ++newy;
3829*4a1a9510SRong-En Fan                                        --newh;
3830*4a1a9510SRong-En Fan                                }
3831*4a1a9510SRong-En Fan                                if(move == TRUE)
3832*4a1a9510SRong-En Fan                                        ++newy;
3833*4a1a9510SRong-En Fan                                break;
3834*4a1a9510SRong-En Fan                        case 10:        /* Enter */
3835*4a1a9510SRong-En Fan                                move(LINES - 4, 0);
3836*4a1a9510SRong-En Fan                                clrtoeol();
3837*4a1a9510SRong-En Fan                                refresh();
3838*4a1a9510SRong-En Fan                                if(size == TRUE)
3839*4a1a9510SRong-En Fan                                {       old_win = panel_window(stack_top);
3840*4a1a9510SRong-En Fan                                        temp_win = newwin(newh, neww, newy, newx);
3841*4a1a9510SRong-En Fan                                        replace_panel(stack_top, temp_win);
3842*4a1a9510SRong-En Fan                                        win_show(temp_win, top-&gt;label, top-&gt;label_color);
3843*4a1a9510SRong-En Fan                                        delwin(old_win);
3844*4a1a9510SRong-En Fan                                        size = FALSE;
3845*4a1a9510SRong-En Fan                                }
3846*4a1a9510SRong-En Fan                                if(move == TRUE)
3847*4a1a9510SRong-En Fan                                {       move_panel(stack_top, newy, newx);
3848*4a1a9510SRong-En Fan                                        move = FALSE;
3849*4a1a9510SRong-En Fan                                }
3850*4a1a9510SRong-En Fan                                break;
3851*4a1a9510SRong-En Fan
3852*4a1a9510SRong-En Fan                }
3853*4a1a9510SRong-En Fan                attron(COLOR_PAIR(4));
3854*4a1a9510SRong-En Fan                mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing");
3855*4a1a9510SRong-En Fan                mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
3856*4a1a9510SRong-En Fan                attroff(COLOR_PAIR(4));
3857*4a1a9510SRong-En Fan                refresh();
3858*4a1a9510SRong-En Fan                update_panels();
3859*4a1a9510SRong-En Fan                doupdate();
3860*4a1a9510SRong-En Fan        }
3861*4a1a9510SRong-En Fan        endwin();
3862*4a1a9510SRong-En Fan        return 0;
3863*4a1a9510SRong-En Fan}
3864*4a1a9510SRong-En Fan
3865*4a1a9510SRong-En Fan/* Put all the windows */
3866*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n)
3867*4a1a9510SRong-En Fan{       int x, y, i;
3868*4a1a9510SRong-En Fan        char label[80];
3869*4a1a9510SRong-En Fan
3870*4a1a9510SRong-En Fan        y = 2;
3871*4a1a9510SRong-En Fan        x = 10;
3872*4a1a9510SRong-En Fan        for(i = 0; i &lt; n; ++i)
3873*4a1a9510SRong-En Fan        {       wins[i] = newwin(NLINES, NCOLS, y, x);
3874*4a1a9510SRong-En Fan                sprintf(label, "Window Number %d", i + 1);
3875*4a1a9510SRong-En Fan                win_show(wins[i], label, i + 1);
3876*4a1a9510SRong-En Fan                y += 3;
3877*4a1a9510SRong-En Fan                x += 7;
3878*4a1a9510SRong-En Fan        }
3879*4a1a9510SRong-En Fan}
3880*4a1a9510SRong-En Fan
3881*4a1a9510SRong-En Fan/* Set the PANEL_DATA structures for individual panels */
3882*4a1a9510SRong-En Fanvoid set_user_ptrs(PANEL **panels, int n)
3883*4a1a9510SRong-En Fan{       PANEL_DATA *ptrs;
3884*4a1a9510SRong-En Fan        WINDOW *win;
3885*4a1a9510SRong-En Fan        int x, y, w, h, i;
3886*4a1a9510SRong-En Fan        char temp[80];
3887*4a1a9510SRong-En Fan
3888*4a1a9510SRong-En Fan        ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA));
3889*4a1a9510SRong-En Fan
3890*4a1a9510SRong-En Fan        for(i = 0;i &lt; n; ++i)
3891*4a1a9510SRong-En Fan        {       win = panel_window(panels[i]);
3892*4a1a9510SRong-En Fan                getbegyx(win, y, x);
3893*4a1a9510SRong-En Fan                getmaxyx(win, h, w);
3894*4a1a9510SRong-En Fan                ptrs[i].x = x;
3895*4a1a9510SRong-En Fan                ptrs[i].y = y;
3896*4a1a9510SRong-En Fan                ptrs[i].w = w;
3897*4a1a9510SRong-En Fan                ptrs[i].h = h;
3898*4a1a9510SRong-En Fan                sprintf(temp, "Window Number %d", i + 1);
3899*4a1a9510SRong-En Fan                strcpy(ptrs[i].label, temp);
3900*4a1a9510SRong-En Fan                ptrs[i].label_color = i + 1;
3901*4a1a9510SRong-En Fan                if(i + 1 == n)
3902*4a1a9510SRong-En Fan                        ptrs[i].next = panels[0];
3903*4a1a9510SRong-En Fan                else
3904*4a1a9510SRong-En Fan                        ptrs[i].next = panels[i + 1];
3905*4a1a9510SRong-En Fan                set_panel_userptr(panels[i], &amp;ptrs[i]);
3906*4a1a9510SRong-En Fan        }
3907*4a1a9510SRong-En Fan}
3908*4a1a9510SRong-En Fan
3909*4a1a9510SRong-En Fan/* Show the window with a border and a label */
3910*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color)
3911*4a1a9510SRong-En Fan{       int startx, starty, height, width;
3912*4a1a9510SRong-En Fan
3913*4a1a9510SRong-En Fan        getbegyx(win, starty, startx);
3914*4a1a9510SRong-En Fan        getmaxyx(win, height, width);
3915*4a1a9510SRong-En Fan
3916*4a1a9510SRong-En Fan        box(win, 0, 0);
3917*4a1a9510SRong-En Fan        mvwaddch(win, 2, 0, ACS_LTEE);
3918*4a1a9510SRong-En Fan        mvwhline(win, 2, 1, ACS_HLINE, width - 2);
3919*4a1a9510SRong-En Fan        mvwaddch(win, 2, width - 1, ACS_RTEE);
3920*4a1a9510SRong-En Fan
3921*4a1a9510SRong-En Fan        print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
3922*4a1a9510SRong-En Fan}
3923*4a1a9510SRong-En Fan
3924*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
3925*4a1a9510SRong-En Fan{       int length, x, y;
3926*4a1a9510SRong-En Fan        float temp;
3927*4a1a9510SRong-En Fan
3928*4a1a9510SRong-En Fan        if(win == NULL)
3929*4a1a9510SRong-En Fan                win = stdscr;
3930*4a1a9510SRong-En Fan        getyx(win, y, x);
3931*4a1a9510SRong-En Fan        if(startx != 0)
3932*4a1a9510SRong-En Fan                x = startx;
3933*4a1a9510SRong-En Fan        if(starty != 0)
3934*4a1a9510SRong-En Fan                y = starty;
3935*4a1a9510SRong-En Fan        if(width == 0)
3936*4a1a9510SRong-En Fan                width = 80;
3937*4a1a9510SRong-En Fan
3938*4a1a9510SRong-En Fan        length = strlen(string);
3939*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
3940*4a1a9510SRong-En Fan        x = startx + (int)temp;
3941*4a1a9510SRong-En Fan        wattron(win, color);
3942*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
3943*4a1a9510SRong-En Fan        wattroff(win, color);
3944*4a1a9510SRong-En Fan        refresh();
3945*4a1a9510SRong-En Fan}</span>
3946*4a1a9510SRong-En Fan</pre>
3947*4a1a9510SRong-En Fan        </div>
3948*4a1a9510SRong-En Fan
3949*4a1a9510SRong-En Fan        <p>Concentrate on the main while loop. Once it finds out
3950*4a1a9510SRong-En Fan        the type of key pressed, it takes appropriate action. If
3951*4a1a9510SRong-En Fan        'r' is pressed resizing mode is started. After this the new
3952*4a1a9510SRong-En Fan        sizes are updated as the user presses the arrow keys. When
3953*4a1a9510SRong-En Fan        the user presses &lt;ENTER&gt; present selection ends and
3954*4a1a9510SRong-En Fan        panel is resized by using the concept explained. While in
3955*4a1a9510SRong-En Fan        resizing mode the program doesn't show how the window is
3956*4a1a9510SRong-En Fan        getting resized. It's left as an exercise to the reader to
3957*4a1a9510SRong-En Fan        print a dotted border while it gets resized to a new
3958*4a1a9510SRong-En Fan        position.</p>
3959*4a1a9510SRong-En Fan
3960*4a1a9510SRong-En Fan        <p>When the user presses 'm' the move mode starts. This is
3961*4a1a9510SRong-En Fan        a bit simpler than resizing. As the arrow keys are pressed
3962*4a1a9510SRong-En Fan        the new position is updated and pressing of &lt;ENTER&gt;
3963*4a1a9510SRong-En Fan        causes the panel to be moved by calling the function
3964*4a1a9510SRong-En Fan        move_panel().</p>
3965*4a1a9510SRong-En Fan
3966*4a1a9510SRong-En Fan        <p>In this program the user data which is represented as
3967*4a1a9510SRong-En Fan        PANEL_DATA, plays very important role in finding the
3968*4a1a9510SRong-En Fan        associated information with a panel. As written in the
3969*4a1a9510SRong-En Fan        comments, the PANEL_DATA stores the panel sizes, label,
3970*4a1a9510SRong-En Fan        label color and a pointer to the next panel in the
3971*4a1a9510SRong-En Fan        cycle.</p>
3972*4a1a9510SRong-En Fan      </div>
3973*4a1a9510SRong-En Fan
3974*4a1a9510SRong-En Fan      <div class="SECT2">
3975*4a1a9510SRong-En Fan        <hr>
3976*4a1a9510SRong-En Fan
3977*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PANELSHOWHIDE" id=
3978*4a1a9510SRong-En Fan        "PANELSHOWHIDE">16.6. Hiding and Showing Panels</a></h3>
3979*4a1a9510SRong-En Fan
3980*4a1a9510SRong-En Fan        <p>A Panel can be hidden by using the function
3981*4a1a9510SRong-En Fan        hide_panel(). This function merely removes it form the
3982*4a1a9510SRong-En Fan        stack of panels, thus hiding it on the screen once you do
3983*4a1a9510SRong-En Fan        update_panels() and doupdate(). It doesn't destroy the
3984*4a1a9510SRong-En Fan        PANEL structure associated with the hidden panel. It can be
3985*4a1a9510SRong-En Fan        shown again by using the show_panel() function.</p>
3986*4a1a9510SRong-En Fan
3987*4a1a9510SRong-En Fan        <p>The following program shows the hiding of panels. Press
3988*4a1a9510SRong-En Fan        'a' or 'b' or 'c' to show or hide first, second and third
3989*4a1a9510SRong-En Fan        windows respectively. It uses a user data with a small
3990*4a1a9510SRong-En Fan        variable hide, which keeps track of whether the window is
3991*4a1a9510SRong-En Fan        hidden or not. For some reason the function <tt class=
3992*4a1a9510SRong-En Fan        "LITERAL">panel_hidden()</tt> which tells whether a panel
3993*4a1a9510SRong-En Fan        is hidden or not is not working. A bug report was also
3994*4a1a9510SRong-En Fan        presented by Michael Andres <a href=
3995*4a1a9510SRong-En Fan        "http://www.geocrawler.com/archives/3/344/1999/9/0/2643549/"
3996*4a1a9510SRong-En Fan        target="_top">here</a></p>
3997*4a1a9510SRong-En Fan
3998*4a1a9510SRong-En Fan        <div class="EXAMPLE">
3999*4a1a9510SRong-En Fan          <a name="PPAHI" id="PPAHI"></a>
4000*4a1a9510SRong-En Fan
4001*4a1a9510SRong-En Fan          <p><b>Example 17. Panel Hiding and Showing
4002*4a1a9510SRong-En Fan          example</b></p>
4003*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4004*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;panel.h&gt;
4005*4a1a9510SRong-En Fan
4006*4a1a9510SRong-En Fantypedef struct _PANEL_DATA {
4007*4a1a9510SRong-En Fan        int hide;       /* TRUE if panel is hidden */
4008*4a1a9510SRong-En Fan}PANEL_DATA;
4009*4a1a9510SRong-En Fan
4010*4a1a9510SRong-En Fan#define NLINES 10
4011*4a1a9510SRong-En Fan#define NCOLS 40
4012*4a1a9510SRong-En Fan
4013*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n);
4014*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color);
4015*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4016*4a1a9510SRong-En Fan
4017*4a1a9510SRong-En Fanint main()
4018*4a1a9510SRong-En Fan{       WINDOW *my_wins[3];
4019*4a1a9510SRong-En Fan        PANEL  *my_panels[3];
4020*4a1a9510SRong-En Fan        PANEL_DATA panel_datas[3];
4021*4a1a9510SRong-En Fan        PANEL_DATA *temp;
4022*4a1a9510SRong-En Fan        int ch;
4023*4a1a9510SRong-En Fan
4024*4a1a9510SRong-En Fan        /* Initialize curses */
4025*4a1a9510SRong-En Fan        initscr();
4026*4a1a9510SRong-En Fan        start_color();
4027*4a1a9510SRong-En Fan        cbreak();
4028*4a1a9510SRong-En Fan        noecho();
4029*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
4030*4a1a9510SRong-En Fan
4031*4a1a9510SRong-En Fan        /* Initialize all the colors */
4032*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
4033*4a1a9510SRong-En Fan        init_pair(2, COLOR_GREEN, COLOR_BLACK);
4034*4a1a9510SRong-En Fan        init_pair(3, COLOR_BLUE, COLOR_BLACK);
4035*4a1a9510SRong-En Fan        init_pair(4, COLOR_CYAN, COLOR_BLACK);
4036*4a1a9510SRong-En Fan
4037*4a1a9510SRong-En Fan        init_wins(my_wins, 3);
4038*4a1a9510SRong-En Fan
4039*4a1a9510SRong-En Fan        /* Attach a panel to each window */     /* Order is bottom up */
4040*4a1a9510SRong-En Fan        my_panels[0] = new_panel(my_wins[0]);   /* Push 0, order: stdscr-0 */
4041*4a1a9510SRong-En Fan        my_panels[1] = new_panel(my_wins[1]);   /* Push 1, order: stdscr-0-1 */
4042*4a1a9510SRong-En Fan        my_panels[2] = new_panel(my_wins[2]);   /* Push 2, order: stdscr-0-1-2 */
4043*4a1a9510SRong-En Fan
4044*4a1a9510SRong-En Fan        /* Initialize panel datas saying that nothing is hidden */
4045*4a1a9510SRong-En Fan        panel_datas[0].hide = FALSE;
4046*4a1a9510SRong-En Fan        panel_datas[1].hide = FALSE;
4047*4a1a9510SRong-En Fan        panel_datas[2].hide = FALSE;
4048*4a1a9510SRong-En Fan
4049*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[0], &amp;panel_datas[0]);
4050*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[1], &amp;panel_datas[1]);
4051*4a1a9510SRong-En Fan        set_panel_userptr(my_panels[2], &amp;panel_datas[2]);
4052*4a1a9510SRong-En Fan
4053*4a1a9510SRong-En Fan        /* Update the stacking order. 2nd panel will be on top */
4054*4a1a9510SRong-En Fan        update_panels();
4055*4a1a9510SRong-En Fan
4056*4a1a9510SRong-En Fan        /* Show it on the screen */
4057*4a1a9510SRong-En Fan        attron(COLOR_PAIR(4));
4058*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Show or Hide a window with 'a'(first window)  'b'(Second Window)  'c'(Third Window)");
4059*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "F1 to Exit");
4060*4a1a9510SRong-En Fan
4061*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(4));
4062*4a1a9510SRong-En Fan        doupdate();
4063*4a1a9510SRong-En Fan
4064*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
4065*4a1a9510SRong-En Fan        {       switch(ch)
4066*4a1a9510SRong-En Fan                {       case 'a':
4067*4a1a9510SRong-En Fan                                temp = (PANEL_DATA *)panel_userptr(my_panels[0]);
4068*4a1a9510SRong-En Fan                                if(temp-&gt;hide == FALSE)
4069*4a1a9510SRong-En Fan                                {       hide_panel(my_panels[0]);
4070*4a1a9510SRong-En Fan                                        temp-&gt;hide = TRUE;
4071*4a1a9510SRong-En Fan                                }
4072*4a1a9510SRong-En Fan                                else
4073*4a1a9510SRong-En Fan                                {       show_panel(my_panels[0]);
4074*4a1a9510SRong-En Fan                                        temp-&gt;hide = FALSE;
4075*4a1a9510SRong-En Fan                                }
4076*4a1a9510SRong-En Fan                                break;
4077*4a1a9510SRong-En Fan                        case 'b':
4078*4a1a9510SRong-En Fan                                temp = (PANEL_DATA *)panel_userptr(my_panels[1]);
4079*4a1a9510SRong-En Fan                                if(temp-&gt;hide == FALSE)
4080*4a1a9510SRong-En Fan                                {       hide_panel(my_panels[1]);
4081*4a1a9510SRong-En Fan                                        temp-&gt;hide = TRUE;
4082*4a1a9510SRong-En Fan                                }
4083*4a1a9510SRong-En Fan                                else
4084*4a1a9510SRong-En Fan                                {       show_panel(my_panels[1]);
4085*4a1a9510SRong-En Fan                                        temp-&gt;hide = FALSE;
4086*4a1a9510SRong-En Fan                                }
4087*4a1a9510SRong-En Fan                                break;
4088*4a1a9510SRong-En Fan                        case 'c':
4089*4a1a9510SRong-En Fan                                temp = (PANEL_DATA *)panel_userptr(my_panels[2]);
4090*4a1a9510SRong-En Fan                                if(temp-&gt;hide == FALSE)
4091*4a1a9510SRong-En Fan                                {       hide_panel(my_panels[2]);
4092*4a1a9510SRong-En Fan                                        temp-&gt;hide = TRUE;
4093*4a1a9510SRong-En Fan                                }
4094*4a1a9510SRong-En Fan                                else
4095*4a1a9510SRong-En Fan                                {       show_panel(my_panels[2]);
4096*4a1a9510SRong-En Fan                                        temp-&gt;hide = FALSE;
4097*4a1a9510SRong-En Fan                                }
4098*4a1a9510SRong-En Fan                                break;
4099*4a1a9510SRong-En Fan                }
4100*4a1a9510SRong-En Fan                update_panels();
4101*4a1a9510SRong-En Fan                doupdate();
4102*4a1a9510SRong-En Fan        }
4103*4a1a9510SRong-En Fan        endwin();
4104*4a1a9510SRong-En Fan        return 0;
4105*4a1a9510SRong-En Fan}
4106*4a1a9510SRong-En Fan
4107*4a1a9510SRong-En Fan/* Put all the windows */
4108*4a1a9510SRong-En Fanvoid init_wins(WINDOW **wins, int n)
4109*4a1a9510SRong-En Fan{       int x, y, i;
4110*4a1a9510SRong-En Fan        char label[80];
4111*4a1a9510SRong-En Fan
4112*4a1a9510SRong-En Fan        y = 2;
4113*4a1a9510SRong-En Fan        x = 10;
4114*4a1a9510SRong-En Fan        for(i = 0; i &lt; n; ++i)
4115*4a1a9510SRong-En Fan        {       wins[i] = newwin(NLINES, NCOLS, y, x);
4116*4a1a9510SRong-En Fan                sprintf(label, "Window Number %d", i + 1);
4117*4a1a9510SRong-En Fan                win_show(wins[i], label, i + 1);
4118*4a1a9510SRong-En Fan                y += 3;
4119*4a1a9510SRong-En Fan                x += 7;
4120*4a1a9510SRong-En Fan        }
4121*4a1a9510SRong-En Fan}
4122*4a1a9510SRong-En Fan
4123*4a1a9510SRong-En Fan/* Show the window with a border and a label */
4124*4a1a9510SRong-En Fanvoid win_show(WINDOW *win, char *label, int label_color)
4125*4a1a9510SRong-En Fan{       int startx, starty, height, width;
4126*4a1a9510SRong-En Fan
4127*4a1a9510SRong-En Fan        getbegyx(win, starty, startx);
4128*4a1a9510SRong-En Fan        getmaxyx(win, height, width);
4129*4a1a9510SRong-En Fan
4130*4a1a9510SRong-En Fan        box(win, 0, 0);
4131*4a1a9510SRong-En Fan        mvwaddch(win, 2, 0, ACS_LTEE);
4132*4a1a9510SRong-En Fan        mvwhline(win, 2, 1, ACS_HLINE, width - 2);
4133*4a1a9510SRong-En Fan        mvwaddch(win, 2, width - 1, ACS_RTEE);
4134*4a1a9510SRong-En Fan
4135*4a1a9510SRong-En Fan        print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
4136*4a1a9510SRong-En Fan}
4137*4a1a9510SRong-En Fan
4138*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4139*4a1a9510SRong-En Fan{       int length, x, y;
4140*4a1a9510SRong-En Fan        float temp;
4141*4a1a9510SRong-En Fan
4142*4a1a9510SRong-En Fan        if(win == NULL)
4143*4a1a9510SRong-En Fan                win = stdscr;
4144*4a1a9510SRong-En Fan        getyx(win, y, x);
4145*4a1a9510SRong-En Fan        if(startx != 0)
4146*4a1a9510SRong-En Fan                x = startx;
4147*4a1a9510SRong-En Fan        if(starty != 0)
4148*4a1a9510SRong-En Fan                y = starty;
4149*4a1a9510SRong-En Fan        if(width == 0)
4150*4a1a9510SRong-En Fan                width = 80;
4151*4a1a9510SRong-En Fan
4152*4a1a9510SRong-En Fan        length = strlen(string);
4153*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
4154*4a1a9510SRong-En Fan        x = startx + (int)temp;
4155*4a1a9510SRong-En Fan        wattron(win, color);
4156*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
4157*4a1a9510SRong-En Fan        wattroff(win, color);
4158*4a1a9510SRong-En Fan        refresh();
4159*4a1a9510SRong-En Fan}</span>
4160*4a1a9510SRong-En Fan</pre>
4161*4a1a9510SRong-En Fan        </div>
4162*4a1a9510SRong-En Fan      </div>
4163*4a1a9510SRong-En Fan
4164*4a1a9510SRong-En Fan      <div class="SECT2">
4165*4a1a9510SRong-En Fan        <hr>
4166*4a1a9510SRong-En Fan
4167*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PANELABOVE" id=
4168*4a1a9510SRong-En Fan        "PANELABOVE">16.7. panel_above() and panel_below()
4169*4a1a9510SRong-En Fan        Functions</a></h3>
4170*4a1a9510SRong-En Fan
4171*4a1a9510SRong-En Fan        <p>The functions <tt class="LITERAL">panel_above()</tt> and
4172*4a1a9510SRong-En Fan        <tt class="LITERAL">panel_below()</tt> can be used to find
4173*4a1a9510SRong-En Fan        out the panel above and below a panel. If the argument to
4174*4a1a9510SRong-En Fan        these functions is NULL, then they return a pointer to
4175*4a1a9510SRong-En Fan        bottom panel and top panel respectively.</p>
4176*4a1a9510SRong-En Fan      </div>
4177*4a1a9510SRong-En Fan    </div>
4178*4a1a9510SRong-En Fan
4179*4a1a9510SRong-En Fan    <div class="SECT1">
4180*4a1a9510SRong-En Fan      <hr>
4181*4a1a9510SRong-En Fan
4182*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="MENUS" id="MENUS">17. Menus
4183*4a1a9510SRong-En Fan      Library</a></h2>
4184*4a1a9510SRong-En Fan
4185*4a1a9510SRong-En Fan      <p>The menus library provides a nice extension to basic
4186*4a1a9510SRong-En Fan      curses, through which you can create menus. It provides a set
4187*4a1a9510SRong-En Fan      of functions to create menus. But they have to be customized
4188*4a1a9510SRong-En Fan      to give a nicer look, with colors etc. Let's get into the
4189*4a1a9510SRong-En Fan      details.</p>
4190*4a1a9510SRong-En Fan
4191*4a1a9510SRong-En Fan      <p>A menu is a screen display that assists the user to choose
4192*4a1a9510SRong-En Fan      some subset of a given set of items. To put it simple, a menu
4193*4a1a9510SRong-En Fan      is a collection of items from which one or more items can be
4194*4a1a9510SRong-En Fan      chosen. Some readers might not be aware of multiple item
4195*4a1a9510SRong-En Fan      selection capability. Menu library provides functionality to
4196*4a1a9510SRong-En Fan      write menus from which the user can chose more than one item
4197*4a1a9510SRong-En Fan      as the preferred choice. This is dealt with in a later
4198*4a1a9510SRong-En Fan      section. Now it is time for some rudiments.</p>
4199*4a1a9510SRong-En Fan
4200*4a1a9510SRong-En Fan      <div class="SECT2">
4201*4a1a9510SRong-En Fan        <hr>
4202*4a1a9510SRong-En Fan
4203*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MENUBASICS" id=
4204*4a1a9510SRong-En Fan        "MENUBASICS">17.1. The Basics</a></h3>
4205*4a1a9510SRong-En Fan
4206*4a1a9510SRong-En Fan        <p>To create menus, you first create items, and then post
4207*4a1a9510SRong-En Fan        the menu to the display. After that, all the processing of
4208*4a1a9510SRong-En Fan        user responses is done in an elegant function menu_driver()
4209*4a1a9510SRong-En Fan        which is the work horse of any menu program.</p>
4210*4a1a9510SRong-En Fan
4211*4a1a9510SRong-En Fan        <p>The general flow of control of a menu program looks like
4212*4a1a9510SRong-En Fan        this.</p>
4213*4a1a9510SRong-En Fan
4214*4a1a9510SRong-En Fan        <ol type="1">
4215*4a1a9510SRong-En Fan          <li>
4216*4a1a9510SRong-En Fan            <p>Initialize curses</p>
4217*4a1a9510SRong-En Fan          </li>
4218*4a1a9510SRong-En Fan
4219*4a1a9510SRong-En Fan          <li>
4220*4a1a9510SRong-En Fan            <p>Create items using new_item(). You can specify a
4221*4a1a9510SRong-En Fan            name and description for the items.</p>
4222*4a1a9510SRong-En Fan          </li>
4223*4a1a9510SRong-En Fan
4224*4a1a9510SRong-En Fan          <li>
4225*4a1a9510SRong-En Fan            <p>Create the menu with new_menu() by specifying the
4226*4a1a9510SRong-En Fan            items to be attached with.</p>
4227*4a1a9510SRong-En Fan          </li>
4228*4a1a9510SRong-En Fan
4229*4a1a9510SRong-En Fan          <li>
4230*4a1a9510SRong-En Fan            <p>Post the menu with menu_post() and refresh the
4231*4a1a9510SRong-En Fan            screen.</p>
4232*4a1a9510SRong-En Fan          </li>
4233*4a1a9510SRong-En Fan
4234*4a1a9510SRong-En Fan          <li>
4235*4a1a9510SRong-En Fan            <p>Process the user requests with a loop and do
4236*4a1a9510SRong-En Fan            necessary updates to menu with menu_driver.</p>
4237*4a1a9510SRong-En Fan          </li>
4238*4a1a9510SRong-En Fan
4239*4a1a9510SRong-En Fan          <li>
4240*4a1a9510SRong-En Fan            <p>Unpost the menu with menu_unpost()</p>
4241*4a1a9510SRong-En Fan          </li>
4242*4a1a9510SRong-En Fan
4243*4a1a9510SRong-En Fan          <li>
4244*4a1a9510SRong-En Fan            <p>Free the memory allocated to menu by free_menu()</p>
4245*4a1a9510SRong-En Fan          </li>
4246*4a1a9510SRong-En Fan
4247*4a1a9510SRong-En Fan          <li>
4248*4a1a9510SRong-En Fan            <p>Free the memory allocated to the items with
4249*4a1a9510SRong-En Fan            free_item()</p>
4250*4a1a9510SRong-En Fan          </li>
4251*4a1a9510SRong-En Fan
4252*4a1a9510SRong-En Fan          <li>
4253*4a1a9510SRong-En Fan            <p>End curses</p>
4254*4a1a9510SRong-En Fan          </li>
4255*4a1a9510SRong-En Fan        </ol>
4256*4a1a9510SRong-En Fan
4257*4a1a9510SRong-En Fan        <p>Let's see a program which prints a simple menu and
4258*4a1a9510SRong-En Fan        updates the current selection with up, down arrows.</p>
4259*4a1a9510SRong-En Fan      </div>
4260*4a1a9510SRong-En Fan
4261*4a1a9510SRong-En Fan      <div class="SECT2">
4262*4a1a9510SRong-En Fan        <hr>
4263*4a1a9510SRong-En Fan
4264*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COMPILEMENUS" id=
4265*4a1a9510SRong-En Fan        "COMPILEMENUS">17.2. Compiling With the Menu
4266*4a1a9510SRong-En Fan        Library</a></h3>
4267*4a1a9510SRong-En Fan
4268*4a1a9510SRong-En Fan        <p>To use menu library functions, you have to include
4269*4a1a9510SRong-En Fan        menu.h and to link the program with menu library the flag
4270*4a1a9510SRong-En Fan        -lmenu should be added along with -lncurses in that
4271*4a1a9510SRong-En Fan        order.</p>
4272*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
4273*4a1a9510SRong-En Fan    #include &lt;menu.h&gt;
4274*4a1a9510SRong-En Fan    .
4275*4a1a9510SRong-En Fan    .
4276*4a1a9510SRong-En Fan    .
4277*4a1a9510SRong-En Fan
4278*4a1a9510SRong-En Fan    compile and link: gcc &lt;program file&gt; -lmenu -lncurses
4279*4a1a9510SRong-En Fan</pre>
4280*4a1a9510SRong-En Fan
4281*4a1a9510SRong-En Fan        <div class="EXAMPLE">
4282*4a1a9510SRong-En Fan          <a name="MMESI" id="MMESI"></a>
4283*4a1a9510SRong-En Fan
4284*4a1a9510SRong-En Fan          <p><b>Example 18. Menu Basics</b></p>
4285*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4286*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4287*4a1a9510SRong-En Fan#include &lt;menu.h&gt;
4288*4a1a9510SRong-En Fan
4289*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4290*4a1a9510SRong-En Fan#define CTRLD   4
4291*4a1a9510SRong-En Fan
4292*4a1a9510SRong-En Fanchar *choices[] = {
4293*4a1a9510SRong-En Fan                        "Choice 1",
4294*4a1a9510SRong-En Fan                        "Choice 2",
4295*4a1a9510SRong-En Fan                        "Choice 3",
4296*4a1a9510SRong-En Fan                        "Choice 4",
4297*4a1a9510SRong-En Fan                        "Exit",
4298*4a1a9510SRong-En Fan                  };
4299*4a1a9510SRong-En Fan
4300*4a1a9510SRong-En Fanint main()
4301*4a1a9510SRong-En Fan{       ITEM **my_items;
4302*4a1a9510SRong-En Fan        int c;
4303*4a1a9510SRong-En Fan        MENU *my_menu;
4304*4a1a9510SRong-En Fan        int n_choices, i;
4305*4a1a9510SRong-En Fan        ITEM *cur_item;
4306*4a1a9510SRong-En Fan
4307*4a1a9510SRong-En Fan
4308*4a1a9510SRong-En Fan        initscr();
4309*4a1a9510SRong-En Fan        cbreak();
4310*4a1a9510SRong-En Fan        noecho();
4311*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
4312*4a1a9510SRong-En Fan
4313*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
4314*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
4315*4a1a9510SRong-En Fan
4316*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4317*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
4318*4a1a9510SRong-En Fan        my_items[n_choices] = (ITEM *)NULL;
4319*4a1a9510SRong-En Fan
4320*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
4321*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "F1 to Exit");
4322*4a1a9510SRong-En Fan        post_menu(my_menu);
4323*4a1a9510SRong-En Fan        refresh();
4324*4a1a9510SRong-En Fan
4325*4a1a9510SRong-En Fan        while((c = getch()) != KEY_F(1))
4326*4a1a9510SRong-En Fan        {   switch(c)
4327*4a1a9510SRong-En Fan            {   case KEY_DOWN:
4328*4a1a9510SRong-En Fan                        menu_driver(my_menu, REQ_DOWN_ITEM);
4329*4a1a9510SRong-En Fan                                break;
4330*4a1a9510SRong-En Fan                        case KEY_UP:
4331*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
4332*4a1a9510SRong-En Fan                                break;
4333*4a1a9510SRong-En Fan                }
4334*4a1a9510SRong-En Fan        }
4335*4a1a9510SRong-En Fan
4336*4a1a9510SRong-En Fan        free_item(my_items[0]);
4337*4a1a9510SRong-En Fan        free_item(my_items[1]);
4338*4a1a9510SRong-En Fan        free_menu(my_menu);
4339*4a1a9510SRong-En Fan        endwin();
4340*4a1a9510SRong-En Fan}
4341*4a1a9510SRong-En Fan        </span>
4342*4a1a9510SRong-En Fan</pre>
4343*4a1a9510SRong-En Fan        </div>
4344*4a1a9510SRong-En Fan
4345*4a1a9510SRong-En Fan        <p>This program demonstrates the basic concepts involved in
4346*4a1a9510SRong-En Fan        creating a menu using menus library. First we create the
4347*4a1a9510SRong-En Fan        items using new_item() and then attach them to the menu
4348*4a1a9510SRong-En Fan        with new_menu() function. After posting the menu and
4349*4a1a9510SRong-En Fan        refreshing the screen, the main processing loop starts. It
4350*4a1a9510SRong-En Fan        reads user input and takes corresponding action. The
4351*4a1a9510SRong-En Fan        function menu_driver() is the main work horse of the menu
4352*4a1a9510SRong-En Fan        system. The second parameter to this function tells what's
4353*4a1a9510SRong-En Fan        to be done with the menu. According to the parameter,
4354*4a1a9510SRong-En Fan        menu_driver() does the corresponding task. The value can be
4355*4a1a9510SRong-En Fan        either a menu navigational request, an ascii character, or
4356*4a1a9510SRong-En Fan        a KEY_MOUSE special key associated with a mouse event.</p>
4357*4a1a9510SRong-En Fan
4358*4a1a9510SRong-En Fan        <p>The menu_driver accepts following navigational
4359*4a1a9510SRong-En Fan        requests.</p>
4360*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
4361*4a1a9510SRong-En Fan&#13;     REQ_LEFT_ITEM         Move left to an item.
4362*4a1a9510SRong-En Fan     REQ_RIGHT_ITEM      Move right to an item.
4363*4a1a9510SRong-En Fan     REQ_UP_ITEM         Move up to an item.
4364*4a1a9510SRong-En Fan     REQ_DOWN_ITEM       Move down to an item.
4365*4a1a9510SRong-En Fan     REQ_SCR_ULINE       Scroll up a line.
4366*4a1a9510SRong-En Fan     REQ_SCR_DLINE          Scroll down a line.
4367*4a1a9510SRong-En Fan     REQ_SCR_DPAGE          Scroll down a page.
4368*4a1a9510SRong-En Fan     REQ_SCR_UPAGE         Scroll up a page.
4369*4a1a9510SRong-En Fan     REQ_FIRST_ITEM     Move to the first item.
4370*4a1a9510SRong-En Fan     REQ_LAST_ITEM         Move to the last item.
4371*4a1a9510SRong-En Fan     REQ_NEXT_ITEM         Move to the next item.
4372*4a1a9510SRong-En Fan     REQ_PREV_ITEM         Move to the previous item.
4373*4a1a9510SRong-En Fan     REQ_TOGGLE_ITEM     Select/deselect an item.
4374*4a1a9510SRong-En Fan     REQ_CLEAR_PATTERN     Clear the menu pattern buffer.
4375*4a1a9510SRong-En Fan     REQ_BACK_PATTERN      Delete the previous character from the pattern buffer.
4376*4a1a9510SRong-En Fan     REQ_NEXT_MATCH     Move to the next item matching the pattern match.
4377*4a1a9510SRong-En Fan     REQ_PREV_MATCH     Move to the previous item matching the pattern match.&#13;
4378*4a1a9510SRong-En Fan</pre>
4379*4a1a9510SRong-En Fan
4380*4a1a9510SRong-En Fan        <p>Don't get overwhelmed by the number of options. We will
4381*4a1a9510SRong-En Fan        see them slowly one after another. The options of interest
4382*4a1a9510SRong-En Fan        in this example are REQ_UP_ITEM and REQ_DOWN_ITEM. These
4383*4a1a9510SRong-En Fan        two options when passed to menu_driver, menu driver updates
4384*4a1a9510SRong-En Fan        the current item to one item up or down respectively.</p>
4385*4a1a9510SRong-En Fan      </div>
4386*4a1a9510SRong-En Fan
4387*4a1a9510SRong-En Fan      <div class="SECT2">
4388*4a1a9510SRong-En Fan        <hr>
4389*4a1a9510SRong-En Fan
4390*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MENUDRIVER" id=
4391*4a1a9510SRong-En Fan        "MENUDRIVER">17.3. Menu Driver: The work horse of the menu
4392*4a1a9510SRong-En Fan        system</a></h3>
4393*4a1a9510SRong-En Fan
4394*4a1a9510SRong-En Fan        <p>As you have seen in the above example, menu_driver plays
4395*4a1a9510SRong-En Fan        an important role in updating the menu. It is very
4396*4a1a9510SRong-En Fan        important to understand various options it takes and what
4397*4a1a9510SRong-En Fan        they do. As explained above, the second parameter to
4398*4a1a9510SRong-En Fan        menu_driver() can be either a navigational request, a
4399*4a1a9510SRong-En Fan        printable character or a KEY_MOUSE key. Let's dissect the
4400*4a1a9510SRong-En Fan        different navigational requests.</p>
4401*4a1a9510SRong-En Fan
4402*4a1a9510SRong-En Fan        <ul>
4403*4a1a9510SRong-En Fan          <li>
4404*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class=
4405*4a1a9510SRong-En Fan            "EMPHASIS">REQ_LEFT_ITEM and
4406*4a1a9510SRong-En Fan            REQ_RIGHT_ITEM</i></span></p>
4407*4a1a9510SRong-En Fan
4408*4a1a9510SRong-En Fan            <p>A Menu can be displayed with multiple columns for
4409*4a1a9510SRong-En Fan            more than one item. This can be done by using the
4410*4a1a9510SRong-En Fan            <tt class="LITERAL">menu_format()</tt>function. When a
4411*4a1a9510SRong-En Fan            multi columnar menu is displayed these requests cause
4412*4a1a9510SRong-En Fan            the menu driver to move the current selection to left
4413*4a1a9510SRong-En Fan            or right.</p>
4414*4a1a9510SRong-En Fan          </li>
4415*4a1a9510SRong-En Fan
4416*4a1a9510SRong-En Fan          <li>
4417*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class=
4418*4a1a9510SRong-En Fan            "EMPHASIS">REQ_UP_ITEM and REQ_DOWN_ITEM</i></span></p>
4419*4a1a9510SRong-En Fan
4420*4a1a9510SRong-En Fan            <p>These two options you have seen in the above
4421*4a1a9510SRong-En Fan            example. These options when given, makes the
4422*4a1a9510SRong-En Fan            menu_driver to move the current selection to an item up
4423*4a1a9510SRong-En Fan            or down.</p>
4424*4a1a9510SRong-En Fan          </li>
4425*4a1a9510SRong-En Fan
4426*4a1a9510SRong-En Fan          <li>
4427*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class="EMPHASIS">REQ_SCR_*
4428*4a1a9510SRong-En Fan            options</i></span></p>
4429*4a1a9510SRong-En Fan
4430*4a1a9510SRong-En Fan            <p>The four options REQ_SCR_ULINE, REQ_SCR_DLINE,
4431*4a1a9510SRong-En Fan            REQ_SCR_DPAGE, REQ_SCR_UPAGE are related to scrolling.
4432*4a1a9510SRong-En Fan            If all the items in the menu cannot be displayed in the
4433*4a1a9510SRong-En Fan            menu sub window, then the menu is scrollable. These
4434*4a1a9510SRong-En Fan            requests can be given to the menu_driver to do the
4435*4a1a9510SRong-En Fan            scrolling either one line up, down or one page down or
4436*4a1a9510SRong-En Fan            up respectively.</p>
4437*4a1a9510SRong-En Fan          </li>
4438*4a1a9510SRong-En Fan
4439*4a1a9510SRong-En Fan          <li>
4440*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class=
4441*4a1a9510SRong-En Fan            "EMPHASIS">REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_NEXT_ITEM
4442*4a1a9510SRong-En Fan            and REQ_PREV_ITEM</i></span></p>
4443*4a1a9510SRong-En Fan
4444*4a1a9510SRong-En Fan            <p>These requests are self explanatory.</p>
4445*4a1a9510SRong-En Fan          </li>
4446*4a1a9510SRong-En Fan
4447*4a1a9510SRong-En Fan          <li>
4448*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class=
4449*4a1a9510SRong-En Fan            "EMPHASIS">REQ_TOGGLE_ITEM</i></span></p>
4450*4a1a9510SRong-En Fan
4451*4a1a9510SRong-En Fan            <p>This request when given, toggles the present
4452*4a1a9510SRong-En Fan            selection. This option is to be used only in a multi
4453*4a1a9510SRong-En Fan            valued menu. So to use this request the option
4454*4a1a9510SRong-En Fan            O_ONEVALUE must be off. This option can be made off or
4455*4a1a9510SRong-En Fan            on with set_menu_opts().</p>
4456*4a1a9510SRong-En Fan          </li>
4457*4a1a9510SRong-En Fan
4458*4a1a9510SRong-En Fan          <li>
4459*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class="EMPHASIS">Pattern
4460*4a1a9510SRong-En Fan            Requests</i></span></p>
4461*4a1a9510SRong-En Fan
4462*4a1a9510SRong-En Fan            <p>Every menu has an associated pattern buffer, which
4463*4a1a9510SRong-En Fan            is used to find the nearest match to the ascii
4464*4a1a9510SRong-En Fan            characters entered by the user. Whenever ascii
4465*4a1a9510SRong-En Fan            characters are given to menu_driver, it puts in to the
4466*4a1a9510SRong-En Fan            pattern buffer. It also tries to find the nearest match
4467*4a1a9510SRong-En Fan            to the pattern in the items list and moves current
4468*4a1a9510SRong-En Fan            selection to that item. The request REQ_CLEAR_PATTERN
4469*4a1a9510SRong-En Fan            clears the pattern buffer. The request REQ_BACK_PATTERN
4470*4a1a9510SRong-En Fan            deletes the previous character in the pattern buffer.
4471*4a1a9510SRong-En Fan            In case the pattern matches more than one item then the
4472*4a1a9510SRong-En Fan            matched items can be cycled through REQ_NEXT_MATCH and
4473*4a1a9510SRong-En Fan            REQ_PREV_MATCH which move the current selection to the
4474*4a1a9510SRong-En Fan            next and previous matches respectively.</p>
4475*4a1a9510SRong-En Fan          </li>
4476*4a1a9510SRong-En Fan
4477*4a1a9510SRong-En Fan          <li>
4478*4a1a9510SRong-En Fan            <p><span class="emphasis"><i class="EMPHASIS">Mouse
4479*4a1a9510SRong-En Fan            Requests</i></span></p>
4480*4a1a9510SRong-En Fan
4481*4a1a9510SRong-En Fan            <p>In case of KEY_MOUSE requests, according to the
4482*4a1a9510SRong-En Fan            mouse position an action is taken accordingly. The
4483*4a1a9510SRong-En Fan            action to be taken is explained in the man page as,</p>
4484*4a1a9510SRong-En Fan            <pre class="PROGRAMLISTING">
4485*4a1a9510SRong-En Fan<span class="emphasis"><i class=
4486*4a1a9510SRong-En Fan"EMPHASIS">       If  the  second argument is the KEY_MOUSE special key, the
4487*4a1a9510SRong-En Fan       associated mouse event is translated into one of the above
4488*4a1a9510SRong-En Fan       pre-defined  requests.   Currently only clicks in the user
4489*4a1a9510SRong-En Fan       window (e.g. inside the menu display area or  the  decora&shy;
4490*4a1a9510SRong-En Fan       tion  window)  are handled. If you click above the display
4491*4a1a9510SRong-En Fan       region of the menu, a REQ_SCR_ULINE is generated,  if  you
4492*4a1a9510SRong-En Fan       doubleclick  a  REQ_SCR_UPAGE  is  generated  and  if  you
4493*4a1a9510SRong-En Fan       tripleclick a REQ_FIRST_ITEM is generated.  If  you  click
4494*4a1a9510SRong-En Fan       below  the  display region of the menu, a REQ_SCR_DLINE is
4495*4a1a9510SRong-En Fan       generated, if you doubleclick a REQ_SCR_DPAGE is generated
4496*4a1a9510SRong-En Fan       and  if  you  tripleclick a REQ_LAST_ITEM is generated. If
4497*4a1a9510SRong-En Fan       you click at an item inside the display area of the  menu,
4498*4a1a9510SRong-En Fan       the menu cursor is positioned to that item.</i></span>
4499*4a1a9510SRong-En Fan</pre>
4500*4a1a9510SRong-En Fan          </li>
4501*4a1a9510SRong-En Fan        </ul>
4502*4a1a9510SRong-En Fan
4503*4a1a9510SRong-En Fan        <p>Each of the above requests will be explained in the
4504*4a1a9510SRong-En Fan        following lines with several examples whenever
4505*4a1a9510SRong-En Fan        appropriate.</p>
4506*4a1a9510SRong-En Fan      </div>
4507*4a1a9510SRong-En Fan
4508*4a1a9510SRong-En Fan      <div class="SECT2">
4509*4a1a9510SRong-En Fan        <hr>
4510*4a1a9510SRong-En Fan
4511*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MENUWINDOWS" id=
4512*4a1a9510SRong-En Fan        "MENUWINDOWS">17.4. Menu Windows</a></h3>
4513*4a1a9510SRong-En Fan
4514*4a1a9510SRong-En Fan        <p>Every menu created is associated with a window and a sub
4515*4a1a9510SRong-En Fan        window. The menu window displays any title or border
4516*4a1a9510SRong-En Fan        associated with the menu. The menu sub window displays the
4517*4a1a9510SRong-En Fan        menu items currently available for selection. But we didn't
4518*4a1a9510SRong-En Fan        specify any window or sub window in the simple example.
4519*4a1a9510SRong-En Fan        When a window is not specified, stdscr is taken as the main
4520*4a1a9510SRong-En Fan        window, and then menu system calculates the sub window size
4521*4a1a9510SRong-En Fan        required for the display of items. Then items are displayed
4522*4a1a9510SRong-En Fan        in the calculated sub window. So let's play with these
4523*4a1a9510SRong-En Fan        windows and display a menu with a border and a title.</p>
4524*4a1a9510SRong-En Fan
4525*4a1a9510SRong-En Fan        <div class="EXAMPLE">
4526*4a1a9510SRong-En Fan          <a name="MMEWI" id="MMEWI"></a>
4527*4a1a9510SRong-En Fan
4528*4a1a9510SRong-En Fan          <p><b>Example 19. Menu Windows Usage example</b></p>
4529*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4530*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;menu.h&gt;
4531*4a1a9510SRong-En Fan
4532*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4533*4a1a9510SRong-En Fan#define CTRLD   4
4534*4a1a9510SRong-En Fan
4535*4a1a9510SRong-En Fanchar *choices[] = {
4536*4a1a9510SRong-En Fan                        "Choice 1",
4537*4a1a9510SRong-En Fan                        "Choice 2",
4538*4a1a9510SRong-En Fan                        "Choice 3",
4539*4a1a9510SRong-En Fan                        "Choice 4",
4540*4a1a9510SRong-En Fan                        "Exit",
4541*4a1a9510SRong-En Fan                        (char *)NULL,
4542*4a1a9510SRong-En Fan                  };
4543*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4544*4a1a9510SRong-En Fan
4545*4a1a9510SRong-En Fanint main()
4546*4a1a9510SRong-En Fan{       ITEM **my_items;
4547*4a1a9510SRong-En Fan        int c;
4548*4a1a9510SRong-En Fan        MENU *my_menu;
4549*4a1a9510SRong-En Fan        WINDOW *my_menu_win;
4550*4a1a9510SRong-En Fan        int n_choices, i;
4551*4a1a9510SRong-En Fan
4552*4a1a9510SRong-En Fan        /* Initialize curses */
4553*4a1a9510SRong-En Fan        initscr();
4554*4a1a9510SRong-En Fan        start_color();
4555*4a1a9510SRong-En Fan        cbreak();
4556*4a1a9510SRong-En Fan        noecho();
4557*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
4558*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
4559*4a1a9510SRong-En Fan
4560*4a1a9510SRong-En Fan        /* Create items */
4561*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
4562*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4563*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4564*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
4565*4a1a9510SRong-En Fan
4566*4a1a9510SRong-En Fan        /* Crate menu */
4567*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
4568*4a1a9510SRong-En Fan
4569*4a1a9510SRong-En Fan        /* Create the window to be associated with the menu */
4570*4a1a9510SRong-En Fan        my_menu_win = newwin(10, 40, 4, 4);
4571*4a1a9510SRong-En Fan        keypad(my_menu_win, TRUE);
4572*4a1a9510SRong-En Fan
4573*4a1a9510SRong-En Fan        /* Set main window and sub window */
4574*4a1a9510SRong-En Fan        set_menu_win(my_menu, my_menu_win);
4575*4a1a9510SRong-En Fan        set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4576*4a1a9510SRong-En Fan
4577*4a1a9510SRong-En Fan        /* Set menu mark to the string " * " */
4578*4a1a9510SRong-En Fan        set_menu_mark(my_menu, " * ");
4579*4a1a9510SRong-En Fan
4580*4a1a9510SRong-En Fan        /* Print a border around the main window and print a title */
4581*4a1a9510SRong-En Fan        box(my_menu_win, 0, 0);
4582*4a1a9510SRong-En Fan        print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4583*4a1a9510SRong-En Fan        mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4584*4a1a9510SRong-En Fan        mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4585*4a1a9510SRong-En Fan        mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4586*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "F1 to exit");
4587*4a1a9510SRong-En Fan        refresh();
4588*4a1a9510SRong-En Fan
4589*4a1a9510SRong-En Fan        /* Post the menu */
4590*4a1a9510SRong-En Fan        post_menu(my_menu);
4591*4a1a9510SRong-En Fan        wrefresh(my_menu_win);
4592*4a1a9510SRong-En Fan
4593*4a1a9510SRong-En Fan        while((c = wgetch(my_menu_win)) != KEY_F(1))
4594*4a1a9510SRong-En Fan        {       switch(c)
4595*4a1a9510SRong-En Fan                {       case KEY_DOWN:
4596*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
4597*4a1a9510SRong-En Fan                                break;
4598*4a1a9510SRong-En Fan                        case KEY_UP:
4599*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
4600*4a1a9510SRong-En Fan                                break;
4601*4a1a9510SRong-En Fan                }
4602*4a1a9510SRong-En Fan                wrefresh(my_menu_win);
4603*4a1a9510SRong-En Fan        }
4604*4a1a9510SRong-En Fan
4605*4a1a9510SRong-En Fan        /* Unpost and free all the memory taken up */
4606*4a1a9510SRong-En Fan        unpost_menu(my_menu);
4607*4a1a9510SRong-En Fan        free_menu(my_menu);
4608*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4609*4a1a9510SRong-En Fan                free_item(my_items[i]);
4610*4a1a9510SRong-En Fan        endwin();
4611*4a1a9510SRong-En Fan}
4612*4a1a9510SRong-En Fan
4613*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4614*4a1a9510SRong-En Fan{       int length, x, y;
4615*4a1a9510SRong-En Fan        float temp;
4616*4a1a9510SRong-En Fan
4617*4a1a9510SRong-En Fan        if(win == NULL)
4618*4a1a9510SRong-En Fan                win = stdscr;
4619*4a1a9510SRong-En Fan        getyx(win, y, x);
4620*4a1a9510SRong-En Fan        if(startx != 0)
4621*4a1a9510SRong-En Fan                x = startx;
4622*4a1a9510SRong-En Fan        if(starty != 0)
4623*4a1a9510SRong-En Fan                y = starty;
4624*4a1a9510SRong-En Fan        if(width == 0)
4625*4a1a9510SRong-En Fan                width = 80;
4626*4a1a9510SRong-En Fan
4627*4a1a9510SRong-En Fan        length = strlen(string);
4628*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
4629*4a1a9510SRong-En Fan        x = startx + (int)temp;
4630*4a1a9510SRong-En Fan        wattron(win, color);
4631*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
4632*4a1a9510SRong-En Fan        wattroff(win, color);
4633*4a1a9510SRong-En Fan        refresh();
4634*4a1a9510SRong-En Fan}</span>
4635*4a1a9510SRong-En Fan</pre>
4636*4a1a9510SRong-En Fan        </div>
4637*4a1a9510SRong-En Fan
4638*4a1a9510SRong-En Fan        <p>This example creates a menu with a title, border, a
4639*4a1a9510SRong-En Fan        fancy line separating title and the items. As you can see,
4640*4a1a9510SRong-En Fan        in order to attach a window to a menu the function
4641*4a1a9510SRong-En Fan        set_menu_win() has to be used. Then we attach the sub
4642*4a1a9510SRong-En Fan        window also. This displays the items in the sub window. You
4643*4a1a9510SRong-En Fan        can also set the mark string which gets displayed to the
4644*4a1a9510SRong-En Fan        left of the selected item with set_menu_mark().</p>
4645*4a1a9510SRong-En Fan      </div>
4646*4a1a9510SRong-En Fan
4647*4a1a9510SRong-En Fan      <div class="SECT2">
4648*4a1a9510SRong-En Fan        <hr>
4649*4a1a9510SRong-En Fan
4650*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="SCROLLMENUS" id=
4651*4a1a9510SRong-En Fan        "SCROLLMENUS">17.5. Scrolling Menus</a></h3>
4652*4a1a9510SRong-En Fan
4653*4a1a9510SRong-En Fan        <p>If the sub window given for a window is not big enough
4654*4a1a9510SRong-En Fan        to show all the items, then the menu will be scrollable.
4655*4a1a9510SRong-En Fan        When you are on the last item in the present list, if you
4656*4a1a9510SRong-En Fan        send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE
4657*4a1a9510SRong-En Fan        and the menu scrolls by one item. You can manually give
4658*4a1a9510SRong-En Fan        REQ_SCR_ operations to do scrolling. Let's see how it can
4659*4a1a9510SRong-En Fan        be done.</p>
4660*4a1a9510SRong-En Fan
4661*4a1a9510SRong-En Fan        <div class="EXAMPLE">
4662*4a1a9510SRong-En Fan          <a name="MMESC" id="MMESC"></a>
4663*4a1a9510SRong-En Fan
4664*4a1a9510SRong-En Fan          <p><b>Example 20. Scrolling Menus example</b></p>
4665*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4666*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4667*4a1a9510SRong-En Fan#include &lt;menu.h&gt;
4668*4a1a9510SRong-En Fan
4669*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4670*4a1a9510SRong-En Fan#define CTRLD   4
4671*4a1a9510SRong-En Fan
4672*4a1a9510SRong-En Fanchar *choices[] = {
4673*4a1a9510SRong-En Fan                        "Choice 1",
4674*4a1a9510SRong-En Fan                        "Choice 2",
4675*4a1a9510SRong-En Fan                        "Choice 3",
4676*4a1a9510SRong-En Fan                        "Choice 4",
4677*4a1a9510SRong-En Fan                        "Choice 5",
4678*4a1a9510SRong-En Fan                        "Choice 6",
4679*4a1a9510SRong-En Fan                        "Choice 7",
4680*4a1a9510SRong-En Fan                        "Choice 8",
4681*4a1a9510SRong-En Fan                        "Choice 9",
4682*4a1a9510SRong-En Fan                        "Choice 10",
4683*4a1a9510SRong-En Fan                        "Exit",
4684*4a1a9510SRong-En Fan                        (char *)NULL,
4685*4a1a9510SRong-En Fan                  };
4686*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
4687*4a1a9510SRong-En Fan
4688*4a1a9510SRong-En Fanint main()
4689*4a1a9510SRong-En Fan{       ITEM **my_items;
4690*4a1a9510SRong-En Fan        int c;
4691*4a1a9510SRong-En Fan        MENU *my_menu;
4692*4a1a9510SRong-En Fan        WINDOW *my_menu_win;
4693*4a1a9510SRong-En Fan        int n_choices, i;
4694*4a1a9510SRong-En Fan
4695*4a1a9510SRong-En Fan        /* Initialize curses */
4696*4a1a9510SRong-En Fan        initscr();
4697*4a1a9510SRong-En Fan        start_color();
4698*4a1a9510SRong-En Fan        cbreak();
4699*4a1a9510SRong-En Fan        noecho();
4700*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
4701*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
4702*4a1a9510SRong-En Fan        init_pair(2, COLOR_CYAN, COLOR_BLACK);
4703*4a1a9510SRong-En Fan
4704*4a1a9510SRong-En Fan        /* Create items */
4705*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
4706*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4707*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4708*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
4709*4a1a9510SRong-En Fan
4710*4a1a9510SRong-En Fan        /* Crate menu */
4711*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
4712*4a1a9510SRong-En Fan
4713*4a1a9510SRong-En Fan        /* Create the window to be associated with the menu */
4714*4a1a9510SRong-En Fan        my_menu_win = newwin(10, 40, 4, 4);
4715*4a1a9510SRong-En Fan        keypad(my_menu_win, TRUE);
4716*4a1a9510SRong-En Fan
4717*4a1a9510SRong-En Fan        /* Set main window and sub window */
4718*4a1a9510SRong-En Fan        set_menu_win(my_menu, my_menu_win);
4719*4a1a9510SRong-En Fan        set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
4720*4a1a9510SRong-En Fan        set_menu_format(my_menu, 5, 1);
4721*4a1a9510SRong-En Fan
4722*4a1a9510SRong-En Fan        /* Set menu mark to the string " * " */
4723*4a1a9510SRong-En Fan        set_menu_mark(my_menu, " * ");
4724*4a1a9510SRong-En Fan
4725*4a1a9510SRong-En Fan        /* Print a border around the main window and print a title */
4726*4a1a9510SRong-En Fan        box(my_menu_win, 0, 0);
4727*4a1a9510SRong-En Fan        print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
4728*4a1a9510SRong-En Fan        mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
4729*4a1a9510SRong-En Fan        mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
4730*4a1a9510SRong-En Fan        mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
4731*4a1a9510SRong-En Fan
4732*4a1a9510SRong-En Fan        /* Post the menu */
4733*4a1a9510SRong-En Fan        post_menu(my_menu);
4734*4a1a9510SRong-En Fan        wrefresh(my_menu_win);
4735*4a1a9510SRong-En Fan
4736*4a1a9510SRong-En Fan        attron(COLOR_PAIR(2));
4737*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scoll down or up a page of items");
4738*4a1a9510SRong-En Fan        mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)");
4739*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(2));
4740*4a1a9510SRong-En Fan        refresh();
4741*4a1a9510SRong-En Fan
4742*4a1a9510SRong-En Fan        while((c = wgetch(my_menu_win)) != KEY_F(1))
4743*4a1a9510SRong-En Fan        {       switch(c)
4744*4a1a9510SRong-En Fan                {       case KEY_DOWN:
4745*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
4746*4a1a9510SRong-En Fan                                break;
4747*4a1a9510SRong-En Fan                        case KEY_UP:
4748*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
4749*4a1a9510SRong-En Fan                                break;
4750*4a1a9510SRong-En Fan                        case KEY_NPAGE:
4751*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_SCR_DPAGE);
4752*4a1a9510SRong-En Fan                                break;
4753*4a1a9510SRong-En Fan                        case KEY_PPAGE:
4754*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_SCR_UPAGE);
4755*4a1a9510SRong-En Fan                                break;
4756*4a1a9510SRong-En Fan                }
4757*4a1a9510SRong-En Fan                wrefresh(my_menu_win);
4758*4a1a9510SRong-En Fan        }
4759*4a1a9510SRong-En Fan
4760*4a1a9510SRong-En Fan        /* Unpost and free all the memory taken up */
4761*4a1a9510SRong-En Fan        unpost_menu(my_menu);
4762*4a1a9510SRong-En Fan        free_menu(my_menu);
4763*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4764*4a1a9510SRong-En Fan                free_item(my_items[i]);
4765*4a1a9510SRong-En Fan        endwin();
4766*4a1a9510SRong-En Fan}
4767*4a1a9510SRong-En Fan
4768*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
4769*4a1a9510SRong-En Fan{       int length, x, y;
4770*4a1a9510SRong-En Fan        float temp;
4771*4a1a9510SRong-En Fan
4772*4a1a9510SRong-En Fan        if(win == NULL)
4773*4a1a9510SRong-En Fan                win = stdscr;
4774*4a1a9510SRong-En Fan        getyx(win, y, x);
4775*4a1a9510SRong-En Fan        if(startx != 0)
4776*4a1a9510SRong-En Fan                x = startx;
4777*4a1a9510SRong-En Fan        if(starty != 0)
4778*4a1a9510SRong-En Fan                y = starty;
4779*4a1a9510SRong-En Fan        if(width == 0)
4780*4a1a9510SRong-En Fan                width = 80;
4781*4a1a9510SRong-En Fan
4782*4a1a9510SRong-En Fan        length = strlen(string);
4783*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
4784*4a1a9510SRong-En Fan        x = startx + (int)temp;
4785*4a1a9510SRong-En Fan        wattron(win, color);
4786*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
4787*4a1a9510SRong-En Fan        wattroff(win, color);
4788*4a1a9510SRong-En Fan        refresh();
4789*4a1a9510SRong-En Fan}</span>
4790*4a1a9510SRong-En Fan</pre>
4791*4a1a9510SRong-En Fan        </div>
4792*4a1a9510SRong-En Fan
4793*4a1a9510SRong-En Fan        <p>This program is self-explanatory. In this example the
4794*4a1a9510SRong-En Fan        number of choices has been increased to ten, which is
4795*4a1a9510SRong-En Fan        larger than our sub window size which can hold 6 items.
4796*4a1a9510SRong-En Fan        This message has to be explicitly conveyed to the menu
4797*4a1a9510SRong-En Fan        system with the function set_menu_format(). In here we
4798*4a1a9510SRong-En Fan        specify the number of rows and columns we want to be
4799*4a1a9510SRong-En Fan        displayed for a single page. We can specify any number of
4800*4a1a9510SRong-En Fan        items to be shown, in the rows variables, if it is less
4801*4a1a9510SRong-En Fan        than the height of the sub window. If the key pressed by
4802*4a1a9510SRong-En Fan        the user is a PAGE UP or PAGE DOWN, the menu is scrolled a
4803*4a1a9510SRong-En Fan        page due to the requests (REQ_SCR_DPAGE and REQ_SCR_UPAGE)
4804*4a1a9510SRong-En Fan        given to menu_driver().</p>
4805*4a1a9510SRong-En Fan      </div>
4806*4a1a9510SRong-En Fan
4807*4a1a9510SRong-En Fan      <div class="SECT2">
4808*4a1a9510SRong-En Fan        <hr>
4809*4a1a9510SRong-En Fan
4810*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MULTICOLUMN" id=
4811*4a1a9510SRong-En Fan        "MULTICOLUMN">17.6. Multi Columnar Menus</a></h3>
4812*4a1a9510SRong-En Fan
4813*4a1a9510SRong-En Fan        <p>In the above example you have seen how to use the
4814*4a1a9510SRong-En Fan        function set_menu_format(). I didn't mention what the cols
4815*4a1a9510SRong-En Fan        variable (third parameter) does. Well, If your sub window
4816*4a1a9510SRong-En Fan        is wide enough, you can opt to display more than one item
4817*4a1a9510SRong-En Fan        per row. This can be specified in the cols variable. To
4818*4a1a9510SRong-En Fan        make things simpler, the following example doesn't show
4819*4a1a9510SRong-En Fan        descriptions for the items.</p>
4820*4a1a9510SRong-En Fan
4821*4a1a9510SRong-En Fan        <div class="EXAMPLE">
4822*4a1a9510SRong-En Fan          <a name="MMEMUCO" id="MMEMUCO"></a>
4823*4a1a9510SRong-En Fan
4824*4a1a9510SRong-En Fan          <p><b>Example 21. Milt Columnar Menus Example</b></p>
4825*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4826*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4827*4a1a9510SRong-En Fan#include &lt;menu.h&gt;
4828*4a1a9510SRong-En Fan
4829*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4830*4a1a9510SRong-En Fan#define CTRLD   4
4831*4a1a9510SRong-En Fan
4832*4a1a9510SRong-En Fanchar *choices[] = {
4833*4a1a9510SRong-En Fan                        "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5",
4834*4a1a9510SRong-En Fan                        "Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10",
4835*4a1a9510SRong-En Fan                        "Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15",
4836*4a1a9510SRong-En Fan                        "Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20",
4837*4a1a9510SRong-En Fan                        "Exit",
4838*4a1a9510SRong-En Fan                        (char *)NULL,
4839*4a1a9510SRong-En Fan                  };
4840*4a1a9510SRong-En Fan
4841*4a1a9510SRong-En Fanint main()
4842*4a1a9510SRong-En Fan{       ITEM **my_items;
4843*4a1a9510SRong-En Fan        int c;
4844*4a1a9510SRong-En Fan        MENU *my_menu;
4845*4a1a9510SRong-En Fan        WINDOW *my_menu_win;
4846*4a1a9510SRong-En Fan        int n_choices, i;
4847*4a1a9510SRong-En Fan
4848*4a1a9510SRong-En Fan        /* Initialize curses */
4849*4a1a9510SRong-En Fan        initscr();
4850*4a1a9510SRong-En Fan        start_color();
4851*4a1a9510SRong-En Fan        cbreak();
4852*4a1a9510SRong-En Fan        noecho();
4853*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
4854*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
4855*4a1a9510SRong-En Fan        init_pair(2, COLOR_CYAN, COLOR_BLACK);
4856*4a1a9510SRong-En Fan
4857*4a1a9510SRong-En Fan        /* Create items */
4858*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
4859*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
4860*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4861*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
4862*4a1a9510SRong-En Fan
4863*4a1a9510SRong-En Fan        /* Crate menu */
4864*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
4865*4a1a9510SRong-En Fan
4866*4a1a9510SRong-En Fan        /* Set menu option not to show the description */
4867*4a1a9510SRong-En Fan        menu_opts_off(my_menu, O_SHOWDESC);
4868*4a1a9510SRong-En Fan
4869*4a1a9510SRong-En Fan        /* Create the window to be associated with the menu */
4870*4a1a9510SRong-En Fan        my_menu_win = newwin(10, 70, 4, 4);
4871*4a1a9510SRong-En Fan        keypad(my_menu_win, TRUE);
4872*4a1a9510SRong-En Fan
4873*4a1a9510SRong-En Fan        /* Set main window and sub window */
4874*4a1a9510SRong-En Fan        set_menu_win(my_menu, my_menu_win);
4875*4a1a9510SRong-En Fan        set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1));
4876*4a1a9510SRong-En Fan        set_menu_format(my_menu, 5, 3);
4877*4a1a9510SRong-En Fan        set_menu_mark(my_menu, " * ");
4878*4a1a9510SRong-En Fan
4879*4a1a9510SRong-En Fan        /* Print a border around the main window and print a title */
4880*4a1a9510SRong-En Fan        box(my_menu_win, 0, 0);
4881*4a1a9510SRong-En Fan
4882*4a1a9510SRong-En Fan        attron(COLOR_PAIR(2));
4883*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll");
4884*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)");
4885*4a1a9510SRong-En Fan        attroff(COLOR_PAIR(2));
4886*4a1a9510SRong-En Fan        refresh();
4887*4a1a9510SRong-En Fan
4888*4a1a9510SRong-En Fan        /* Post the menu */
4889*4a1a9510SRong-En Fan        post_menu(my_menu);
4890*4a1a9510SRong-En Fan        wrefresh(my_menu_win);
4891*4a1a9510SRong-En Fan
4892*4a1a9510SRong-En Fan        while((c = wgetch(my_menu_win)) != KEY_F(1))
4893*4a1a9510SRong-En Fan        {       switch(c)
4894*4a1a9510SRong-En Fan                {       case KEY_DOWN:
4895*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
4896*4a1a9510SRong-En Fan                                break;
4897*4a1a9510SRong-En Fan                        case KEY_UP:
4898*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
4899*4a1a9510SRong-En Fan                                break;
4900*4a1a9510SRong-En Fan                        case KEY_LEFT:
4901*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_LEFT_ITEM);
4902*4a1a9510SRong-En Fan                                break;
4903*4a1a9510SRong-En Fan                        case KEY_RIGHT:
4904*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_RIGHT_ITEM);
4905*4a1a9510SRong-En Fan                                break;
4906*4a1a9510SRong-En Fan                        case KEY_NPAGE:
4907*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_SCR_DPAGE);
4908*4a1a9510SRong-En Fan                                break;
4909*4a1a9510SRong-En Fan                        case KEY_PPAGE:
4910*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_SCR_UPAGE);
4911*4a1a9510SRong-En Fan                                break;
4912*4a1a9510SRong-En Fan                }
4913*4a1a9510SRong-En Fan                wrefresh(my_menu_win);
4914*4a1a9510SRong-En Fan        }
4915*4a1a9510SRong-En Fan
4916*4a1a9510SRong-En Fan        /* Unpost and free all the memory taken up */
4917*4a1a9510SRong-En Fan        unpost_menu(my_menu);
4918*4a1a9510SRong-En Fan        free_menu(my_menu);
4919*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
4920*4a1a9510SRong-En Fan                free_item(my_items[i]);
4921*4a1a9510SRong-En Fan        endwin();
4922*4a1a9510SRong-En Fan}</span>
4923*4a1a9510SRong-En Fan</pre>
4924*4a1a9510SRong-En Fan        </div>
4925*4a1a9510SRong-En Fan
4926*4a1a9510SRong-En Fan        <p>Watch the function call to set_menu_format(). It
4927*4a1a9510SRong-En Fan        specifies the number of columns to be 3, thus displaying 3
4928*4a1a9510SRong-En Fan        items per row. We have also switched off the showing
4929*4a1a9510SRong-En Fan        descriptions with the function menu_opts_off(). There are
4930*4a1a9510SRong-En Fan        couple of functions set_menu_opts(), menu_opts_on() and
4931*4a1a9510SRong-En Fan        menu_opts() which can be used to manipulate menu options.
4932*4a1a9510SRong-En Fan        The following menu options can be specified.</p>
4933*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
4934*4a1a9510SRong-En Fan       O_ONEVALUE
4935*4a1a9510SRong-En Fan            Only one item can be selected for this menu.
4936*4a1a9510SRong-En Fan
4937*4a1a9510SRong-En Fan       O_SHOWDESC
4938*4a1a9510SRong-En Fan            Display  the  item  descriptions  when  the  menu  is
4939*4a1a9510SRong-En Fan            posted.
4940*4a1a9510SRong-En Fan
4941*4a1a9510SRong-En Fan       O_ROWMAJOR
4942*4a1a9510SRong-En Fan            Display the menu in row-major order.
4943*4a1a9510SRong-En Fan
4944*4a1a9510SRong-En Fan       O_IGNORECASE
4945*4a1a9510SRong-En Fan            Ignore the case when pattern-matching.
4946*4a1a9510SRong-En Fan
4947*4a1a9510SRong-En Fan       O_SHOWMATCH
4948*4a1a9510SRong-En Fan            Move the cursor to within the item  name  while  pat&shy;
4949*4a1a9510SRong-En Fan            tern-matching.
4950*4a1a9510SRong-En Fan
4951*4a1a9510SRong-En Fan       O_NONCYCLIC
4952*4a1a9510SRong-En Fan            Don't   wrap   around  next-item  and  previous-item,
4953*4a1a9510SRong-En Fan            requests to the other end of the menu.
4954*4a1a9510SRong-En Fan</pre>
4955*4a1a9510SRong-En Fan
4956*4a1a9510SRong-En Fan        <p>All options are on by default. You can switch specific
4957*4a1a9510SRong-En Fan        attributes on or off with menu_opts_on() and
4958*4a1a9510SRong-En Fan        menu_opts_off() functions. You can also use set_menu_opts()
4959*4a1a9510SRong-En Fan        to directly specify the options. The argument to this
4960*4a1a9510SRong-En Fan        function should be a OR ed value of some of those above
4961*4a1a9510SRong-En Fan        constants. The function menu_opts() can be used to find out
4962*4a1a9510SRong-En Fan        a menu's present options.</p>
4963*4a1a9510SRong-En Fan      </div>
4964*4a1a9510SRong-En Fan
4965*4a1a9510SRong-En Fan      <div class="SECT2">
4966*4a1a9510SRong-En Fan        <hr>
4967*4a1a9510SRong-En Fan
4968*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MULTIVALUEMENUS" id=
4969*4a1a9510SRong-En Fan        "MULTIVALUEMENUS">17.7. Multi Valued Menus</a></h3>
4970*4a1a9510SRong-En Fan
4971*4a1a9510SRong-En Fan        <p>You might be wondering what if you switch off the option
4972*4a1a9510SRong-En Fan        O_ONEVALUE. Then the menu becomes multi-valued. That means
4973*4a1a9510SRong-En Fan        you can select more than one item. This brings us to the
4974*4a1a9510SRong-En Fan        request REQ_TOGGLE_ITEM. Let's see it in action.</p>
4975*4a1a9510SRong-En Fan
4976*4a1a9510SRong-En Fan        <div class="EXAMPLE">
4977*4a1a9510SRong-En Fan          <a name="MMETO" id="MMETO"></a>
4978*4a1a9510SRong-En Fan
4979*4a1a9510SRong-En Fan          <p><b>Example 22. Multi Valued Menus example</b></p>
4980*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
4981*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
4982*4a1a9510SRong-En Fan#include &lt;menu.h&gt;
4983*4a1a9510SRong-En Fan
4984*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
4985*4a1a9510SRong-En Fan#define CTRLD   4
4986*4a1a9510SRong-En Fan
4987*4a1a9510SRong-En Fanchar *choices[] = {
4988*4a1a9510SRong-En Fan                        "Choice 1",
4989*4a1a9510SRong-En Fan                        "Choice 2",
4990*4a1a9510SRong-En Fan                        "Choice 3",
4991*4a1a9510SRong-En Fan                        "Choice 4",
4992*4a1a9510SRong-En Fan                        "Choice 5",
4993*4a1a9510SRong-En Fan                        "Choice 6",
4994*4a1a9510SRong-En Fan                        "Choice 7",
4995*4a1a9510SRong-En Fan                        "Exit",
4996*4a1a9510SRong-En Fan                  };
4997*4a1a9510SRong-En Fan
4998*4a1a9510SRong-En Fanint main()
4999*4a1a9510SRong-En Fan{       ITEM **my_items;
5000*4a1a9510SRong-En Fan        int c;
5001*4a1a9510SRong-En Fan        MENU *my_menu;
5002*4a1a9510SRong-En Fan        int n_choices, i;
5003*4a1a9510SRong-En Fan        ITEM *cur_item;
5004*4a1a9510SRong-En Fan
5005*4a1a9510SRong-En Fan        /* Initialize curses */
5006*4a1a9510SRong-En Fan        initscr();
5007*4a1a9510SRong-En Fan        cbreak();
5008*4a1a9510SRong-En Fan        noecho();
5009*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5010*4a1a9510SRong-En Fan
5011*4a1a9510SRong-En Fan        /* Initialize items */
5012*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
5013*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5014*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
5015*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
5016*4a1a9510SRong-En Fan        my_items[n_choices] = (ITEM *)NULL;
5017*4a1a9510SRong-En Fan
5018*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
5019*4a1a9510SRong-En Fan
5020*4a1a9510SRong-En Fan        /* Make the menu multi valued */
5021*4a1a9510SRong-En Fan        menu_opts_off(my_menu, O_ONEVALUE);
5022*4a1a9510SRong-En Fan
5023*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Use &lt;SPACE&gt; to select or unselect an item.");
5024*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "&lt;ENTER&gt; to see presently selected items(F1 to Exit)");
5025*4a1a9510SRong-En Fan        post_menu(my_menu);
5026*4a1a9510SRong-En Fan        refresh();
5027*4a1a9510SRong-En Fan
5028*4a1a9510SRong-En Fan        while((c = getch()) != KEY_F(1))
5029*4a1a9510SRong-En Fan        {       switch(c)
5030*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5031*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
5032*4a1a9510SRong-En Fan                                break;
5033*4a1a9510SRong-En Fan                        case KEY_UP:
5034*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
5035*4a1a9510SRong-En Fan                                break;
5036*4a1a9510SRong-En Fan                        case ' ':
5037*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_TOGGLE_ITEM);
5038*4a1a9510SRong-En Fan                                break;
5039*4a1a9510SRong-En Fan                        case 10:        /* Enter */
5040*4a1a9510SRong-En Fan                        {       char temp[200];
5041*4a1a9510SRong-En Fan                                ITEM **items;
5042*4a1a9510SRong-En Fan
5043*4a1a9510SRong-En Fan                                items = menu_items(my_menu);
5044*4a1a9510SRong-En Fan                                temp[0] = '\0';
5045*4a1a9510SRong-En Fan                                for(i = 0; i &lt; item_count(my_menu); ++i)
5046*4a1a9510SRong-En Fan                                        if(item_value(items[i]) == TRUE)
5047*4a1a9510SRong-En Fan                                        {       strcat(temp, item_name(items[i]));
5048*4a1a9510SRong-En Fan                                                strcat(temp, " ");
5049*4a1a9510SRong-En Fan                                        }
5050*4a1a9510SRong-En Fan                                move(20, 0);
5051*4a1a9510SRong-En Fan                                clrtoeol();
5052*4a1a9510SRong-En Fan                                mvprintw(20, 0, temp);
5053*4a1a9510SRong-En Fan                                refresh();
5054*4a1a9510SRong-En Fan                        }
5055*4a1a9510SRong-En Fan                        break;
5056*4a1a9510SRong-En Fan                }
5057*4a1a9510SRong-En Fan        }
5058*4a1a9510SRong-En Fan
5059*4a1a9510SRong-En Fan        free_item(my_items[0]);
5060*4a1a9510SRong-En Fan        free_item(my_items[1]);
5061*4a1a9510SRong-En Fan        free_menu(my_menu);
5062*4a1a9510SRong-En Fan        endwin();
5063*4a1a9510SRong-En Fan}
5064*4a1a9510SRong-En Fan        </span>
5065*4a1a9510SRong-En Fan</pre>
5066*4a1a9510SRong-En Fan        </div>
5067*4a1a9510SRong-En Fan
5068*4a1a9510SRong-En Fan        <p>Whew, A lot of new functions. Let's take them one after
5069*4a1a9510SRong-En Fan        another. Firstly, the REQ_TOGGLE_ITEM. In a multi-valued
5070*4a1a9510SRong-En Fan        menu, the user should be allowed to select or un select
5071*4a1a9510SRong-En Fan        more than one item. The request REQ_TOGGLE_ITEM toggles the
5072*4a1a9510SRong-En Fan        present selection. In this case when space is pressed
5073*4a1a9510SRong-En Fan        REQ_TOGGLE_ITEM request is sent to menu_driver to achieve
5074*4a1a9510SRong-En Fan        the result.</p>
5075*4a1a9510SRong-En Fan
5076*4a1a9510SRong-En Fan        <p>Now when the user presses &lt;ENTER&gt; we show the
5077*4a1a9510SRong-En Fan        items he presently selected. First we find out the items
5078*4a1a9510SRong-En Fan        associated with the menu using the function menu_items().
5079*4a1a9510SRong-En Fan        Then we loop through the items to find out if the item is
5080*4a1a9510SRong-En Fan        selected or not. The function item_value() returns TRUE if
5081*4a1a9510SRong-En Fan        an item is selected. The function item_count() returns the
5082*4a1a9510SRong-En Fan        number of items in the menu. The item name can be found
5083*4a1a9510SRong-En Fan        with item_name(). You can also find the description
5084*4a1a9510SRong-En Fan        associated with an item using item_description().</p>
5085*4a1a9510SRong-En Fan      </div>
5086*4a1a9510SRong-En Fan
5087*4a1a9510SRong-En Fan      <div class="SECT2">
5088*4a1a9510SRong-En Fan        <hr>
5089*4a1a9510SRong-En Fan
5090*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MENUOPT" id="MENUOPT">17.8. Menu
5091*4a1a9510SRong-En Fan        Options</a></h3>
5092*4a1a9510SRong-En Fan
5093*4a1a9510SRong-En Fan        <p>Well, by this time you must be itching for some
5094*4a1a9510SRong-En Fan        difference in your menu, with lots of functionality. I
5095*4a1a9510SRong-En Fan        know. You want Colors !!!. You want to create nice menus
5096*4a1a9510SRong-En Fan        similar to those text mode <a href=
5097*4a1a9510SRong-En Fan        "http://www.jersey.net/~debinjoe/games/" target="_top">dos
5098*4a1a9510SRong-En Fan        games</a>. The functions set_menu_fore() and
5099*4a1a9510SRong-En Fan        set_menu_back() can be used to change the attribute of the
5100*4a1a9510SRong-En Fan        selected item and unselected item. The names are
5101*4a1a9510SRong-En Fan        misleading. They don't change menu's foreground or
5102*4a1a9510SRong-En Fan        background which would have been useless.</p>
5103*4a1a9510SRong-En Fan
5104*4a1a9510SRong-En Fan        <p>The function set_menu_grey() can be used to set the
5105*4a1a9510SRong-En Fan        display attribute for the non-selectable items in the menu.
5106*4a1a9510SRong-En Fan        This brings us to the interesting option for an item the
5107*4a1a9510SRong-En Fan        one and only O_SELECTABLE. We can turn it off by the
5108*4a1a9510SRong-En Fan        function item_opts_off() and after that that item is not
5109*4a1a9510SRong-En Fan        selectable. It's like a grayed item in those fancy windows
5110*4a1a9510SRong-En Fan        menus. Let's put these concepts in practice with this
5111*4a1a9510SRong-En Fan        example</p>
5112*4a1a9510SRong-En Fan
5113*4a1a9510SRong-En Fan        <div class="EXAMPLE">
5114*4a1a9510SRong-En Fan          <a name="MMEAT" id="MMEAT"></a>
5115*4a1a9510SRong-En Fan
5116*4a1a9510SRong-En Fan          <p><b>Example 23. Menu Options example</b></p>
5117*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5118*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;menu.h&gt;
5119*4a1a9510SRong-En Fan
5120*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5121*4a1a9510SRong-En Fan#define CTRLD   4
5122*4a1a9510SRong-En Fan
5123*4a1a9510SRong-En Fanchar *choices[] = {
5124*4a1a9510SRong-En Fan                        "Choice 1",
5125*4a1a9510SRong-En Fan                        "Choice 2",
5126*4a1a9510SRong-En Fan                        "Choice 3",
5127*4a1a9510SRong-En Fan                        "Choice 4",
5128*4a1a9510SRong-En Fan                        "Choice 5",
5129*4a1a9510SRong-En Fan                        "Choice 6",
5130*4a1a9510SRong-En Fan                        "Choice 7",
5131*4a1a9510SRong-En Fan                        "Exit",
5132*4a1a9510SRong-En Fan                  };
5133*4a1a9510SRong-En Fan
5134*4a1a9510SRong-En Fanint main()
5135*4a1a9510SRong-En Fan{       ITEM **my_items;
5136*4a1a9510SRong-En Fan        int c;
5137*4a1a9510SRong-En Fan        MENU *my_menu;
5138*4a1a9510SRong-En Fan        int n_choices, i;
5139*4a1a9510SRong-En Fan        ITEM *cur_item;
5140*4a1a9510SRong-En Fan
5141*4a1a9510SRong-En Fan        /* Initialize curses */
5142*4a1a9510SRong-En Fan        initscr();
5143*4a1a9510SRong-En Fan        start_color();
5144*4a1a9510SRong-En Fan        cbreak();
5145*4a1a9510SRong-En Fan        noecho();
5146*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5147*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
5148*4a1a9510SRong-En Fan        init_pair(2, COLOR_GREEN, COLOR_BLACK);
5149*4a1a9510SRong-En Fan        init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5150*4a1a9510SRong-En Fan
5151*4a1a9510SRong-En Fan        /* Initialize items */
5152*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
5153*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5154*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
5155*4a1a9510SRong-En Fan                my_items[i] = new_item(choices[i], choices[i]);
5156*4a1a9510SRong-En Fan        my_items[n_choices] = (ITEM *)NULL;
5157*4a1a9510SRong-En Fan        item_opts_off(my_items[3], O_SELECTABLE);
5158*4a1a9510SRong-En Fan        item_opts_off(my_items[6], O_SELECTABLE);
5159*4a1a9510SRong-En Fan
5160*4a1a9510SRong-En Fan        /* Create menu */
5161*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
5162*4a1a9510SRong-En Fan
5163*4a1a9510SRong-En Fan        /* Set fore ground and back ground of the menu */
5164*4a1a9510SRong-En Fan        set_menu_fore(my_menu, COLOR_PAIR(1) | A_REVERSE);
5165*4a1a9510SRong-En Fan        set_menu_back(my_menu, COLOR_PAIR(2));
5166*4a1a9510SRong-En Fan        set_menu_grey(my_menu, COLOR_PAIR(3));
5167*4a1a9510SRong-En Fan
5168*4a1a9510SRong-En Fan        /* Post the menu */
5169*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5170*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5171*4a1a9510SRong-En Fan        post_menu(my_menu);
5172*4a1a9510SRong-En Fan        refresh();
5173*4a1a9510SRong-En Fan
5174*4a1a9510SRong-En Fan        while((c = getch()) != KEY_F(1))
5175*4a1a9510SRong-En Fan        {       switch(c)
5176*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5177*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
5178*4a1a9510SRong-En Fan                                break;
5179*4a1a9510SRong-En Fan                        case KEY_UP:
5180*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
5181*4a1a9510SRong-En Fan                                break;
5182*4a1a9510SRong-En Fan                        case 10: /* Enter */
5183*4a1a9510SRong-En Fan                                move(20, 0);
5184*4a1a9510SRong-En Fan                                clrtoeol();
5185*4a1a9510SRong-En Fan                                mvprintw(20, 0, "Item selected is : %s",
5186*4a1a9510SRong-En Fan                                                item_name(current_item(my_menu)));
5187*4a1a9510SRong-En Fan                                pos_menu_cursor(my_menu);
5188*4a1a9510SRong-En Fan                                break;
5189*4a1a9510SRong-En Fan                }
5190*4a1a9510SRong-En Fan        }
5191*4a1a9510SRong-En Fan        unpost_menu(my_menu);
5192*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
5193*4a1a9510SRong-En Fan                free_item(my_items[i]);
5194*4a1a9510SRong-En Fan        free_menu(my_menu);
5195*4a1a9510SRong-En Fan        endwin();
5196*4a1a9510SRong-En Fan}
5197*4a1a9510SRong-En Fan        </span>
5198*4a1a9510SRong-En Fan</pre>
5199*4a1a9510SRong-En Fan        </div>
5200*4a1a9510SRong-En Fan      </div>
5201*4a1a9510SRong-En Fan
5202*4a1a9510SRong-En Fan      <div class="SECT2">
5203*4a1a9510SRong-En Fan        <hr>
5204*4a1a9510SRong-En Fan
5205*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="MENUUSERPTR" id=
5206*4a1a9510SRong-En Fan        "MENUUSERPTR">17.9. The useful User Pointer</a></h3>
5207*4a1a9510SRong-En Fan
5208*4a1a9510SRong-En Fan        <p>We can associate a user pointer with each item in the
5209*4a1a9510SRong-En Fan        menu. It works the same way as user pointer in panels. It's
5210*4a1a9510SRong-En Fan        not touched by menu system. You can store any thing you
5211*4a1a9510SRong-En Fan        like in that. I usually use it to store the function to be
5212*4a1a9510SRong-En Fan        executed when the menu option is chosen (It's selected and
5213*4a1a9510SRong-En Fan        may be the user pressed &lt;ENTER&gt;);</p>
5214*4a1a9510SRong-En Fan
5215*4a1a9510SRong-En Fan        <div class="EXAMPLE">
5216*4a1a9510SRong-En Fan          <a name="MMEUS" id="MMEUS"></a>
5217*4a1a9510SRong-En Fan
5218*4a1a9510SRong-En Fan          <p><b>Example 24. Menu User Pointer Usage</b></p>
5219*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5220*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;curses.h&gt;
5221*4a1a9510SRong-En Fan#include &lt;menu.h&gt;
5222*4a1a9510SRong-En Fan
5223*4a1a9510SRong-En Fan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
5224*4a1a9510SRong-En Fan#define CTRLD   4
5225*4a1a9510SRong-En Fan
5226*4a1a9510SRong-En Fanchar *choices[] = {
5227*4a1a9510SRong-En Fan                        "Choice 1",
5228*4a1a9510SRong-En Fan                        "Choice 2",
5229*4a1a9510SRong-En Fan                        "Choice 3",
5230*4a1a9510SRong-En Fan                        "Choice 4",
5231*4a1a9510SRong-En Fan                        "Choice 5",
5232*4a1a9510SRong-En Fan                        "Choice 6",
5233*4a1a9510SRong-En Fan                        "Choice 7",
5234*4a1a9510SRong-En Fan                        "Exit",
5235*4a1a9510SRong-En Fan                  };
5236*4a1a9510SRong-En Fanvoid func(char *name);
5237*4a1a9510SRong-En Fan
5238*4a1a9510SRong-En Fanint main()
5239*4a1a9510SRong-En Fan{       ITEM **my_items;
5240*4a1a9510SRong-En Fan        int c;
5241*4a1a9510SRong-En Fan        MENU *my_menu;
5242*4a1a9510SRong-En Fan        int n_choices, i;
5243*4a1a9510SRong-En Fan        ITEM *cur_item;
5244*4a1a9510SRong-En Fan
5245*4a1a9510SRong-En Fan        /* Initialize curses */
5246*4a1a9510SRong-En Fan        initscr();
5247*4a1a9510SRong-En Fan        start_color();
5248*4a1a9510SRong-En Fan        cbreak();
5249*4a1a9510SRong-En Fan        noecho();
5250*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5251*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
5252*4a1a9510SRong-En Fan        init_pair(2, COLOR_GREEN, COLOR_BLACK);
5253*4a1a9510SRong-En Fan        init_pair(3, COLOR_MAGENTA, COLOR_BLACK);
5254*4a1a9510SRong-En Fan
5255*4a1a9510SRong-En Fan        /* Initialize items */
5256*4a1a9510SRong-En Fan        n_choices = ARRAY_SIZE(choices);
5257*4a1a9510SRong-En Fan        my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
5258*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
5259*4a1a9510SRong-En Fan        {       my_items[i] = new_item(choices[i], choices[i]);
5260*4a1a9510SRong-En Fan                /* Set the user pointer */
5261*4a1a9510SRong-En Fan                set_item_userptr(my_items[i], func);
5262*4a1a9510SRong-En Fan        }
5263*4a1a9510SRong-En Fan        my_items[n_choices] = (ITEM *)NULL;
5264*4a1a9510SRong-En Fan
5265*4a1a9510SRong-En Fan        /* Create menu */
5266*4a1a9510SRong-En Fan        my_menu = new_menu((ITEM **)my_items);
5267*4a1a9510SRong-En Fan
5268*4a1a9510SRong-En Fan        /* Post the menu */
5269*4a1a9510SRong-En Fan        mvprintw(LINES - 3, 0, "Press &lt;ENTER&gt; to see the option selected");
5270*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)");
5271*4a1a9510SRong-En Fan        post_menu(my_menu);
5272*4a1a9510SRong-En Fan        refresh();
5273*4a1a9510SRong-En Fan
5274*4a1a9510SRong-En Fan        while((c = getch()) != KEY_F(1))
5275*4a1a9510SRong-En Fan        {       switch(c)
5276*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5277*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_DOWN_ITEM);
5278*4a1a9510SRong-En Fan                                break;
5279*4a1a9510SRong-En Fan                        case KEY_UP:
5280*4a1a9510SRong-En Fan                                menu_driver(my_menu, REQ_UP_ITEM);
5281*4a1a9510SRong-En Fan                                break;
5282*4a1a9510SRong-En Fan                        case 10: /* Enter */
5283*4a1a9510SRong-En Fan                        {       ITEM *cur;
5284*4a1a9510SRong-En Fan                                void (*p)(char *);
5285*4a1a9510SRong-En Fan
5286*4a1a9510SRong-En Fan                                cur = current_item(my_menu);
5287*4a1a9510SRong-En Fan                                p = item_userptr(cur);
5288*4a1a9510SRong-En Fan                                p((char *)item_name(cur));
5289*4a1a9510SRong-En Fan                                pos_menu_cursor(my_menu);
5290*4a1a9510SRong-En Fan                                break;
5291*4a1a9510SRong-En Fan                        }
5292*4a1a9510SRong-En Fan                        break;
5293*4a1a9510SRong-En Fan                }
5294*4a1a9510SRong-En Fan        }
5295*4a1a9510SRong-En Fan        unpost_menu(my_menu);
5296*4a1a9510SRong-En Fan        for(i = 0; i &lt; n_choices; ++i)
5297*4a1a9510SRong-En Fan                free_item(my_items[i]);
5298*4a1a9510SRong-En Fan        free_menu(my_menu);
5299*4a1a9510SRong-En Fan        endwin();
5300*4a1a9510SRong-En Fan}
5301*4a1a9510SRong-En Fan
5302*4a1a9510SRong-En Fanvoid func(char *name)
5303*4a1a9510SRong-En Fan{       move(20, 0);
5304*4a1a9510SRong-En Fan        clrtoeol();
5305*4a1a9510SRong-En Fan        mvprintw(20, 0, "Item selected is : %s", name);
5306*4a1a9510SRong-En Fan}       </span>
5307*4a1a9510SRong-En Fan</pre>
5308*4a1a9510SRong-En Fan        </div>
5309*4a1a9510SRong-En Fan      </div>
5310*4a1a9510SRong-En Fan    </div>
5311*4a1a9510SRong-En Fan
5312*4a1a9510SRong-En Fan    <div class="SECT1">
5313*4a1a9510SRong-En Fan      <hr>
5314*4a1a9510SRong-En Fan
5315*4a1a9510SRong-En Fan      <h2 class="SECT1"><a name="FORMS" id="FORMS">18. Forms
5316*4a1a9510SRong-En Fan      Library</a></h2>
5317*4a1a9510SRong-En Fan
5318*4a1a9510SRong-En Fan      <p>Well. If you have seen those forms on web pages which take
5319*4a1a9510SRong-En Fan      input from users and do various kinds of things, you might be
5320*4a1a9510SRong-En Fan      wondering how would any one create such forms in text mode
5321*4a1a9510SRong-En Fan      display. It's quite difficult to write those nifty forms in
5322*4a1a9510SRong-En Fan      plain ncurses. Forms library tries to provide a basic frame
5323*4a1a9510SRong-En Fan      work to build and maintain forms with ease. It has lot of
5324*4a1a9510SRong-En Fan      features(functions) which manage validation, dynamic
5325*4a1a9510SRong-En Fan      expansion of fields etc.. Let's see it in full flow.</p>
5326*4a1a9510SRong-En Fan
5327*4a1a9510SRong-En Fan      <p>A form is a collection of fields; each field can be either
5328*4a1a9510SRong-En Fan      a label(static text) or a data-entry location. The forms also
5329*4a1a9510SRong-En Fan      library provides functions to divide forms into multiple
5330*4a1a9510SRong-En Fan      pages.</p>
5331*4a1a9510SRong-En Fan
5332*4a1a9510SRong-En Fan      <div class="SECT2">
5333*4a1a9510SRong-En Fan        <hr>
5334*4a1a9510SRong-En Fan
5335*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="FORMBASICS" id=
5336*4a1a9510SRong-En Fan        "FORMBASICS">18.1. The Basics</a></h3>
5337*4a1a9510SRong-En Fan
5338*4a1a9510SRong-En Fan        <p>Forms are created in much the same way as menus. First
5339*4a1a9510SRong-En Fan        the fields related to the form are created with
5340*4a1a9510SRong-En Fan        new_field(). You can set options for the fields, so that
5341*4a1a9510SRong-En Fan        they can be displayed with some fancy attributes, validated
5342*4a1a9510SRong-En Fan        before the field looses focus etc.. Then the fields are
5343*4a1a9510SRong-En Fan        attached to form. After this, the form can be posted to
5344*4a1a9510SRong-En Fan        display and is ready to receive inputs. On the similar
5345*4a1a9510SRong-En Fan        lines to menu_driver(), the form is manipulated with
5346*4a1a9510SRong-En Fan        form_driver(). We can send requests to form_driver to move
5347*4a1a9510SRong-En Fan        focus to a certain field, move cursor to end of the field
5348*4a1a9510SRong-En Fan        etc.. After the user enters values in the fields and
5349*4a1a9510SRong-En Fan        validation done, form can be unposted and memory allocated
5350*4a1a9510SRong-En Fan        can be freed.</p>
5351*4a1a9510SRong-En Fan
5352*4a1a9510SRong-En Fan        <p>The general flow of control of a forms program looks
5353*4a1a9510SRong-En Fan        like this.</p>
5354*4a1a9510SRong-En Fan
5355*4a1a9510SRong-En Fan        <ol type="1">
5356*4a1a9510SRong-En Fan          <li>
5357*4a1a9510SRong-En Fan            <p>Initialize curses</p>
5358*4a1a9510SRong-En Fan          </li>
5359*4a1a9510SRong-En Fan
5360*4a1a9510SRong-En Fan          <li>
5361*4a1a9510SRong-En Fan            <p>Create fields using new_field(). You can specify the
5362*4a1a9510SRong-En Fan            height and width of the field, and its position on the
5363*4a1a9510SRong-En Fan            form.</p>
5364*4a1a9510SRong-En Fan          </li>
5365*4a1a9510SRong-En Fan
5366*4a1a9510SRong-En Fan          <li>
5367*4a1a9510SRong-En Fan            <p>Create the forms with new_form() by specifying the
5368*4a1a9510SRong-En Fan            fields to be attached with.</p>
5369*4a1a9510SRong-En Fan          </li>
5370*4a1a9510SRong-En Fan
5371*4a1a9510SRong-En Fan          <li>
5372*4a1a9510SRong-En Fan            <p>Post the form with form_post() and refresh the
5373*4a1a9510SRong-En Fan            screen.</p>
5374*4a1a9510SRong-En Fan          </li>
5375*4a1a9510SRong-En Fan
5376*4a1a9510SRong-En Fan          <li>
5377*4a1a9510SRong-En Fan            <p>Process the user requests with a loop and do
5378*4a1a9510SRong-En Fan            necessary updates to form with form_driver.</p>
5379*4a1a9510SRong-En Fan          </li>
5380*4a1a9510SRong-En Fan
5381*4a1a9510SRong-En Fan          <li>
5382*4a1a9510SRong-En Fan            <p>Unpost the menu with form_unpost()</p>
5383*4a1a9510SRong-En Fan          </li>
5384*4a1a9510SRong-En Fan
5385*4a1a9510SRong-En Fan          <li>
5386*4a1a9510SRong-En Fan            <p>Free the memory allocated to menu by free_form()</p>
5387*4a1a9510SRong-En Fan          </li>
5388*4a1a9510SRong-En Fan
5389*4a1a9510SRong-En Fan          <li>
5390*4a1a9510SRong-En Fan            <p>Free the memory allocated to the items with
5391*4a1a9510SRong-En Fan            free_field()</p>
5392*4a1a9510SRong-En Fan          </li>
5393*4a1a9510SRong-En Fan
5394*4a1a9510SRong-En Fan          <li>
5395*4a1a9510SRong-En Fan            <p>End curses</p>
5396*4a1a9510SRong-En Fan          </li>
5397*4a1a9510SRong-En Fan        </ol>
5398*4a1a9510SRong-En Fan
5399*4a1a9510SRong-En Fan        <p>As you can see, working with forms library is much
5400*4a1a9510SRong-En Fan        similar to handling menu library. The following examples
5401*4a1a9510SRong-En Fan        will explore various aspects of form processing. Let's
5402*4a1a9510SRong-En Fan        start the journey with a simple example. first.</p>
5403*4a1a9510SRong-En Fan      </div>
5404*4a1a9510SRong-En Fan
5405*4a1a9510SRong-En Fan      <div class="SECT2">
5406*4a1a9510SRong-En Fan        <hr>
5407*4a1a9510SRong-En Fan
5408*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="COMPILEFORMS" id=
5409*4a1a9510SRong-En Fan        "COMPILEFORMS">18.2. Compiling With the Forms
5410*4a1a9510SRong-En Fan        Library</a></h3>
5411*4a1a9510SRong-En Fan
5412*4a1a9510SRong-En Fan        <p>To use forms library functions, you have to include
5413*4a1a9510SRong-En Fan        form.h and to link the program with forms library the flag
5414*4a1a9510SRong-En Fan        -lform should be added along with -lncurses in that
5415*4a1a9510SRong-En Fan        order.</p>
5416*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
5417*4a1a9510SRong-En Fan    #include &lt;form.h&gt;
5418*4a1a9510SRong-En Fan    .
5419*4a1a9510SRong-En Fan    .
5420*4a1a9510SRong-En Fan    .
5421*4a1a9510SRong-En Fan
5422*4a1a9510SRong-En Fan    compile and link: gcc &lt;program file&gt; -lform -lncurses
5423*4a1a9510SRong-En Fan</pre>
5424*4a1a9510SRong-En Fan
5425*4a1a9510SRong-En Fan        <div class="EXAMPLE">
5426*4a1a9510SRong-En Fan          <a name="FFOSI" id="FFOSI"></a>
5427*4a1a9510SRong-En Fan
5428*4a1a9510SRong-En Fan          <p><b>Example 25. Forms Basics</b></p>
5429*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5430*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5431*4a1a9510SRong-En Fan
5432*4a1a9510SRong-En Fanint main()
5433*4a1a9510SRong-En Fan{       FIELD *field[3];
5434*4a1a9510SRong-En Fan        FORM  *my_form;
5435*4a1a9510SRong-En Fan        int ch;
5436*4a1a9510SRong-En Fan
5437*4a1a9510SRong-En Fan        /* Initialize curses */
5438*4a1a9510SRong-En Fan        initscr();
5439*4a1a9510SRong-En Fan        cbreak();
5440*4a1a9510SRong-En Fan        noecho();
5441*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5442*4a1a9510SRong-En Fan
5443*4a1a9510SRong-En Fan        /* Initialize the fields */
5444*4a1a9510SRong-En Fan        field[0] = new_field(1, 10, 4, 18, 0, 0);
5445*4a1a9510SRong-En Fan        field[1] = new_field(1, 10, 6, 18, 0, 0);
5446*4a1a9510SRong-En Fan        field[2] = NULL;
5447*4a1a9510SRong-En Fan
5448*4a1a9510SRong-En Fan        /* Set field options */
5449*4a1a9510SRong-En Fan        set_field_back(field[0], A_UNDERLINE);  /* Print a line for the option  */
5450*4a1a9510SRong-En Fan        field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5451*4a1a9510SRong-En Fan                                                /* Field is filled up           */
5452*4a1a9510SRong-En Fan        set_field_back(field[1], A_UNDERLINE);
5453*4a1a9510SRong-En Fan        field_opts_off(field[1], O_AUTOSKIP);
5454*4a1a9510SRong-En Fan
5455*4a1a9510SRong-En Fan        /* Create the form and post it */
5456*4a1a9510SRong-En Fan        my_form = new_form(field);
5457*4a1a9510SRong-En Fan        post_form(my_form);
5458*4a1a9510SRong-En Fan        refresh();
5459*4a1a9510SRong-En Fan
5460*4a1a9510SRong-En Fan        mvprintw(4, 10, "Value 1:");
5461*4a1a9510SRong-En Fan        mvprintw(6, 10, "Value 2:");
5462*4a1a9510SRong-En Fan        refresh();
5463*4a1a9510SRong-En Fan
5464*4a1a9510SRong-En Fan        /* Loop through to get user requests */
5465*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
5466*4a1a9510SRong-En Fan        {       switch(ch)
5467*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5468*4a1a9510SRong-En Fan                                /* Go to next field */
5469*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_NEXT_FIELD);
5470*4a1a9510SRong-En Fan                                /* Go to the end of the present buffer */
5471*4a1a9510SRong-En Fan                                /* Leaves nicely at the last character */
5472*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5473*4a1a9510SRong-En Fan                                break;
5474*4a1a9510SRong-En Fan                        case KEY_UP:
5475*4a1a9510SRong-En Fan                                /* Go to previous field */
5476*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_PREV_FIELD);
5477*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5478*4a1a9510SRong-En Fan                                break;
5479*4a1a9510SRong-En Fan                        default:
5480*4a1a9510SRong-En Fan                                /* If this is a normal character, it gets */
5481*4a1a9510SRong-En Fan                                /* Printed                                */
5482*4a1a9510SRong-En Fan                                form_driver(my_form, ch);
5483*4a1a9510SRong-En Fan                                break;
5484*4a1a9510SRong-En Fan                }
5485*4a1a9510SRong-En Fan        }
5486*4a1a9510SRong-En Fan
5487*4a1a9510SRong-En Fan        /* Un post form and free the memory */
5488*4a1a9510SRong-En Fan        unpost_form(my_form);
5489*4a1a9510SRong-En Fan        free_form(my_form);
5490*4a1a9510SRong-En Fan        free_field(field[0]);
5491*4a1a9510SRong-En Fan        free_field(field[1]);
5492*4a1a9510SRong-En Fan
5493*4a1a9510SRong-En Fan        endwin();
5494*4a1a9510SRong-En Fan        return 0;
5495*4a1a9510SRong-En Fan}</span>
5496*4a1a9510SRong-En Fan</pre>
5497*4a1a9510SRong-En Fan        </div>
5498*4a1a9510SRong-En Fan
5499*4a1a9510SRong-En Fan        <p>Above example is pretty straight forward. It creates two
5500*4a1a9510SRong-En Fan        fields with <tt class="LITERAL">new_field()</tt>.
5501*4a1a9510SRong-En Fan        new_field() takes height, width, starty, startx, number of
5502*4a1a9510SRong-En Fan        offscreen rows and number of additional working buffers.
5503*4a1a9510SRong-En Fan        The fifth argument number of offscreen rows specifies how
5504*4a1a9510SRong-En Fan        much of the field to be shown. If it is zero, the entire
5505*4a1a9510SRong-En Fan        field is always displayed otherwise the form will be
5506*4a1a9510SRong-En Fan        scrollable when the user accesses not displayed parts of
5507*4a1a9510SRong-En Fan        the field. The forms library allocates one buffer per field
5508*4a1a9510SRong-En Fan        to store the data user enters. Using the last parameter to
5509*4a1a9510SRong-En Fan        new_field() we can specify it to allocate some additional
5510*4a1a9510SRong-En Fan        buffers. These can be used for any purpose you like.</p>
5511*4a1a9510SRong-En Fan
5512*4a1a9510SRong-En Fan        <p>After creating the fields, back ground attribute of both
5513*4a1a9510SRong-En Fan        of them is set to an underscore with set_field_back(). The
5514*4a1a9510SRong-En Fan        AUTOSKIP option is turned off using field_opts_off(). If
5515*4a1a9510SRong-En Fan        this option is turned on, focus will move to the next field
5516*4a1a9510SRong-En Fan        in the form once the active field is filled up
5517*4a1a9510SRong-En Fan        completely.</p>
5518*4a1a9510SRong-En Fan
5519*4a1a9510SRong-En Fan        <p>After attaching the fields to the form, it is posted.
5520*4a1a9510SRong-En Fan        Here on, user inputs are processed in the while loop, by
5521*4a1a9510SRong-En Fan        making corresponding requests to form_driver. The details
5522*4a1a9510SRong-En Fan        of all the requests to the form_driver() are explained
5523*4a1a9510SRong-En Fan        later.</p>
5524*4a1a9510SRong-En Fan      </div>
5525*4a1a9510SRong-En Fan
5526*4a1a9510SRong-En Fan      <div class="SECT2">
5527*4a1a9510SRong-En Fan        <hr>
5528*4a1a9510SRong-En Fan
5529*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="PLAYFIELDS" id=
5530*4a1a9510SRong-En Fan        "PLAYFIELDS">18.3. Playing with Fields</a></h3>
5531*4a1a9510SRong-En Fan
5532*4a1a9510SRong-En Fan        <p>Each form field is associated with a lot of attributes.
5533*4a1a9510SRong-En Fan        They can be manipulated to get the required effect and to
5534*4a1a9510SRong-En Fan        have fun !!!. So why wait?</p>
5535*4a1a9510SRong-En Fan
5536*4a1a9510SRong-En Fan        <div class="SECT3">
5537*4a1a9510SRong-En Fan          <hr>
5538*4a1a9510SRong-En Fan
5539*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="FETCHINFO" id=
5540*4a1a9510SRong-En Fan          "FETCHINFO">18.3.1. Fetching Size and Location of
5541*4a1a9510SRong-En Fan          Field</a></h4>
5542*4a1a9510SRong-En Fan
5543*4a1a9510SRong-En Fan          <p>The parameters we have given at the time of creation
5544*4a1a9510SRong-En Fan          of a field can be retrieved with field_info(). It returns
5545*4a1a9510SRong-En Fan          height, width, starty, startx, number of offscreen rows,
5546*4a1a9510SRong-En Fan          and number of additional buffers into the parameters
5547*4a1a9510SRong-En Fan          given to it. It is a sort of inverse of new_field().</p>
5548*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5549*4a1a9510SRong-En Fanint field_info(     FIELD *field,              /* field from which to fetch */
5550*4a1a9510SRong-En Fan                    int *height, *int width,   /* field size */
5551*4a1a9510SRong-En Fan                    int *top, int *left,       /* upper left corner */
5552*4a1a9510SRong-En Fan                    int *offscreen,            /* number of offscreen rows */
5553*4a1a9510SRong-En Fan                    int *nbuf);                /* number of working buffers */
5554*4a1a9510SRong-En Fan</pre>
5555*4a1a9510SRong-En Fan        </div>
5556*4a1a9510SRong-En Fan
5557*4a1a9510SRong-En Fan        <div class="SECT3">
5558*4a1a9510SRong-En Fan          <hr>
5559*4a1a9510SRong-En Fan
5560*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="MOVEFIELD" id=
5561*4a1a9510SRong-En Fan          "MOVEFIELD">18.3.2. Moving the field</a></h4>
5562*4a1a9510SRong-En Fan
5563*4a1a9510SRong-En Fan          <p>The location of the field can be moved to a different
5564*4a1a9510SRong-En Fan          position with move_field().</p>
5565*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5566*4a1a9510SRong-En Fanint move_field(    FIELD *field,              /* field to alter */
5567*4a1a9510SRong-En Fan                   int top, int left);        /* new upper-left corner */
5568*4a1a9510SRong-En Fan</pre>
5569*4a1a9510SRong-En Fan
5570*4a1a9510SRong-En Fan          <p>As usual, the changed position can be queried with
5571*4a1a9510SRong-En Fan          field_infor().</p>
5572*4a1a9510SRong-En Fan        </div>
5573*4a1a9510SRong-En Fan
5574*4a1a9510SRong-En Fan        <div class="SECT3">
5575*4a1a9510SRong-En Fan          <hr>
5576*4a1a9510SRong-En Fan
5577*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="JUSTIFYFIELD" id=
5578*4a1a9510SRong-En Fan          "JUSTIFYFIELD">18.3.3. Field Justification</a></h4>
5579*4a1a9510SRong-En Fan
5580*4a1a9510SRong-En Fan          <p>The justification to be done for the field can be
5581*4a1a9510SRong-En Fan          fixed using the function set_field_just().</p>
5582*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5583*4a1a9510SRong-En Fan    int set_field_just(FIELD *field,          /* field to alter */
5584*4a1a9510SRong-En Fan               int justmode);         /* mode to set */
5585*4a1a9510SRong-En Fan    int field_just(FIELD *field);          /* fetch justify mode of field */
5586*4a1a9510SRong-En Fan</pre>
5587*4a1a9510SRong-En Fan
5588*4a1a9510SRong-En Fan          <p>The justification mode valued accepted and returned by
5589*4a1a9510SRong-En Fan          these functions are NO_JUSTIFICATION, JUSTIFY_RIGHT,
5590*4a1a9510SRong-En Fan          JUSTIFY_LEFT, or JUSTIFY_CENTER.</p>
5591*4a1a9510SRong-En Fan        </div>
5592*4a1a9510SRong-En Fan
5593*4a1a9510SRong-En Fan        <div class="SECT3">
5594*4a1a9510SRong-En Fan          <hr>
5595*4a1a9510SRong-En Fan
5596*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="FIELDDISPATTRIB" id=
5597*4a1a9510SRong-En Fan          "FIELDDISPATTRIB">18.3.4. Field Display
5598*4a1a9510SRong-En Fan          Attributes</a></h4>
5599*4a1a9510SRong-En Fan
5600*4a1a9510SRong-En Fan          <p>As you have seen, in the above example, display
5601*4a1a9510SRong-En Fan          attribute for the fields can be set with set_field_fore()
5602*4a1a9510SRong-En Fan          and setfield_back(). These functions set foreground and
5603*4a1a9510SRong-En Fan          background attribute of the fields. You can also specify
5604*4a1a9510SRong-En Fan          a pad character which will be filled in the unfilled
5605*4a1a9510SRong-En Fan          portion of the field. The pad character is set with a
5606*4a1a9510SRong-En Fan          call to set_field_pad(). Default pad value is a space.
5607*4a1a9510SRong-En Fan          The functions field_fore(), field_back, field_pad() can
5608*4a1a9510SRong-En Fan          be used to query the present foreground, background
5609*4a1a9510SRong-En Fan          attributes and pad character for the field. The following
5610*4a1a9510SRong-En Fan          list gives the usage of functions.</p>
5611*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5612*4a1a9510SRong-En Fan&#13;int set_field_fore(FIELD *field,        /* field to alter */
5613*4a1a9510SRong-En Fan                   chtype attr);        /* attribute to set */
5614*4a1a9510SRong-En Fan
5615*4a1a9510SRong-En Fanchtype field_fore(FIELD *field);        /* field to query */
5616*4a1a9510SRong-En Fan                                        /* returns foreground attribute */
5617*4a1a9510SRong-En Fan
5618*4a1a9510SRong-En Fanint set_field_back(FIELD *field,        /* field to alter */
5619*4a1a9510SRong-En Fan                   chtype attr);        /* attribute to set */
5620*4a1a9510SRong-En Fan
5621*4a1a9510SRong-En Fanchtype field_back(FIELD *field);        /* field to query */
5622*4a1a9510SRong-En Fan                                        /* returns background attribute */
5623*4a1a9510SRong-En Fan
5624*4a1a9510SRong-En Fanint set_field_pad(FIELD *field,         /* field to alter */
5625*4a1a9510SRong-En Fan                  int pad);             /* pad character to set */
5626*4a1a9510SRong-En Fan
5627*4a1a9510SRong-En Fanchtype field_pad(FIELD *field);         /* field to query */
5628*4a1a9510SRong-En Fan                                        /* returns present pad character */&#13;
5629*4a1a9510SRong-En Fan</pre>
5630*4a1a9510SRong-En Fan
5631*4a1a9510SRong-En Fan          <p>Though above functions seem quite simple, using colors
5632*4a1a9510SRong-En Fan          with set_field_fore() may be frustrating in the
5633*4a1a9510SRong-En Fan          beginning. Let me first explain about foreground and
5634*4a1a9510SRong-En Fan          background attributes of a field. The foreground
5635*4a1a9510SRong-En Fan          attribute is associated with the character. That means a
5636*4a1a9510SRong-En Fan          character in the field is printed with the attribute you
5637*4a1a9510SRong-En Fan          have set with set_field_fore(). Background attribute is
5638*4a1a9510SRong-En Fan          the attribute used to fill background of field, whether
5639*4a1a9510SRong-En Fan          any character is there or not. So what about colors?
5640*4a1a9510SRong-En Fan          Since colors are always defined in pairs, what is the
5641*4a1a9510SRong-En Fan          right way to display colored fields? Here's an example
5642*4a1a9510SRong-En Fan          clarifying color attributes.</p>
5643*4a1a9510SRong-En Fan
5644*4a1a9510SRong-En Fan          <div class="EXAMPLE">
5645*4a1a9510SRong-En Fan            <a name="FFOAT" id="FFOAT"></a>
5646*4a1a9510SRong-En Fan
5647*4a1a9510SRong-En Fan            <p><b>Example 26. Form Attributes example</b></p>
5648*4a1a9510SRong-En Fan            <pre class="PROGRAMLISTING">
5649*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5650*4a1a9510SRong-En Fan
5651*4a1a9510SRong-En Fanint main()
5652*4a1a9510SRong-En Fan{       FIELD *field[3];
5653*4a1a9510SRong-En Fan        FORM  *my_form;
5654*4a1a9510SRong-En Fan        int ch;
5655*4a1a9510SRong-En Fan
5656*4a1a9510SRong-En Fan        /* Initialize curses */
5657*4a1a9510SRong-En Fan        initscr();
5658*4a1a9510SRong-En Fan        start_color();
5659*4a1a9510SRong-En Fan        cbreak();
5660*4a1a9510SRong-En Fan        noecho();
5661*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5662*4a1a9510SRong-En Fan
5663*4a1a9510SRong-En Fan        /* Initialize few color pairs */
5664*4a1a9510SRong-En Fan        init_pair(1, COLOR_WHITE, COLOR_BLUE);
5665*4a1a9510SRong-En Fan        init_pair(2, COLOR_WHITE, COLOR_BLUE);
5666*4a1a9510SRong-En Fan
5667*4a1a9510SRong-En Fan        /* Initialize the fields */
5668*4a1a9510SRong-En Fan        field[0] = new_field(1, 10, 4, 18, 0, 0);
5669*4a1a9510SRong-En Fan        field[1] = new_field(1, 10, 6, 18, 0, 0);
5670*4a1a9510SRong-En Fan        field[2] = NULL;
5671*4a1a9510SRong-En Fan
5672*4a1a9510SRong-En Fan        /* Set field options */
5673*4a1a9510SRong-En Fan        set_field_fore(field[0], COLOR_PAIR(1));/* Put the field with blue background */
5674*4a1a9510SRong-En Fan        set_field_back(field[0], COLOR_PAIR(2));/* and white foreground (characters */
5675*4a1a9510SRong-En Fan                                                /* are printed in white         */
5676*4a1a9510SRong-En Fan        field_opts_off(field[0], O_AUTOSKIP);   /* Don't go to next field when this */
5677*4a1a9510SRong-En Fan                                                /* Field is filled up           */
5678*4a1a9510SRong-En Fan        set_field_back(field[1], A_UNDERLINE);
5679*4a1a9510SRong-En Fan        field_opts_off(field[1], O_AUTOSKIP);
5680*4a1a9510SRong-En Fan
5681*4a1a9510SRong-En Fan        /* Create the form and post it */
5682*4a1a9510SRong-En Fan        my_form = new_form(field);
5683*4a1a9510SRong-En Fan        post_form(my_form);
5684*4a1a9510SRong-En Fan        refresh();
5685*4a1a9510SRong-En Fan
5686*4a1a9510SRong-En Fan        set_current_field(my_form, field[0]); /* Set focus to the colored field */
5687*4a1a9510SRong-En Fan        mvprintw(4, 10, "Value 1:");
5688*4a1a9510SRong-En Fan        mvprintw(6, 10, "Value 2:");
5689*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
5690*4a1a9510SRong-En Fan        refresh();
5691*4a1a9510SRong-En Fan
5692*4a1a9510SRong-En Fan        /* Loop through to get user requests */
5693*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
5694*4a1a9510SRong-En Fan        {       switch(ch)
5695*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5696*4a1a9510SRong-En Fan                                /* Go to next field */
5697*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_NEXT_FIELD);
5698*4a1a9510SRong-En Fan                                /* Go to the end of the present buffer */
5699*4a1a9510SRong-En Fan                                /* Leaves nicely at the last character */
5700*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5701*4a1a9510SRong-En Fan                                break;
5702*4a1a9510SRong-En Fan                        case KEY_UP:
5703*4a1a9510SRong-En Fan                                /* Go to previous field */
5704*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_PREV_FIELD);
5705*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5706*4a1a9510SRong-En Fan                                break;
5707*4a1a9510SRong-En Fan                        default:
5708*4a1a9510SRong-En Fan                                /* If this is a normal character, it gets */
5709*4a1a9510SRong-En Fan                                /* Printed                                */
5710*4a1a9510SRong-En Fan                                form_driver(my_form, ch);
5711*4a1a9510SRong-En Fan                                break;
5712*4a1a9510SRong-En Fan                }
5713*4a1a9510SRong-En Fan        }
5714*4a1a9510SRong-En Fan
5715*4a1a9510SRong-En Fan        /* Un post form and free the memory */
5716*4a1a9510SRong-En Fan        unpost_form(my_form);
5717*4a1a9510SRong-En Fan        free_form(my_form);
5718*4a1a9510SRong-En Fan        free_field(field[0]);
5719*4a1a9510SRong-En Fan        free_field(field[1]);
5720*4a1a9510SRong-En Fan
5721*4a1a9510SRong-En Fan        endwin();
5722*4a1a9510SRong-En Fan        return 0;
5723*4a1a9510SRong-En Fan}</span>
5724*4a1a9510SRong-En Fan</pre>
5725*4a1a9510SRong-En Fan          </div>
5726*4a1a9510SRong-En Fan
5727*4a1a9510SRong-En Fan          <p>Play with the color pairs and try to understand the
5728*4a1a9510SRong-En Fan          foreground and background attributes. In my programs
5729*4a1a9510SRong-En Fan          using color attributes, I usually set only the background
5730*4a1a9510SRong-En Fan          with set_field_back(). Curses simply doesn't allow
5731*4a1a9510SRong-En Fan          defining individual color attributes.</p>
5732*4a1a9510SRong-En Fan        </div>
5733*4a1a9510SRong-En Fan
5734*4a1a9510SRong-En Fan        <div class="SECT3">
5735*4a1a9510SRong-En Fan          <hr>
5736*4a1a9510SRong-En Fan
5737*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="FIELDOPTIONBITS" id=
5738*4a1a9510SRong-En Fan          "FIELDOPTIONBITS">18.3.5. Field Option Bits</a></h4>
5739*4a1a9510SRong-En Fan
5740*4a1a9510SRong-En Fan          <p>There is also a large collection of field option bits
5741*4a1a9510SRong-En Fan          you can set to control various aspects of forms
5742*4a1a9510SRong-En Fan          processing. You can manipulate them with these
5743*4a1a9510SRong-En Fan          functions:</p>
5744*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5745*4a1a9510SRong-En Fanint set_field_opts(FIELD *field,          /* field to alter */
5746*4a1a9510SRong-En Fan                   int attr);             /* attribute to set */
5747*4a1a9510SRong-En Fan
5748*4a1a9510SRong-En Fanint field_opts_on(FIELD *field,           /* field to alter */
5749*4a1a9510SRong-En Fan                  int attr);              /* attributes to turn on */
5750*4a1a9510SRong-En Fan
5751*4a1a9510SRong-En Fanint field_opts_off(FIELD *field,          /* field to alter */
5752*4a1a9510SRong-En Fan                  int attr);              /* attributes to turn off */
5753*4a1a9510SRong-En Fan
5754*4a1a9510SRong-En Fanint field_opts(FIELD *field);             /* field to query */
5755*4a1a9510SRong-En Fan</pre>
5756*4a1a9510SRong-En Fan
5757*4a1a9510SRong-En Fan          <p>The function set_field_opts() can be used to directly
5758*4a1a9510SRong-En Fan          set attributes of a field or you can choose to switch a
5759*4a1a9510SRong-En Fan          few attributes on and off with field_opts_on() and
5760*4a1a9510SRong-En Fan          field_opts_off() selectively. Anytime you can query the
5761*4a1a9510SRong-En Fan          attributes of a field with field_opts(). The following is
5762*4a1a9510SRong-En Fan          the list of available options. By default, all options
5763*4a1a9510SRong-En Fan          are on.</p>
5764*4a1a9510SRong-En Fan
5765*4a1a9510SRong-En Fan          <div class="VARIABLELIST">
5766*4a1a9510SRong-En Fan            <dl>
5767*4a1a9510SRong-En Fan              <dt>O_VISIBLE</dt>
5768*4a1a9510SRong-En Fan
5769*4a1a9510SRong-En Fan              <dd>
5770*4a1a9510SRong-En Fan                <p>Controls whether the field is visible on the
5771*4a1a9510SRong-En Fan                screen. Can be used during form processing to hide
5772*4a1a9510SRong-En Fan                or pop up fields depending on the value of parent
5773*4a1a9510SRong-En Fan                fields.</p>
5774*4a1a9510SRong-En Fan              </dd>
5775*4a1a9510SRong-En Fan
5776*4a1a9510SRong-En Fan              <dt>O_ACTIVE</dt>
5777*4a1a9510SRong-En Fan
5778*4a1a9510SRong-En Fan              <dd>
5779*4a1a9510SRong-En Fan                <p>Controls whether the field is active during
5780*4a1a9510SRong-En Fan                forms processing (i.e. visited by form navigation
5781*4a1a9510SRong-En Fan                keys). Can be used to make labels or derived fields
5782*4a1a9510SRong-En Fan                with buffer values alterable by the forms
5783*4a1a9510SRong-En Fan                application, not the user.</p>
5784*4a1a9510SRong-En Fan              </dd>
5785*4a1a9510SRong-En Fan
5786*4a1a9510SRong-En Fan              <dt>O_PUBLIC</dt>
5787*4a1a9510SRong-En Fan
5788*4a1a9510SRong-En Fan              <dd>
5789*4a1a9510SRong-En Fan                <p>Controls whether data is displayed during field
5790*4a1a9510SRong-En Fan                entry. If this option is turned off on a field, the
5791*4a1a9510SRong-En Fan                library will accept and edit data in that field,
5792*4a1a9510SRong-En Fan                but it will not be displayed and the visible field
5793*4a1a9510SRong-En Fan                cursor will not move. You can turn off the O_PUBLIC
5794*4a1a9510SRong-En Fan                bit to define password fields.</p>
5795*4a1a9510SRong-En Fan              </dd>
5796*4a1a9510SRong-En Fan
5797*4a1a9510SRong-En Fan              <dt>O_EDIT</dt>
5798*4a1a9510SRong-En Fan
5799*4a1a9510SRong-En Fan              <dd>
5800*4a1a9510SRong-En Fan                <p>Controls whether the field's data can be
5801*4a1a9510SRong-En Fan                modified. When this option is off, all editing
5802*4a1a9510SRong-En Fan                requests except <tt class=
5803*4a1a9510SRong-En Fan                "LITERAL">REQ_PREV_CHOICE</tt> and <tt class=
5804*4a1a9510SRong-En Fan                "LITERAL">REQ_NEXT_CHOICE</tt>will fail. Such
5805*4a1a9510SRong-En Fan                read-only fields may be useful for help
5806*4a1a9510SRong-En Fan                messages.</p>
5807*4a1a9510SRong-En Fan              </dd>
5808*4a1a9510SRong-En Fan
5809*4a1a9510SRong-En Fan              <dt>O_WRAP</dt>
5810*4a1a9510SRong-En Fan
5811*4a1a9510SRong-En Fan              <dd>
5812*4a1a9510SRong-En Fan                <p>Controls word-wrapping in multi-line fields.
5813*4a1a9510SRong-En Fan                Normally, when any character of a (blank-separated)
5814*4a1a9510SRong-En Fan                word reaches the end of the current line, the
5815*4a1a9510SRong-En Fan                entire word is wrapped to the next line (assuming
5816*4a1a9510SRong-En Fan                there is one). When this option is off, the word
5817*4a1a9510SRong-En Fan                will be split across the line break.</p>
5818*4a1a9510SRong-En Fan              </dd>
5819*4a1a9510SRong-En Fan
5820*4a1a9510SRong-En Fan              <dt>O_BLANK</dt>
5821*4a1a9510SRong-En Fan
5822*4a1a9510SRong-En Fan              <dd>
5823*4a1a9510SRong-En Fan                <p>Controls field blanking. When this option is on,
5824*4a1a9510SRong-En Fan                entering a character at the first field position
5825*4a1a9510SRong-En Fan                erases the entire field (except for the
5826*4a1a9510SRong-En Fan                just-entered character).</p>
5827*4a1a9510SRong-En Fan              </dd>
5828*4a1a9510SRong-En Fan
5829*4a1a9510SRong-En Fan              <dt>O_AUTOSKIP</dt>
5830*4a1a9510SRong-En Fan
5831*4a1a9510SRong-En Fan              <dd>
5832*4a1a9510SRong-En Fan                <p>Controls automatic skip to next field when this
5833*4a1a9510SRong-En Fan                one fills. Normally, when the forms user tries to
5834*4a1a9510SRong-En Fan                type more data into a field than will fit, the
5835*4a1a9510SRong-En Fan                editing location jumps to next field. When this
5836*4a1a9510SRong-En Fan                option is off, the user's cursor will hang at the
5837*4a1a9510SRong-En Fan                end of the field. This option is ignored in dynamic
5838*4a1a9510SRong-En Fan                fields that have not reached their size limit.</p>
5839*4a1a9510SRong-En Fan              </dd>
5840*4a1a9510SRong-En Fan
5841*4a1a9510SRong-En Fan              <dt>O_NULLOK</dt>
5842*4a1a9510SRong-En Fan
5843*4a1a9510SRong-En Fan              <dd>
5844*4a1a9510SRong-En Fan                <p>Controls whether validation is applied to blank
5845*4a1a9510SRong-En Fan                fields. Normally, it is not; the user can leave a
5846*4a1a9510SRong-En Fan                field blank without invoking the usual validation
5847*4a1a9510SRong-En Fan                check on exit. If this option is off on a field,
5848*4a1a9510SRong-En Fan                exit from it will invoke a validation check.</p>
5849*4a1a9510SRong-En Fan              </dd>
5850*4a1a9510SRong-En Fan
5851*4a1a9510SRong-En Fan              <dt>O_PASSOK</dt>
5852*4a1a9510SRong-En Fan
5853*4a1a9510SRong-En Fan              <dd>
5854*4a1a9510SRong-En Fan                <p>Controls whether validation occurs on every
5855*4a1a9510SRong-En Fan                exit, or only after the field is modified. Normally
5856*4a1a9510SRong-En Fan                the latter is true. Setting O_PASSOK may be useful
5857*4a1a9510SRong-En Fan                if your field's validation function may change
5858*4a1a9510SRong-En Fan                during forms processing.</p>
5859*4a1a9510SRong-En Fan              </dd>
5860*4a1a9510SRong-En Fan
5861*4a1a9510SRong-En Fan              <dt>O_STATIC</dt>
5862*4a1a9510SRong-En Fan
5863*4a1a9510SRong-En Fan              <dd>
5864*4a1a9510SRong-En Fan                <p>Controls whether the field is fixed to its
5865*4a1a9510SRong-En Fan                initial dimensions. If you turn this off, the field
5866*4a1a9510SRong-En Fan                becomes dynamic and will stretch to fit entered
5867*4a1a9510SRong-En Fan                data.</p>
5868*4a1a9510SRong-En Fan              </dd>
5869*4a1a9510SRong-En Fan            </dl>
5870*4a1a9510SRong-En Fan          </div>
5871*4a1a9510SRong-En Fan
5872*4a1a9510SRong-En Fan          <p>A field's options cannot be changed while the field is
5873*4a1a9510SRong-En Fan          currently selected. However, options may be changed on
5874*4a1a9510SRong-En Fan          posted fields that are not current.</p>
5875*4a1a9510SRong-En Fan
5876*4a1a9510SRong-En Fan          <p>The option values are bit-masks and can be composed
5877*4a1a9510SRong-En Fan          with logical-or in the obvious way. You have seen the
5878*4a1a9510SRong-En Fan          usage of switching off O_AUTOSKIP option. The following
5879*4a1a9510SRong-En Fan          example clarifies usage of some more options. Other
5880*4a1a9510SRong-En Fan          options are explained where appropriate.</p>
5881*4a1a9510SRong-En Fan
5882*4a1a9510SRong-En Fan          <div class="EXAMPLE">
5883*4a1a9510SRong-En Fan            <a name="FFOOP" id="FFOOP"></a>
5884*4a1a9510SRong-En Fan
5885*4a1a9510SRong-En Fan            <p><b>Example 27. Field Options Usage example</b></p>
5886*4a1a9510SRong-En Fan            <pre class="PROGRAMLISTING">
5887*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
5888*4a1a9510SRong-En Fan
5889*4a1a9510SRong-En Fan#define STARTX 15
5890*4a1a9510SRong-En Fan#define STARTY 4
5891*4a1a9510SRong-En Fan#define WIDTH 25
5892*4a1a9510SRong-En Fan
5893*4a1a9510SRong-En Fan#define N_FIELDS 3
5894*4a1a9510SRong-En Fan
5895*4a1a9510SRong-En Fanint main()
5896*4a1a9510SRong-En Fan{       FIELD *field[N_FIELDS];
5897*4a1a9510SRong-En Fan        FORM  *my_form;
5898*4a1a9510SRong-En Fan        int ch, i;
5899*4a1a9510SRong-En Fan
5900*4a1a9510SRong-En Fan        /* Initialize curses */
5901*4a1a9510SRong-En Fan        initscr();
5902*4a1a9510SRong-En Fan        cbreak();
5903*4a1a9510SRong-En Fan        noecho();
5904*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
5905*4a1a9510SRong-En Fan
5906*4a1a9510SRong-En Fan        /* Initialize the fields */
5907*4a1a9510SRong-En Fan        for(i = 0; i &lt; N_FIELDS - 1; ++i)
5908*4a1a9510SRong-En Fan                field[i] = new_field(1, WIDTH, STARTY + i * 2, STARTX, 0, 0);
5909*4a1a9510SRong-En Fan        field[N_FIELDS - 1] = NULL;
5910*4a1a9510SRong-En Fan
5911*4a1a9510SRong-En Fan        /* Set field options */
5912*4a1a9510SRong-En Fan        set_field_back(field[1], A_UNDERLINE);  /* Print a line for the option  */
5913*4a1a9510SRong-En Fan
5914*4a1a9510SRong-En Fan        field_opts_off(field[0], O_ACTIVE); /* This field is a static label */
5915*4a1a9510SRong-En Fan        field_opts_off(field[1], O_PUBLIC); /* This filed is like a password field*/
5916*4a1a9510SRong-En Fan        field_opts_off(field[1], O_AUTOSKIP); /* To avoid entering the same field */
5917*4a1a9510SRong-En Fan                                              /* after last character is entered */
5918*4a1a9510SRong-En Fan
5919*4a1a9510SRong-En Fan        /* Create the form and post it */
5920*4a1a9510SRong-En Fan        my_form = new_form(field);
5921*4a1a9510SRong-En Fan        post_form(my_form);
5922*4a1a9510SRong-En Fan        refresh();
5923*4a1a9510SRong-En Fan
5924*4a1a9510SRong-En Fan        set_field_just(field[0], JUSTIFY_CENTER); /* Center Justification */
5925*4a1a9510SRong-En Fan        set_field_buffer(field[0], 0, "This is a static Field");
5926*4a1a9510SRong-En Fan                                                  /* Initialize the field  */
5927*4a1a9510SRong-En Fan        mvprintw(STARTY, STARTX - 10, "Field 1:");
5928*4a1a9510SRong-En Fan        mvprintw(STARTY + 2, STARTX - 10, "Field 2:");
5929*4a1a9510SRong-En Fan        refresh();
5930*4a1a9510SRong-En Fan
5931*4a1a9510SRong-En Fan        /* Loop through to get user requests */
5932*4a1a9510SRong-En Fan        while((ch = getch()) != KEY_F(1))
5933*4a1a9510SRong-En Fan        {       switch(ch)
5934*4a1a9510SRong-En Fan                {       case KEY_DOWN:
5935*4a1a9510SRong-En Fan                                /* Go to next field */
5936*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_NEXT_FIELD);
5937*4a1a9510SRong-En Fan                                /* Go to the end of the present buffer */
5938*4a1a9510SRong-En Fan                                /* Leaves nicely at the last character */
5939*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5940*4a1a9510SRong-En Fan                                break;
5941*4a1a9510SRong-En Fan                        case KEY_UP:
5942*4a1a9510SRong-En Fan                                /* Go to previous field */
5943*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_PREV_FIELD);
5944*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
5945*4a1a9510SRong-En Fan                                break;
5946*4a1a9510SRong-En Fan                        default:
5947*4a1a9510SRong-En Fan                                /* If this is a normal character, it gets */
5948*4a1a9510SRong-En Fan                                /* Printed                                */
5949*4a1a9510SRong-En Fan                                form_driver(my_form, ch);
5950*4a1a9510SRong-En Fan                                break;
5951*4a1a9510SRong-En Fan                }
5952*4a1a9510SRong-En Fan        }
5953*4a1a9510SRong-En Fan
5954*4a1a9510SRong-En Fan        /* Un post form and free the memory */
5955*4a1a9510SRong-En Fan        unpost_form(my_form);
5956*4a1a9510SRong-En Fan        free_form(my_form);
5957*4a1a9510SRong-En Fan        free_field(field[0]);
5958*4a1a9510SRong-En Fan        free_field(field[1]);
5959*4a1a9510SRong-En Fan
5960*4a1a9510SRong-En Fan        endwin();
5961*4a1a9510SRong-En Fan        return 0;
5962*4a1a9510SRong-En Fan}</span>
5963*4a1a9510SRong-En Fan</pre>
5964*4a1a9510SRong-En Fan          </div>
5965*4a1a9510SRong-En Fan
5966*4a1a9510SRong-En Fan          <p>This example, though useless, shows the usage of
5967*4a1a9510SRong-En Fan          options. If used properly, they can present information
5968*4a1a9510SRong-En Fan          very effectively in a form. The second field being not
5969*4a1a9510SRong-En Fan          O_PUBLIC, does not show the characters you are
5970*4a1a9510SRong-En Fan          typing.</p>
5971*4a1a9510SRong-En Fan        </div>
5972*4a1a9510SRong-En Fan
5973*4a1a9510SRong-En Fan        <div class="SECT3">
5974*4a1a9510SRong-En Fan          <hr>
5975*4a1a9510SRong-En Fan
5976*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="FIELDSTATUS" id=
5977*4a1a9510SRong-En Fan          "FIELDSTATUS">18.3.6. Field Status</a></h4>
5978*4a1a9510SRong-En Fan
5979*4a1a9510SRong-En Fan          <p>The field status specifies whether the field has got
5980*4a1a9510SRong-En Fan          edited or not. It is initially set to FALSE and when user
5981*4a1a9510SRong-En Fan          enters something and the data buffer gets modified it
5982*4a1a9510SRong-En Fan          becomes TRUE. So a field's status can be queried to find
5983*4a1a9510SRong-En Fan          out whether it has been modified or not. The following
5984*4a1a9510SRong-En Fan          functions can assist in those operations.</p>
5985*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
5986*4a1a9510SRong-En Fanint set_field_status(FIELD *field,      /* field to alter */
5987*4a1a9510SRong-En Fan                   int status);         /* status to set */
5988*4a1a9510SRong-En Fan
5989*4a1a9510SRong-En Fanint field_status(FIELD *field);         /* fetch status of field */
5990*4a1a9510SRong-En Fan</pre>
5991*4a1a9510SRong-En Fan
5992*4a1a9510SRong-En Fan          <p>It's better to check the field's status only after
5993*4a1a9510SRong-En Fan          after leaving the field, as data buffer might not have
5994*4a1a9510SRong-En Fan          been updated yet as the validation is still due. To
5995*4a1a9510SRong-En Fan          guarantee that right status is returned, call
5996*4a1a9510SRong-En Fan          field_status() either (1) in the field's exit validation
5997*4a1a9510SRong-En Fan          check routine, (2) from the field's or form's
5998*4a1a9510SRong-En Fan          initialization or termination hooks, or (3) just after a
5999*4a1a9510SRong-En Fan          REQ_VALIDATION request has been processed by the forms
6000*4a1a9510SRong-En Fan          driver</p>
6001*4a1a9510SRong-En Fan        </div>
6002*4a1a9510SRong-En Fan
6003*4a1a9510SRong-En Fan        <div class="SECT3">
6004*4a1a9510SRong-En Fan          <hr>
6005*4a1a9510SRong-En Fan
6006*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="FIELDUSERPTR" id=
6007*4a1a9510SRong-En Fan          "FIELDUSERPTR">18.3.7. Field User Pointer</a></h4>
6008*4a1a9510SRong-En Fan
6009*4a1a9510SRong-En Fan          <p>Every field structure contains one pointer that can be
6010*4a1a9510SRong-En Fan          used by the user for various purposes. It is not touched
6011*4a1a9510SRong-En Fan          by forms library and can be used for any purpose by the
6012*4a1a9510SRong-En Fan          user. The following functions set and fetch user
6013*4a1a9510SRong-En Fan          pointer.</p>
6014*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
6015*4a1a9510SRong-En Fanint set_field_userptr(FIELD *field,
6016*4a1a9510SRong-En Fan           char *userptr);      /* the user pointer you wish to associate */
6017*4a1a9510SRong-En Fan                                /* with the field    */
6018*4a1a9510SRong-En Fan
6019*4a1a9510SRong-En Fanchar *field_userptr(FIELD *field);      /* fetch user pointer of the field */
6020*4a1a9510SRong-En Fan</pre>
6021*4a1a9510SRong-En Fan        </div>
6022*4a1a9510SRong-En Fan
6023*4a1a9510SRong-En Fan        <div class="SECT3">
6024*4a1a9510SRong-En Fan          <hr>
6025*4a1a9510SRong-En Fan
6026*4a1a9510SRong-En Fan          <h4 class="SECT3"><a name="VARIABLESIZEFIELDS" id=
6027*4a1a9510SRong-En Fan          "VARIABLESIZEFIELDS">18.3.8. Variable-Sized
6028*4a1a9510SRong-En Fan          Fields</a></h4>
6029*4a1a9510SRong-En Fan
6030*4a1a9510SRong-En Fan          <p>If you want a dynamically changing field with variable
6031*4a1a9510SRong-En Fan          width, this is the feature you want to put to full use.
6032*4a1a9510SRong-En Fan          This will allow the user to enter more data than the
6033*4a1a9510SRong-En Fan          original size of the field and let the field grow.
6034*4a1a9510SRong-En Fan          According to the field orientation it will scroll
6035*4a1a9510SRong-En Fan          horizontally or vertically to incorporate the new
6036*4a1a9510SRong-En Fan          data.</p>
6037*4a1a9510SRong-En Fan
6038*4a1a9510SRong-En Fan          <p>To make a field dynamically growable, the option
6039*4a1a9510SRong-En Fan          O_STATIC should be turned off. This can be done with
6040*4a1a9510SRong-En Fan          a</p>
6041*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
6042*4a1a9510SRong-En Fan    field_opts_off(field_pointer, O_STATIC);
6043*4a1a9510SRong-En Fan</pre>
6044*4a1a9510SRong-En Fan
6045*4a1a9510SRong-En Fan          <p>But it's usually not advisable to allow a field to
6046*4a1a9510SRong-En Fan          grow infinitely. You can set a maximum limit to the
6047*4a1a9510SRong-En Fan          growth of the field with</p>
6048*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
6049*4a1a9510SRong-En Fanint set_max_field(FIELD *field,    /* Field on which to operate */
6050*4a1a9510SRong-En Fan                  int max_growth); /* maximum growth allowed for the field */
6051*4a1a9510SRong-En Fan</pre>
6052*4a1a9510SRong-En Fan
6053*4a1a9510SRong-En Fan          <p>The field info for a dynamically growable field can be
6054*4a1a9510SRong-En Fan          retrieved by</p>
6055*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
6056*4a1a9510SRong-En Fanint dynamic_field_info( FIELD *field,     /* Field on which to operate */
6057*4a1a9510SRong-En Fan            int   *prows,     /* number of rows will be filled in this */
6058*4a1a9510SRong-En Fan            int   *pcols,     /* number of columns will be filled in this*/
6059*4a1a9510SRong-En Fan            int   *pmax)      /* maximum allowable growth will be filled */
6060*4a1a9510SRong-En Fan                              /* in this */
6061*4a1a9510SRong-En Fan</pre>Though field_info work as usual, it is advisable to use this
6062*4a1a9510SRong-En Fanfunction to get the proper attributes of a dynamically growable
6063*4a1a9510SRong-En Fanfield.
6064*4a1a9510SRong-En Fan
6065*4a1a9510SRong-En Fan          <p>Recall the library routine new_field; a new field
6066*4a1a9510SRong-En Fan          created with height set to one will be defined to be a
6067*4a1a9510SRong-En Fan          one line field. A new field created with height greater
6068*4a1a9510SRong-En Fan          than one will be defined to be a multi line field.</p>
6069*4a1a9510SRong-En Fan
6070*4a1a9510SRong-En Fan          <p>A one line field with O_STATIC turned off (dynamically
6071*4a1a9510SRong-En Fan          growable field) will contain a single fixed row, but the
6072*4a1a9510SRong-En Fan          number of columns can increase if the user enters more
6073*4a1a9510SRong-En Fan          data than the initial field will hold. The number of
6074*4a1a9510SRong-En Fan          columns displayed will remain fixed and the additional
6075*4a1a9510SRong-En Fan          data will scroll horizontally.</p>
6076*4a1a9510SRong-En Fan
6077*4a1a9510SRong-En Fan          <p>A multi line field with O_STATIC turned off
6078*4a1a9510SRong-En Fan          (dynamically growable field) will contain a fixed number
6079*4a1a9510SRong-En Fan          of columns, but the number of rows can increase if the
6080*4a1a9510SRong-En Fan          user enters more data than the initial field will hold.
6081*4a1a9510SRong-En Fan          The number of rows displayed will remain fixed and the
6082*4a1a9510SRong-En Fan          additional data will scroll vertically.</p>
6083*4a1a9510SRong-En Fan
6084*4a1a9510SRong-En Fan          <p>The above two paragraphs pretty much describe a
6085*4a1a9510SRong-En Fan          dynamically growable field's behavior. The way other
6086*4a1a9510SRong-En Fan          parts of forms library behaves is described below:</p>
6087*4a1a9510SRong-En Fan
6088*4a1a9510SRong-En Fan          <ol type="1">
6089*4a1a9510SRong-En Fan            <li>
6090*4a1a9510SRong-En Fan              <p>The field option O_AUTOSKIP will be ignored if the
6091*4a1a9510SRong-En Fan              option O_STATIC is off and there is no maximum growth
6092*4a1a9510SRong-En Fan              specified for the field. Currently, O_AUTOSKIP
6093*4a1a9510SRong-En Fan              generates an automatic REQ_NEXT_FIELD form driver
6094*4a1a9510SRong-En Fan              request when the user types in the last character
6095*4a1a9510SRong-En Fan              position of a field. On a growable field with no
6096*4a1a9510SRong-En Fan              maximum growth specified, there is no last character
6097*4a1a9510SRong-En Fan              position. If a maximum growth is specified, the
6098*4a1a9510SRong-En Fan              O_AUTOSKIP option will work as normal if the field
6099*4a1a9510SRong-En Fan              has grown to its maximum size.</p>
6100*4a1a9510SRong-En Fan            </li>
6101*4a1a9510SRong-En Fan
6102*4a1a9510SRong-En Fan            <li>
6103*4a1a9510SRong-En Fan              <p>The field justification will be ignored if the
6104*4a1a9510SRong-En Fan              option O_STATIC is off. Currently, set_field_just can
6105*4a1a9510SRong-En Fan              be used to JUSTIFY_LEFT, JUSTIFY_RIGHT,
6106*4a1a9510SRong-En Fan              JUSTIFY_CENTER the contents of a one line field. A
6107*4a1a9510SRong-En Fan              growable one line field will, by definition, grow and
6108*4a1a9510SRong-En Fan              scroll horizontally and may contain more data than
6109*4a1a9510SRong-En Fan              can be justified. The return from field_just will be
6110*4a1a9510SRong-En Fan              unchanged.</p>
6111*4a1a9510SRong-En Fan            </li>
6112*4a1a9510SRong-En Fan
6113*4a1a9510SRong-En Fan            <li>
6114*4a1a9510SRong-En Fan              <p>The overloaded form driver request REQ_NEW_LINE
6115*4a1a9510SRong-En Fan              will operate the same way regardless of the
6116*4a1a9510SRong-En Fan              O_NL_OVERLOAD form option if the field option
6117*4a1a9510SRong-En Fan              O_STATIC is off and there is no maximum growth
6118*4a1a9510SRong-En Fan              specified for the field. Currently, if the form
6119*4a1a9510SRong-En Fan              option O_NL_OVERLOAD is on, REQ_NEW_LINE implicitly
6120*4a1a9510SRong-En Fan              generates a REQ_NEXT_FIELD if called from the last
6121*4a1a9510SRong-En Fan              line of a field. If a field can grow without bound,
6122*4a1a9510SRong-En Fan              there is no last line, so REQ_NEW_LINE will never
6123*4a1a9510SRong-En Fan              implicitly generate a REQ_NEXT_FIELD. If a maximum
6124*4a1a9510SRong-En Fan              growth limit is specified and the O_NL_OVERLOAD form
6125*4a1a9510SRong-En Fan              option is on, REQ_NEW_LINE will only implicitly
6126*4a1a9510SRong-En Fan              generate REQ_NEXT_FIELD if the field has grown to its
6127*4a1a9510SRong-En Fan              maximum size and the user is on the last line.</p>
6128*4a1a9510SRong-En Fan            </li>
6129*4a1a9510SRong-En Fan
6130*4a1a9510SRong-En Fan            <li>
6131*4a1a9510SRong-En Fan              <p>The library call dup_field will work as usual; it
6132*4a1a9510SRong-En Fan              will duplicate the field, including the current
6133*4a1a9510SRong-En Fan              buffer size and contents of the field being
6134*4a1a9510SRong-En Fan              duplicated. Any specified maximum growth will also be
6135*4a1a9510SRong-En Fan              duplicated.</p>
6136*4a1a9510SRong-En Fan            </li>
6137*4a1a9510SRong-En Fan
6138*4a1a9510SRong-En Fan            <li>
6139*4a1a9510SRong-En Fan              <p>The library call link_field will work as usual; it
6140*4a1a9510SRong-En Fan              will duplicate all field attributes and share buffers
6141*4a1a9510SRong-En Fan              with the field being linked. If the O_STATIC field
6142*4a1a9510SRong-En Fan              option is subsequently changed by a field sharing
6143*4a1a9510SRong-En Fan              buffers, how the system reacts to an attempt to enter
6144*4a1a9510SRong-En Fan              more data into the field than the buffer will
6145*4a1a9510SRong-En Fan              currently hold will depend on the setting of the
6146*4a1a9510SRong-En Fan              option in the current field.</p>
6147*4a1a9510SRong-En Fan            </li>
6148*4a1a9510SRong-En Fan
6149*4a1a9510SRong-En Fan            <li>
6150*4a1a9510SRong-En Fan              <p>The library call field_info will work as usual;
6151*4a1a9510SRong-En Fan              the variable nrow will contain the value of the
6152*4a1a9510SRong-En Fan              original call to new_field. The user should use
6153*4a1a9510SRong-En Fan              dynamic_field_info, described above, to query the
6154*4a1a9510SRong-En Fan              current size of the buffer.</p>
6155*4a1a9510SRong-En Fan            </li>
6156*4a1a9510SRong-En Fan          </ol>
6157*4a1a9510SRong-En Fan
6158*4a1a9510SRong-En Fan          <p>Some of the above points make sense only after
6159*4a1a9510SRong-En Fan          explaining form driver. We will be looking into that in
6160*4a1a9510SRong-En Fan          next few sections.</p>
6161*4a1a9510SRong-En Fan        </div>
6162*4a1a9510SRong-En Fan      </div>
6163*4a1a9510SRong-En Fan
6164*4a1a9510SRong-En Fan      <div class="SECT2">
6165*4a1a9510SRong-En Fan        <hr>
6166*4a1a9510SRong-En Fan
6167*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="FORMWINDOWS" id=
6168*4a1a9510SRong-En Fan        "FORMWINDOWS">18.4. Form Windows</a></h3>
6169*4a1a9510SRong-En Fan
6170*4a1a9510SRong-En Fan        <p>The form windows concept is pretty much similar to menu
6171*4a1a9510SRong-En Fan        windows. Every form is associated with a main window and a
6172*4a1a9510SRong-En Fan        sub window. The form main window displays any title or
6173*4a1a9510SRong-En Fan        border associated or whatever the user wishes. Then the sub
6174*4a1a9510SRong-En Fan        window contains all the fields and displays them according
6175*4a1a9510SRong-En Fan        to their position. This gives the flexibility of
6176*4a1a9510SRong-En Fan        manipulating fancy form displaying very easily.</p>
6177*4a1a9510SRong-En Fan
6178*4a1a9510SRong-En Fan        <p>Since this is pretty much similar to menu windows, I am
6179*4a1a9510SRong-En Fan        providing an example with out much explanation. The
6180*4a1a9510SRong-En Fan        functions are similar and they work the same way.</p>
6181*4a1a9510SRong-En Fan
6182*4a1a9510SRong-En Fan        <div class="EXAMPLE">
6183*4a1a9510SRong-En Fan          <a name="FFOWI" id="FFOWI"></a>
6184*4a1a9510SRong-En Fan
6185*4a1a9510SRong-En Fan          <p><b>Example 28. Form Windows Example</b></p>
6186*4a1a9510SRong-En Fan          <pre class="PROGRAMLISTING">
6187*4a1a9510SRong-En Fan<span class="INLINEMEDIAOBJECT">#include &lt;form.h&gt;
6188*4a1a9510SRong-En Fan
6189*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
6190*4a1a9510SRong-En Fan
6191*4a1a9510SRong-En Fanint main()
6192*4a1a9510SRong-En Fan{
6193*4a1a9510SRong-En Fan        FIELD *field[3];
6194*4a1a9510SRong-En Fan        FORM  *my_form;
6195*4a1a9510SRong-En Fan        WINDOW *my_form_win;
6196*4a1a9510SRong-En Fan        int ch, rows, cols;
6197*4a1a9510SRong-En Fan
6198*4a1a9510SRong-En Fan        /* Initialize curses */
6199*4a1a9510SRong-En Fan        initscr();
6200*4a1a9510SRong-En Fan        start_color();
6201*4a1a9510SRong-En Fan        cbreak();
6202*4a1a9510SRong-En Fan        noecho();
6203*4a1a9510SRong-En Fan        keypad(stdscr, TRUE);
6204*4a1a9510SRong-En Fan
6205*4a1a9510SRong-En Fan        /* Initialize few color pairs */
6206*4a1a9510SRong-En Fan        init_pair(1, COLOR_RED, COLOR_BLACK);
6207*4a1a9510SRong-En Fan
6208*4a1a9510SRong-En Fan        /* Initialize the fields */
6209*4a1a9510SRong-En Fan        field[0] = new_field(1, 10, 6, 1, 0, 0);
6210*4a1a9510SRong-En Fan        field[1] = new_field(1, 10, 8, 1, 0, 0);
6211*4a1a9510SRong-En Fan        field[2] = NULL;
6212*4a1a9510SRong-En Fan
6213*4a1a9510SRong-En Fan        /* Set field options */
6214*4a1a9510SRong-En Fan        set_field_back(field[0], A_UNDERLINE);
6215*4a1a9510SRong-En Fan        field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */
6216*4a1a9510SRong-En Fan                                              /* Field is filled up             */
6217*4a1a9510SRong-En Fan        set_field_back(field[1], A_UNDERLINE);
6218*4a1a9510SRong-En Fan        field_opts_off(field[1], O_AUTOSKIP);
6219*4a1a9510SRong-En Fan
6220*4a1a9510SRong-En Fan        /* Create the form and post it */
6221*4a1a9510SRong-En Fan        my_form = new_form(field);
6222*4a1a9510SRong-En Fan
6223*4a1a9510SRong-En Fan        /* Calculate the area required for the form */
6224*4a1a9510SRong-En Fan        scale_form(my_form, &amp;rows, &amp;cols);
6225*4a1a9510SRong-En Fan
6226*4a1a9510SRong-En Fan        /* Create the window to be associated with the form */
6227*4a1a9510SRong-En Fan        my_form_win = newwin(rows + 4, cols + 4, 4, 4);
6228*4a1a9510SRong-En Fan        keypad(my_form_win, TRUE);
6229*4a1a9510SRong-En Fan
6230*4a1a9510SRong-En Fan        /* Set main window and sub window */
6231*4a1a9510SRong-En Fan        set_form_win(my_form, my_form_win);
6232*4a1a9510SRong-En Fan        set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2));
6233*4a1a9510SRong-En Fan
6234*4a1a9510SRong-En Fan        /* Print a border around the main window and print a title */
6235*4a1a9510SRong-En Fan        box(my_form_win, 0, 0);
6236*4a1a9510SRong-En Fan        print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1));
6237*4a1a9510SRong-En Fan
6238*4a1a9510SRong-En Fan        post_form(my_form);
6239*4a1a9510SRong-En Fan        wrefresh(my_form_win);
6240*4a1a9510SRong-En Fan
6241*4a1a9510SRong-En Fan        mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
6242*4a1a9510SRong-En Fan        refresh();
6243*4a1a9510SRong-En Fan
6244*4a1a9510SRong-En Fan        /* Loop through to get user requests */
6245*4a1a9510SRong-En Fan        while((ch = wgetch(my_form_win)) != KEY_F(1))
6246*4a1a9510SRong-En Fan        {       switch(ch)
6247*4a1a9510SRong-En Fan                {       case KEY_DOWN:
6248*4a1a9510SRong-En Fan                                /* Go to next field */
6249*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_NEXT_FIELD);
6250*4a1a9510SRong-En Fan                                /* Go to the end of the present buffer */
6251*4a1a9510SRong-En Fan                                /* Leaves nicely at the last character */
6252*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
6253*4a1a9510SRong-En Fan                                break;
6254*4a1a9510SRong-En Fan                        case KEY_UP:
6255*4a1a9510SRong-En Fan                                /* Go to previous field */
6256*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_PREV_FIELD);
6257*4a1a9510SRong-En Fan                                form_driver(my_form, REQ_END_LINE);
6258*4a1a9510SRong-En Fan                                break;
6259*4a1a9510SRong-En Fan                        default:
6260*4a1a9510SRong-En Fan                                /* If this is a normal character, it gets */
6261*4a1a9510SRong-En Fan                                /* Printed                                */
6262*4a1a9510SRong-En Fan                                form_driver(my_form, ch);
6263*4a1a9510SRong-En Fan                                break;
6264*4a1a9510SRong-En Fan                }
6265*4a1a9510SRong-En Fan        }
6266*4a1a9510SRong-En Fan
6267*4a1a9510SRong-En Fan        /* Un post form and free the memory */
6268*4a1a9510SRong-En Fan        unpost_form(my_form);
6269*4a1a9510SRong-En Fan        free_form(my_form);
6270*4a1a9510SRong-En Fan        free_field(field[0]);
6271*4a1a9510SRong-En Fan        free_field(field[1]);
6272*4a1a9510SRong-En Fan
6273*4a1a9510SRong-En Fan        endwin();
6274*4a1a9510SRong-En Fan        return 0;
6275*4a1a9510SRong-En Fan}
6276*4a1a9510SRong-En Fan
6277*4a1a9510SRong-En Fanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
6278*4a1a9510SRong-En Fan{       int length, x, y;
6279*4a1a9510SRong-En Fan        float temp;
6280*4a1a9510SRong-En Fan
6281*4a1a9510SRong-En Fan        if(win == NULL)
6282*4a1a9510SRong-En Fan                win = stdscr;
6283*4a1a9510SRong-En Fan        getyx(win, y, x);
6284*4a1a9510SRong-En Fan        if(startx != 0)
6285*4a1a9510SRong-En Fan                x = startx;
6286*4a1a9510SRong-En Fan        if(starty != 0)
6287*4a1a9510SRong-En Fan                y = starty;
6288*4a1a9510SRong-En Fan        if(width == 0)
6289*4a1a9510SRong-En Fan                width = 80;
6290*4a1a9510SRong-En Fan
6291*4a1a9510SRong-En Fan        length = strlen(string);
6292*4a1a9510SRong-En Fan        temp = (width - length)/ 2;
6293*4a1a9510SRong-En Fan        x = startx + (int)temp;
6294*4a1a9510SRong-En Fan        wattron(win, color);
6295*4a1a9510SRong-En Fan        mvwprintw(win, y, x, "%s", string);
6296*4a1a9510SRong-En Fan        wattroff(win, color);
6297*4a1a9510SRong-En Fan        refresh();
6298*4a1a9510SRong-En Fan}</span>
6299*4a1a9510SRong-En Fan</pre>
6300*4a1a9510SRong-En Fan        </div>
6301*4a1a9510SRong-En Fan      </div>
6302*4a1a9510SRong-En Fan
6303*4a1a9510SRong-En Fan      <div class="SECT2">
6304*4a1a9510SRong-En Fan        <hr>
6305*4a1a9510SRong-En Fan
6306*4a1a9510SRong-En Fan        <h3 class="SECT2"><a name="FILEDVALIDATE" id=
6307*4a1a9510SRong-En Fan        "FILEDVALIDATE">18.5. Field Validation</a></h3>
6308*4a1a9510SRong-En Fan
6309*4a1a9510SRong-En Fan        <p>By default, a field will accept any data input by the
6310*4a1a9510SRong-En Fan        user. It is possible to attach validation to the field.
6311*4a1a9510SRong-En Fan        Then any attempt by the user to leave the field, while it
6312*4a1a9510SRong-En Fan        contains data that doesn't match the validation type will
6313*4a1a9510SRong-En Fan        fail. Some validation types also have a character-validity
6314*4a1a9510SRong-En Fan        check for each time a character is entered in the
6315*4a1a9510SRong-En Fan        field.</p>
6316*4a1a9510SRong-En Fan
6317*4a1a9510SRong-En Fan        <p>Validation can be attached to a field with the following
6318*4a1a9510SRong-En Fan        function.</p>
6319*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
6320*4a1a9510SRong-En Fanint set_field_type(FIELD *field,          /* field to alter */
6321*4a1a9510SRong-En Fan                   FIELDTYPE *ftype,      /* type to associate */
6322*4a1a9510SRong-En Fan                   ...);                  /* additional arguments*/
6323*4a1a9510SRong-En Fan</pre>Once set, the validation type for a field can be queried with
6324*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
6325*4a1a9510SRong-En FanFIELDTYPE *field_type(FIELD *field);      /* field to query */
6326*4a1a9510SRong-En Fan</pre>
6327*4a1a9510SRong-En Fan
6328*4a1a9510SRong-En Fan        <p>The form driver validates the data in a field only when
6329*4a1a9510SRong-En Fan        data is entered by the end-user. Validation does not occur
6330*4a1a9510SRong-En Fan        when</p>
6331*4a1a9510SRong-En Fan
6332*4a1a9510SRong-En Fan        <ul>
6333*4a1a9510SRong-En Fan          <li>
6334*4a1a9510SRong-En Fan            <p>the application program changes the field value by
6335*4a1a9510SRong-En Fan            calling set_field_buffer.</p>
6336*4a1a9510SRong-En Fan          </li>
6337*4a1a9510SRong-En Fan
6338*4a1a9510SRong-En Fan          <li>
6339*4a1a9510SRong-En Fan            <p>linked field values are changed indirectly -- by
6340*4a1a9510SRong-En Fan            changing the field to which they are linked</p>
6341*4a1a9510SRong-En Fan          </li>
6342*4a1a9510SRong-En Fan        </ul>
6343*4a1a9510SRong-En Fan
6344*4a1a9510SRong-En Fan        <p>The following are the pre-defined validation types. You
6345*4a1a9510SRong-En Fan        can also specify custom validation, though it's a bit
6346*4a1a9510SRong-En Fan        tricky and cumbersome.</p>
6347*4a1a9510SRong-En Fan
6348*4a1a9510SRong-En Fan        <h1 class="BRIDGEHEAD"><a name="AEN1069" id=
6349*4a1a9510SRong-En Fan        "AEN1069"></a>TYPE_ALPHA</h1>
6350*4a1a9510SRong-En Fan
6351*4a1a9510SRong-En Fan        <p>This field type accepts alphabetic data; no blanks, no
6352*4a1a9510SRong-En Fan        digits, no special characters (this is checked at
6353*4a1a9510SRong-En Fan        character-entry time). It is set up with:</p>
6354*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
6355*4a1a9510SRong-En Fanint set_field_type(FIELD *field,          /* field to alter */
6356*4a1a9510SRong-En Fan                   TYPE_ALPHA,            /* type to associate */
6357*4a1a9510SRong-En Fan                   int width);            /* minimum width of field */
6358*4a1a9510SRong-En Fan</pre>
6359*4a1a9510SRong-En Fan
6360*4a1a9510SRong-En Fan        <p>The width argument sets a minimum width of data. The
6361*4a1a9510SRong-En Fan        user has to enter at-least width number of characters
6362*4a1a9510SRong-En Fan        before he can leave the field. Typically you'll want to set
6363*4a1a9510SRong-En Fan        this to the field width; if it's greater than the field
6364*4a1a9510SRong-En Fan        width, the validation check will always fail. A minimum
6365*4a1a9510SRong-En Fan        width of zero makes field completion optional.</p>
6366*4a1a9510SRong-En Fan
6367*4a1a9510SRong-En Fan        <h1 class="BRIDGEHEAD"><a name="AEN1073" id=
6368*4a1a9510SRong-En Fan        "AEN1073"></a>TYPE_ALNUM</h1>
6369*4a1a9510SRong-En Fan
6370*4a1a9510SRong-En Fan        <p>This field type accepts alphabetic data and digits; no
6371*4a1a9510SRong-En Fan        blanks, no special characters (this is checked at
6372*4a1a9510SRong-En Fan        character-entry time). It is set up with:</p>
6373*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
6374*4a1a9510SRong-En Fanint set_field_type(FIELD *field,          /* field to alter */
6375*4a1a9510SRong-En Fan                   TYPE_ALNUM,            /* type to associate */
6376*4a1a9510SRong-En Fan                   int width);            /* minimum width of field */
6377*4a1a9510SRong-En Fan</pre>
6378*4a1a9510SRong-En Fan
6379*4a1a9510SRong-En Fan        <p>The width argument sets a minimum width of data. As with
6380*4a1a9510SRong-En Fan        TYPE_ALPHA, typically you'll want to set this to the field
6381*4a1a9510SRong-En Fan        width; if it's greater than the field width, the validation
6382*4a1a9510SRong-En Fan        check will always fail. A minimum width of zero makes field
6383*4a1a9510SRong-En Fan        completion optional.</p>
6384*4a1a9510SRong-En Fan
6385*4a1a9510SRong-En Fan        <h1 class="BRIDGEHEAD"><a name="AEN1077" id=
6386*4a1a9510SRong-En Fan        "AEN1077"></a>TYPE_ENUM</h1>
6387*4a1a9510SRong-En Fan
6388*4a1a9510SRong-En Fan        <p>This type allows you to restrict a field's values to be
6389*4a1a9510SRong-En Fan        among a specified set of string values (for example, the
6390*4a1a9510SRong-En Fan        two-letter postal codes for U.S. states). It is set up
6391*4a1a9510SRong-En Fan        with:</p>
6392*4a1a9510SRong-En Fan        <pre class="PROGRAMLISTING">
6393*4a1a9510SRong-En Fanint set_field_type(FIELD *field,          /* field to alter */
6394*4a1a9510SRong-En Fan                   TYPE_ENUM,             /* type to associate */
6395*4a1a9510SRong-En Fan                   char **valuelist;      /* list of possible values */
6396*4a1a9510SRong-En Fan                   int checkcase;         /* case-sensitive? */
6397*4a1a9510SRong-En Fan                   int checkunique);      /* must specify uniquely? */
6398*4a1a9510SRong-En Fan</pre>
6399*4a1a9510SRong-En Fan
6400*4a1a9510SRong-En Fan        <p>The valuelist parameter must point at a NULL-terminated
6401*4a1a9510SRong-En Fan        list of valid strings. The checkcase argument, if true,
6402*4a1a9510SRong-En Fan        makes comparison with the string case-sensitive.</p>
6403*4a1a9510SRong-En Fan
6404*4a1a9510SRong-En Fan        <p>When the user exits a TYPE_ENUM field, the validation
6405*4a1a9510SRong-En Fan        procedure tries to complete the data in the buffer to a
6406*4a1a9510SRong-En Fan        valid entry. If a complete choice string has been entered,
6407*4a1a9510SRong-En Fan        it is of course valid. But it is also possible to enter a
6408*4a1a9510SRong-En Fan        prefix of a valid string and have it completed for you.</p>
6409*4a1a9510SRong-En Fan
6410*4a1a9510SRong-En Fan        <p>By default, if you enter such a prefix and it matches
6411*4a1a9510SRong-En Fan        more than one value in the string list, the prefix will be
6412*4a1a9510SRong-En Fan        completed to the first matching value. But the checkunique
6413*4a1a9510SRong-En Fan        argument, if true, requires prefix matches to be unique in
6414        order to be valid.</p>
6415
6416        <p>The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests
6417        can be particularly useful with these fields.</p>
6418
6419        <h1 class="BRIDGEHEAD"><a name="AEN1084" id=
6420        "AEN1084"></a>TYPE_INTEGER</h1>
6421
6422        <p>This field type accepts an integer. It is set up as
6423        follows:</p>
6424        <pre class="PROGRAMLISTING">
6425int set_field_type(FIELD *field,          /* field to alter */
6426                   TYPE_INTEGER,          /* type to associate */
6427                   int padding,           /* # places to zero-pad to */
6428                   int vmin, int vmax);   /* valid range */
6429</pre>
6430
6431        <p>Valid characters consist of an optional leading minus
6432        and digits. The range check is performed on exit. If the
6433        range maximum is less than or equal to the minimum, the
6434        range is ignored.</p>
6435
6436        <p>If the value passes its range check, it is padded with
6437        as many leading zero digits as necessary to meet the
6438        padding argument.</p>
6439
6440        <p>A TYPE_INTEGER value buffer can conveniently be
6441        interpreted with the C library function atoi(3).</p>
6442
6443        <h1 class="BRIDGEHEAD"><a name="AEN1090" id=
6444        "AEN1090"></a>TYPE_NUMERIC</h1>
6445
6446        <p>This field type accepts a decimal number. It is set up
6447        as follows:</p>
6448        <pre class="PROGRAMLISTING">
6449int set_field_type(FIELD *field,          /* field to alter */
6450                   TYPE_NUMERIC,          /* type to associate */
6451                   int padding,           /* # places of precision */
6452                   int vmin, int vmax);   /* valid range */
6453</pre>
6454
6455        <p>Valid characters consist of an optional leading minus
6456        and digits. possibly including a decimal point. The range
6457        check is performed on exit. If the range maximum is less
6458        than or equal to the minimum, the range is ignored.</p>
6459
6460        <p>If the value passes its range check, it is padded with
6461        as many trailing zero digits as necessary to meet the
6462        padding argument.</p>
6463
6464        <p>A TYPE_NUMERIC value buffer can conveniently be
6465        interpreted with the C library function atof(3).</p>
6466
6467        <h1 class="BRIDGEHEAD"><a name="AEN1096" id=
6468        "AEN1096"></a>TYPE_REGEXP</h1>
6469
6470        <p>This field type accepts data matching a regular
6471        expression. It is set up as follows:</p>
6472        <pre class="PROGRAMLISTING">
6473int set_field_type(FIELD *field,          /* field to alter */
6474                   TYPE_REGEXP,           /* type to associate */
6475                   char *regexp);         /* expression to match */
6476</pre>
6477
6478        <p>The syntax for regular expressions is that of
6479        regcomp(3). The check for regular-expression match is
6480        performed on exit.</p>
6481      </div>
6482
6483      <div class="SECT2">
6484        <hr>
6485
6486        <h3 class="SECT2"><a name="FORMDRIVER" id=
6487        "FORMDRIVER">18.6. Form Driver: The work horse of the forms
6488        system</a></h3>
6489
6490        <p>As in the menu system, form_driver() plays a very
6491        important role in forms system. All types of requests to
6492        forms system should be funneled through form_driver().</p>
6493        <pre class="PROGRAMLISTING">
6494int form_driver(FORM *form,     /* form on which to operate     */
6495                int request)    /* form request code         */
6496</pre>
6497
6498        <p>As you have seen some of the examples above, you have to
6499        be in a loop looking for user input and then decide whether
6500        it's a field data or a form request. The form requests are
6501        then passed to form_driver() to do the work.</p>
6502
6503        <p>The requests roughly can be divided into following
6504        categories. Different requests and their usage is explained
6505        below:</p>
6506
6507        <div class="SECT3">
6508          <hr>
6509
6510          <h4 class="SECT3"><a name="PAGENAVREQ" id=
6511          "PAGENAVREQ">18.6.1. Page Navigation Requests</a></h4>
6512
6513          <p>These requests cause page-level moves through the
6514          form, triggering display of a new form screen. A form can
6515          be made of multiple pages. If you have a big form with
6516          lot of fields and logical sections, then you can divide
6517          the form into pages. The function set_new_page() to set a
6518          new page at the field specified.</p>
6519          <pre class="PROGRAMLISTING">
6520int set_new_page(FIELD *field,/* Field at which page break to be set or unset */
6521         bool new_page_flag); /* should be TRUE to put a break */
6522</pre>
6523
6524          <p>The following requests allow you to move to different
6525          pages</p>
6526
6527          <ul>
6528            <li>
6529              <p><span class="emphasis"><i class=
6530              "EMPHASIS">REQ_NEXT_PAGE</i></span> Move to the next
6531              form page.</p>
6532            </li>
6533
6534            <li>
6535              <p><span class="emphasis"><i class=
6536              "EMPHASIS">REQ_PREV_PAGE</i></span> Move to the
6537              previous form page.</p>
6538            </li>
6539
6540            <li>
6541              <p><span class="emphasis"><i class=
6542              "EMPHASIS">REQ_FIRST_PAGE</i></span> Move to the
6543              first form page.</p>
6544            </li>
6545
6546            <li>
6547              <p><span class="emphasis"><i class=
6548              "EMPHASIS">REQ_LAST_PAGE</i></span> Move to the last
6549              form page.</p>
6550            </li>
6551          </ul>
6552
6553          <p>These requests treat the list as cyclic; that is,
6554          REQ_NEXT_PAGE from the last page goes to the first, and
6555          REQ_PREV_PAGE from the first page goes to the last.</p>
6556        </div>
6557
6558        <div class="SECT3">
6559          <hr>
6560
6561          <h4 class="SECT3"><a name="INTERFIELDNAVREQ" id=
6562          "INTERFIELDNAVREQ">18.6.2. Inter-Field Navigation
6563          Requests</a></h4>
6564
6565          <p>These requests handle navigation between fields on the
6566          same page.</p>
6567
6568          <ul>
6569            <li>
6570              <p><span class="emphasis"><i class=
6571              "EMPHASIS">REQ_NEXT_FIELD</i></span> Move to next
6572              field.</p>
6573            </li>
6574
6575            <li>
6576              <p><span class="emphasis"><i class=
6577              "EMPHASIS">REQ_PREV_FIELD</i></span> Move to previous
6578              field.</p>
6579            </li>
6580
6581            <li>
6582              <p><span class="emphasis"><i class=
6583              "EMPHASIS">REQ_FIRST_FIELD</i></span> Move to the
6584              first field.</p>
6585            </li>
6586
6587            <li>
6588              <p><span class="emphasis"><i class=
6589              "EMPHASIS">REQ_LAST_FIELD</i></span> Move to the last
6590              field.</p>
6591            </li>
6592
6593            <li>
6594              <p><span class="emphasis"><i class=
6595              "EMPHASIS">REQ_SNEXT_FIELD</i></span> Move to sorted
6596              next field.</p>
6597            </li>
6598
6599            <li>
6600              <p><span class="emphasis"><i class=
6601              "EMPHASIS">REQ_SPREV_FIELD</i></span> Move to sorted
6602              previous field.</p>
6603            </li>
6604
6605            <li>
6606              <p><span class="emphasis"><i class=
6607              "EMPHASIS">REQ_SFIRST_FIELD</i></span> Move to the
6608              sorted first field.</p>
6609            </li>
6610
6611            <li>
6612              <p><span class="emphasis"><i class=
6613              "EMPHASIS">REQ_SLAST_FIELD</i></span> Move to the
6614              sorted last field.</p>
6615            </li>
6616
6617            <li>
6618              <p><span class="emphasis"><i class=
6619              "EMPHASIS">REQ_LEFT_FIELD</i></span> Move left to
6620              field.</p>
6621            </li>
6622
6623            <li>
6624              <p><span class="emphasis"><i class=
6625              "EMPHASIS">REQ_RIGHT_FIELD</i></span> Move right to
6626              field.</p>
6627            </li>
6628
6629            <li>
6630              <p><span class="emphasis"><i class=
6631              "EMPHASIS">REQ_UP_FIELD</i></span> Move up to
6632              field.</p>
6633            </li>
6634
6635            <li>
6636              <p><span class="emphasis"><i class=
6637              "EMPHASIS">REQ_DOWN_FIELD</i></span> Move down to
6638              field.</p>
6639            </li>
6640          </ul>
6641
6642          <p>These requests treat the list of fields on a page as
6643          cyclic; that is, REQ_NEXT_FIELD from the last field goes
6644          to the first, and REQ_PREV_FIELD from the first field
6645          goes to the last. The order of the fields for these (and
6646          the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is
6647          simply the order of the field pointers in the form array
6648          (as set up by new_form() or set_form_fields()</p>
6649
6650          <p>It is also possible to traverse the fields as if they
6651          had been sorted in screen-position order, so the sequence
6652          goes left-to-right and top-to-bottom. To do this, use the
6653          second group of four sorted-movement requests.</p>
6654
6655          <p>Finally, it is possible to move between fields using
6656          visual directions up, down, right, and left. To
6657          accomplish this, use the third group of four requests.
6658          Note, however, that the position of a form for purposes
6659          of these requests is its upper-left corner.</p>
6660
6661          <p>For example, suppose you have a multi-line field B,
6662          and two single-line fields A and C on the same line with
6663          B, with A to the left of B and C to the right of B. A
6664          REQ_MOVE_RIGHT from A will go to B only if A, B, and C
6665          all share the same first line; otherwise it will skip
6666          over B to C.</p>
6667        </div>
6668
6669        <div class="SECT3">
6670          <hr>
6671
6672          <h4 class="SECT3"><a name="INTRAFIELDNAVREQ" id=
6673          "INTRAFIELDNAVREQ">18.6.3. Intra-Field Navigation
6674          Requests</a></h4>
6675
6676          <p>These requests drive movement of the edit cursor
6677          within the currently selected field.</p>
6678
6679          <ul>
6680            <li>
6681              <p><span class="emphasis"><i class=
6682              "EMPHASIS">REQ_NEXT_CHAR</i></span> Move to next
6683              character.</p>
6684            </li>
6685
6686            <li>
6687              <p><span class="emphasis"><i class=
6688              "EMPHASIS">REQ_PREV_CHAR</i></span> Move to previous
6689              character.</p>
6690            </li>
6691
6692            <li>
6693              <p><span class="emphasis"><i class=
6694              "EMPHASIS">REQ_NEXT_LINE</i></span> Move to next
6695              line.</p>
6696            </li>
6697
6698            <li>
6699              <p><span class="emphasis"><i class=
6700              "EMPHASIS">REQ_PREV_LINE</i></span> Move to previous
6701              line.</p>
6702            </li>
6703
6704            <li>
6705              <p><span class="emphasis"><i class=
6706              "EMPHASIS">REQ_NEXT_WORD</i></span> Move to next
6707              word.</p>
6708            </li>
6709
6710            <li>
6711              <p><span class="emphasis"><i class=
6712              "EMPHASIS">REQ_PREV_WORD</i></span> Move to previous
6713              word.</p>
6714            </li>
6715
6716            <li>
6717              <p><span class="emphasis"><i class=
6718              "EMPHASIS">REQ_BEG_FIELD</i></span> Move to beginning
6719              of field.</p>
6720            </li>
6721
6722            <li>
6723              <p><span class="emphasis"><i class=
6724              "EMPHASIS">REQ_END_FIELD</i></span> Move to end of
6725              field.</p>
6726            </li>
6727
6728            <li>
6729              <p><span class="emphasis"><i class=
6730              "EMPHASIS">REQ_BEG_LINE</i></span> Move to beginning
6731              of line.</p>
6732            </li>
6733
6734            <li>
6735              <p><span class="emphasis"><i class=
6736              "EMPHASIS">REQ_END_LINE</i></span> Move to end of
6737              line.</p>
6738            </li>
6739
6740            <li>
6741              <p><span class="emphasis"><i class=
6742              "EMPHASIS">REQ_LEFT_CHAR</i></span> Move left in
6743              field.</p>
6744            </li>
6745
6746            <li>
6747              <p><span class="emphasis"><i class=
6748              "EMPHASIS">REQ_RIGHT_CHAR</i></span> Move right in
6749              field.</p>
6750            </li>
6751
6752            <li>
6753              <p><span class="emphasis"><i class=
6754              "EMPHASIS">REQ_UP_CHAR</i></span> Move up in
6755              field.</p>
6756            </li>
6757
6758            <li>
6759              <p><span class="emphasis"><i class=
6760              "EMPHASIS">REQ_DOWN_CHAR</i></span> Move down in
6761              field.</p>
6762            </li>
6763          </ul>
6764
6765          <p>Each word is separated from the previous and next
6766          characters by whitespace. The commands to move to
6767          beginning and end of line or field look for the first or
6768          last non-pad character in their ranges.</p>
6769        </div>
6770
6771        <div class="SECT3">
6772          <hr>
6773
6774          <h4 class="SECT3"><a name="SCROLLREQ" id=
6775          "SCROLLREQ">18.6.4. Scrolling Requests</a></h4>
6776
6777          <p>Fields that are dynamic and have grown and fields
6778          explicitly created with offscreen rows are scrollable.
6779          One-line fields scroll horizontally; multi-line fields
6780          scroll vertically. Most scrolling is triggered by editing
6781          and intra-field movement (the library scrolls the field
6782          to keep the cursor visible). It is possible to explicitly
6783          request scrolling with the following requests:</p>
6784
6785          <ul>
6786            <li>
6787              <p><span class="emphasis"><i class=
6788              "EMPHASIS">REQ_SCR_FLINE</i></span> Scroll vertically
6789              forward a line.</p>
6790            </li>
6791
6792            <li>
6793              <p><span class="emphasis"><i class=
6794              "EMPHASIS">REQ_SCR_BLINE</i></span> Scroll vertically
6795              backward a line.</p>
6796            </li>
6797
6798            <li>
6799              <p><span class="emphasis"><i class=
6800              "EMPHASIS">REQ_SCR_FPAGE</i></span> Scroll vertically
6801              forward a page.</p>
6802            </li>
6803
6804            <li>
6805              <p><span class="emphasis"><i class=
6806              "EMPHASIS">REQ_SCR_BPAGE</i></span> Scroll vertically
6807              backward a page.</p>
6808            </li>
6809
6810            <li>
6811              <p><span class="emphasis"><i class=
6812              "EMPHASIS">REQ_SCR_FHPAGE</i></span> Scroll
6813              vertically forward half a page.</p>
6814            </li>
6815
6816            <li>
6817              <p><span class="emphasis"><i class=
6818              "EMPHASIS">REQ_SCR_BHPAGE</i></span> Scroll
6819              vertically backward half a page.</p>
6820            </li>
6821
6822            <li>
6823              <p><span class="emphasis"><i class=
6824              "EMPHASIS">REQ_SCR_FCHAR</i></span> Scroll
6825              horizontally forward a character.</p>
6826            </li>
6827
6828            <li>
6829              <p><span class="emphasis"><i class=
6830              "EMPHASIS">REQ_SCR_BCHAR</i></span> Scroll
6831              horizontally backward a character.</p>
6832            </li>
6833
6834            <li>
6835              <p><span class="emphasis"><i class=
6836              "EMPHASIS">REQ_SCR_HFLINE</i></span> Scroll
6837              horizontally one field width forward.</p>
6838            </li>
6839
6840            <li>
6841              <p><span class="emphasis"><i class=
6842              "EMPHASIS">REQ_SCR_HBLINE</i></span> Scroll
6843              horizontally one field width backward.</p>
6844            </li>
6845
6846            <li>
6847              <p><span class="emphasis"><i class=
6848              "EMPHASIS">REQ_SCR_HFHALF</i></span> Scroll
6849              horizontally one half field width forward.</p>
6850            </li>
6851
6852            <li>
6853              <p><span class="emphasis"><i class=
6854              "EMPHASIS">REQ_SCR_HBHALF</i></span> Scroll
6855              horizontally one half field width backward.</p>
6856            </li>
6857          </ul>
6858
6859          <p>For scrolling purposes, a page of a field is the
6860          height of its visible part.</p>
6861        </div>
6862
6863        <div class="SECT3">
6864          <hr>
6865
6866          <h4 class="SECT3"><a name="EDITREQ" id="EDITREQ">18.6.5.
6867          Editing Requests</a></h4>
6868
6869          <p>When you pass the forms driver an ASCII character, it
6870          is treated as a request to add the character to the
6871          field's data buffer. Whether this is an insertion or a
6872          replacement depends on the field's edit mode (insertion
6873          is the default.</p>
6874
6875          <p>The following requests support editing the field and
6876          changing the edit mode:</p>
6877
6878          <ul>
6879            <li>
6880              <p><span class="emphasis"><i class=
6881              "EMPHASIS">REQ_INS_MODE</i></span> Set insertion
6882              mode.</p>
6883            </li>
6884
6885            <li>
6886              <p><span class="emphasis"><i class=
6887              "EMPHASIS">REQ_OVL_MODE</i></span> Set overlay
6888              mode.</p>
6889            </li>
6890
6891            <li>
6892              <p><span class="emphasis"><i class=
6893              "EMPHASIS">REQ_NEW_LINE</i></span> New line request
6894              (see below for explanation).</p>
6895            </li>
6896
6897            <li>
6898              <p><span class="emphasis"><i class=
6899              "EMPHASIS">REQ_INS_CHAR</i></span> Insert space at
6900              character location.</p>
6901            </li>
6902
6903            <li>
6904              <p><span class="emphasis"><i class=
6905              "EMPHASIS">REQ_INS_LINE</i></span> Insert blank line
6906              at character location.</p>
6907            </li>
6908
6909            <li>
6910              <p><span class="emphasis"><i class=
6911              "EMPHASIS">REQ_DEL_CHAR</i></span> Delete character
6912              at cursor.</p>
6913            </li>
6914
6915            <li>
6916              <p><span class="emphasis"><i class=
6917              "EMPHASIS">REQ_DEL_PREV</i></span> Delete previous
6918              word at cursor.</p>
6919            </li>
6920
6921            <li>
6922              <p><span class="emphasis"><i class=
6923              "EMPHASIS">REQ_DEL_LINE</i></span> Delete line at
6924              cursor.</p>
6925            </li>
6926
6927            <li>
6928              <p><span class="emphasis"><i class=
6929              "EMPHASIS">REQ_DEL_WORD</i></span> Delete word at
6930              cursor.</p>
6931            </li>
6932
6933            <li>
6934              <p><span class="emphasis"><i class=
6935              "EMPHASIS">REQ_CLR_EOL</i></span> Clear to end of
6936              line.</p>
6937            </li>
6938
6939            <li>
6940              <p><span class="emphasis"><i class=
6941              "EMPHASIS">REQ_CLR_EOF</i></span> Clear to end of
6942              field.</p>
6943            </li>
6944
6945            <li>
6946              <p><span class="emphasis"><i class=
6947              "EMPHASIS">REQ_CLR_FIELD</i></span> Clear entire
6948              field.</p>
6949            </li>
6950          </ul>
6951
6952          <p>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV
6953          requests is complicated and partly controlled by a pair
6954          of forms options. The special cases are triggered when
6955          the cursor is at the beginning of a field, or on the last
6956          line of the field.</p>
6957
6958          <p>First, we consider REQ_NEW_LINE:</p>
6959
6960          <p>The normal behavior of REQ_NEW_LINE in insert mode is
6961          to break the current line at the position of the edit
6962          cursor, inserting the portion of the current line after
6963          the cursor as a new line following the current and moving
6964          the cursor to the beginning of that new line (you may
6965          think of this as inserting a newline in the field
6966          buffer).</p>
6967
6968          <p>The normal behavior of REQ_NEW_LINE in overlay mode is
6969          to clear the current line from the position of the edit
6970          cursor to end of line. The cursor is then moved to the
6971          beginning of the next line.</p>
6972
6973          <p>However, REQ_NEW_LINE at the beginning of a field, or
6974          on the last line of a field, instead does a
6975          REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this special
6976          action is disabled.</p>
6977
6978          <p>Now, let us consider REQ_DEL_PREV:</p>
6979
6980          <p>The normal behavior of REQ_DEL_PREV is to delete the
6981          previous character. If insert mode is on, and the cursor
6982          is at the start of a line, and the text on that line will
6983          fit on the previous one, it instead appends the contents
6984          of the current line to the previous one and deletes the
6985          current line (you may think of this as deleting a newline
6986          from the field buffer).</p>
6987
6988          <p>However, REQ_DEL_PREV at the beginning of a field is
6989          instead treated as a REQ_PREV_FIELD.</p>
6990
6991          <p>If the O_BS_OVERLOAD option is off, this special
6992          action is disabled and the forms driver just returns
6993          E_REQUEST_DENIED.</p>
6994        </div>
6995
6996        <div class="SECT3">
6997          <hr>
6998
6999          <h4 class="SECT3"><a name="ORDERREQ" id=
7000          "ORDERREQ">18.6.6. Order Requests</a></h4>
7001
7002          <p>If the type of your field is ordered, and has
7003          associated functions for getting the next and previous
7004          values of the type from a given value, there are requests
7005          that can fetch that value into the field buffer:</p>
7006
7007          <ul>
7008            <li>
7009              <p><span class="emphasis"><i class=
7010              "EMPHASIS">REQ_NEXT_CHOICE</i></span> Place the
7011              successor value of the current value in the
7012              buffer.</p>
7013            </li>
7014
7015            <li>
7016              <p><span class="emphasis"><i class=
7017              "EMPHASIS">REQ_PREV_CHOICE</i></span> Place the
7018              predecessor value of the current value in the
7019              buffer.</p>
7020            </li>
7021          </ul>
7022
7023          <p>Of the built-in field types, only TYPE_ENUM has
7024          built-in successor and predecessor functions. When you
7025          define a field type of your own (see Custom Validation
7026          Types), you can associate our own ordering functions.</p>
7027        </div>
7028
7029        <div class="SECT3">
7030          <hr>
7031
7032          <h4 class="SECT3"><a name="APPLICCOMMANDS" id=
7033          "APPLICCOMMANDS">18.6.7. Application Commands</a></h4>
7034
7035          <p>Form requests are represented as integers above the
7036          curses value greater than KEY_MAX and less than or equal
7037          to the constant MAX_COMMAND. A value within this range
7038          gets ignored by form_driver(). So this can be used for
7039          any purpose by the application. It can be treated as an
7040          application specific action and take corresponding
7041          action.</p>
7042        </div>
7043      </div>
7044    </div>
7045
7046    <div class="SECT1">
7047      <hr>
7048
7049      <h2 class="SECT1"><a name="TOOLS" id="TOOLS">19. Tools and
7050      Widget Libraries</a></h2>
7051
7052      <p>Now that you have seen the capabilities of ncurses and its
7053      sister libraries, you are rolling your sleeves up and gearing
7054      for a project that heavily manipulates screen. But wait.. It
7055      can be pretty difficult to write and maintain complex GUI
7056      widgets in plain ncurses or even with the additional
7057      libraries. There are some ready-to-use tools and widget
7058      libraries that can be used instead of writing your own
7059      widgets. You can use some of them, get ideas from the code,
7060      or even extend them.</p>
7061
7062      <div class="SECT2">
7063        <hr>
7064
7065        <h3 class="SECT2"><a name="CDK" id="CDK">19.1. CDK (Curses
7066        Development Kit)</a></h3>
7067
7068        <p>In the author's words</p>
7069
7070        <p><span class="emphasis"><i class="EMPHASIS">CDK stands
7071        for 'Curses Development Kit' and it currently contains 21
7072        ready to use widgets which facilitate the speedy
7073        development of full screen curses programs.</i></span></p>
7074
7075        <p>The kit provides some useful widgets, which can be used
7076        in your programs directly. It's pretty well written and the
7077        documentation is very good. The examples in the examples
7078        directory can be a good place to start for beginners. The
7079        CDK can be downloaded from <a href=
7080        "https://invisible-island.net/cdk/" target=
7081        "_top">https://invisible-island.net/cdk/</a> . Follow the
7082        instructions in README file to install it.</p>
7083
7084        <div class="SECT3">
7085          <hr>
7086
7087          <h4 class="SECT3"><a name="WIDGETLIST" id=
7088          "WIDGETLIST">19.1.1. Widget List</a></h4>
7089
7090          <p>The following is the list of widgets provided with cdk
7091          and their description.</p>
7092          <pre class="PROGRAMLISTING">
7093Widget Type           Quick Description
7094===========================================================================
7095Alphalist             Allows a user to select from a list of words, with
7096                      the ability to narrow the search list by typing in a
7097                      few characters of the desired word.
7098Buttonbox             This creates a multiple button widget.
7099Calendar              Creates a little simple calendar widget.
7100Dialog                Prompts the user with a message, and the user
7101                      can pick an answer from the buttons provided.
7102Entry                 Allows the user to enter various types of information.
7103File Selector         A file selector built from Cdk base widgets. This
7104                      example shows how to create more complicated widgets
7105                      using the Cdk widget library.
7106Graph                 Draws a graph.
7107Histogram             Draws a histogram.
7108Item List             Creates a pop up field which allows the user to select
7109                      one of several choices in a small field. Very useful
7110                      for things like days of the week or month names.
7111Label                 Displays messages in a pop up box, or the label can be
7112                      considered part of the screen.
7113Marquee               Displays a message in a scrolling marquee.
7114Matrix                Creates a complex matrix with lots of options.
7115Menu                  Creates a pull-down menu interface.
7116Multiple Line Entry   A multiple line entry field. Very useful
7117                      for long fields. (like a description
7118                      field)
7119Radio List            Creates a radio button list.
7120Scale                 Creates a numeric scale. Used for allowing a user to
7121                      pick a numeric value and restrict them to a range of
7122                      values.
7123Scrolling List        Creates a scrolling list/menu list.
7124Scrolling Window      Creates a scrolling log file viewer. Can add
7125                      information into the window while its running.
7126                      A good widget for displaying the progress of
7127                      something. (akin to a console window)
7128Selection List        Creates a multiple option selection list.
7129Slider                Akin to the scale widget, this widget provides a
7130                      visual slide bar to represent the numeric value.
7131Template              Creates a entry field with character sensitive
7132                      positions. Used for pre-formatted fields like
7133                      dates and phone numbers.
7134Viewer                This is a file/information viewer. Very useful
7135                      when you need to display loads of information.
7136===========================================================================
7137</pre>
7138
7139          <p>A few of the widgets are modified by Thomas Dickey in
7140          recent versions.</p>
7141        </div>
7142
7143        <div class="SECT3">
7144          <hr>
7145
7146          <h4 class="SECT3"><a name="CDKATTRACT" id=
7147          "CDKATTRACT">19.1.2. Some Attractive Features</a></h4>
7148
7149          <p>Apart from making our life easier with readily usable
7150          widgets, cdk solves one frustrating problem with printing
7151          multi colored strings, justified strings elegantly.
7152          Special formatting tags can be embedded in the strings
7153          which are passed to CDK functions. For Example</p>
7154
7155          <p>If the string</p>
7156          <pre class="PROGRAMLISTING">
7157"&lt;/B/1&gt;This line should have a yellow foreground and a blue
7158background.&lt;!1&gt;"
7159</pre>
7160
7161          <p>given as a parameter to newCDKLabel(), it prints the
7162          line with yellow foreground and blue background. There
7163          are other tags available for justifying string, embedding
7164          special drawing characters etc.. Please refer to the man
7165          page cdk_display(3X) for details. The man page explains
7166          the usage with nice examples.</p>
7167        </div>
7168
7169        <div class="SECT3">
7170          <hr>
7171
7172          <h4 class="SECT3"><a name="CDKCONCLUSION" id=
7173          "CDKCONCLUSION">19.1.3. Conclusion</a></h4>
7174
7175          <p>All in all, CDK is a well-written package of widgets,
7176          which if used properly can form a strong frame work for
7177          developing complex GUI.</p>
7178        </div>
7179      </div>
7180
7181      <div class="SECT2">
7182        <hr>
7183
7184        <h3 class="SECT2"><a name="DIALOG" id="DIALOG">19.2. The
7185        dialog</a></h3>
7186
7187        <p>Long long ago, in September 1994, when few people knew
7188        linux, Jeff Tranter wrote an <a href=
7189        "http://www2.linuxjournal.com/lj-issues/issue5/2807.html"
7190        target="_top">article</a> on dialog in Linux Journal. He
7191        starts the article with these words..</p>
7192
7193        <p><span class="emphasis"><i class="EMPHASIS">Linux is
7194        based on the Unix operating system, but also features a
7195        number of unique and useful kernel features and application
7196        programs that often go beyond what is available under Unix.
7197        One little-known gem is "dialog", a utility for creating
7198        professional-looking dialog boxes from within shell
7199        scripts. This article presents a tutorial introduction to
7200        the dialog utility, and shows examples of how and where it
7201        can be used</i></span></p>
7202
7203        <p>As he explains, dialog is a real gem in making
7204        professional-looking dialog boxes with ease. It creates a
7205        variety of dialog boxes, menus, check lists etc.. It is
7206        usually installed by default. If not, you can download it
7207        from <a href="https://invisible-island.net/dialog/" target=
7208        "_top">Thomas Dickey</a>'s site.</p>
7209
7210        <p>The above-mentioned article gives a very good overview
7211        of its uses and capabilites. The man page has more details.
7212        It can be used in variety of situations. One good example
7213        is building of linux kernel in text mode. Linux kernel uses
7214        a modified version of dialog tailored for its needs.</p>
7215
7216        <p>dialog was initially designed to be used with shell
7217        scripts. If you want to use its functionality in a c
7218        program, then you can use libdialog. The documentation
7219        regarding this is sparse. Definitive reference is the
7220        dialog.h header file which comes with the library. You may
7221        need to hack here and there to get the required output. The
7222        source is easily customizable. I have used it on a number
7223        of occasions by modifying the code.</p>
7224      </div>
7225
7226      <div class="SECT2">
7227        <hr>
7228
7229        <h3 class="SECT2"><a name="PERLCURSES" id=
7230        "PERLCURSES">19.3. Perl Curses Modules CURSES::FORM and
7231        CURSES::WIDGETS</a></h3>
7232
7233        <p>The perl module Curses, Curses::Form and Curses::Widgets
7234        give access to curses from perl. If you have curses and
7235        basic perl is installed, you can get these modules from
7236        <a href="http://www.cpan.org/modules/01modules.index.html"
7237        target="_top">CPAN All Modules page</a>. Get the three
7238        zipped modules in the Curses category. Once installed you
7239        can use these modules from perl scripts like any other
7240        module. For more information on perl modules see perlmod
7241        man page. The above modules come with good documentation
7242        and they have some demo scripts to test the functionality.
7243        Though the widgets provided are very rudimentary, these
7244        modules provide good access to curses library from
7245        perl.</p>
7246
7247        <p>Some of my code examples are converted to perl by
7248        Anuradha Ratnaweera and they are available in the
7249        <tt class="LITERAL">perl</tt> directory.</p>
7250
7251        <p>For more information see man pages Curses(3) ,
7252        Curses::Form(3) and Curses::Widgets(3). These pages are
7253        installed only when the above modules are acquired and
7254        installed.</p>
7255      </div>
7256    </div>
7257
7258    <div class="SECT1">
7259      <hr>
7260
7261      <h2 class="SECT1"><a name="JUSTFORFUN" id="JUSTFORFUN">20.
7262      Just For Fun !!!</a></h2>
7263
7264      <p>This section contains few programs written by me just for
7265      fun. They don't signify a better programming practice or the
7266      best way of using ncurses. They are provided here so as to
7267      allow beginners to get ideas and add more programs to this
7268      section. If you have written a couple of nice, simple
7269      programs in curses and want them to included here, contact
7270      <a href="mailto:[email protected]" target="_top">me</a>.</p>
7271
7272      <div class="SECT2">
7273        <hr>
7274
7275        <h3 class="SECT2"><a name="GAMEOFLIFE" id=
7276        "GAMEOFLIFE">20.1. The Game of Life</a></h3>
7277
7278        <p>Game of life is a wonder of math. In <a href=
7279        "http://www.math.com/students/wonders/life/life.html"
7280        target="_top">Paul Callahan</a>'s words</p>
7281        <pre class="PROGRAMLISTING">
7282<span class="emphasis"><i class=
7283"EMPHASIS">The Game of Life (or simply Life) is not a game in the conventional sense. There
7284are no players, and no winning or losing. Once the "pieces" are placed in the
7285starting position, the rules determine everything that happens later.
7286Nevertheless, Life is full of surprises! In most cases, it is impossible to look
7287at a starting position (or pattern) and see what will happen in the future. The
7288only way to find out is to follow the rules of the game.</i></span>
7289</pre>
7290
7291        <p>This program starts with a simple inverted U pattern and
7292        shows how wonderful life works. There is a lot of room for
7293        improvement in the program. You can let the user enter
7294        pattern of his choice or even take input from a file. You
7295        can also change rules and play with a lot of variations.
7296        Search on <a href="http://www.google.com" target=
7297        "_top">google</a> for interesting information on game of
7298        life.</p>
7299
7300        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7301        JustForFun/life.c</i></span></p>
7302      </div>
7303
7304      <div class="SECT2">
7305        <hr>
7306
7307        <h3 class="SECT2"><a name="MAGIC" id="MAGIC">20.2. Magic
7308        Square</a></h3>
7309
7310        <p>Magic Square, another wonder of math, is very simple to
7311        understand but very difficult to make. In a magic square
7312        sum of the numbers in each row, each column is equal. Even
7313        diagnol sum can be equal. There are many variations which
7314        have special properties.</p>
7315
7316        <p>This program creates a simple magic square of odd
7317        order.</p>
7318
7319        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7320        JustForFun/magic.c</i></span></p>
7321      </div>
7322
7323      <div class="SECT2">
7324        <hr>
7325
7326        <h3 class="SECT2"><a name="HANOI" id="HANOI">20.3. Towers
7327        of Hanoi</a></h3>
7328
7329        <p>The famous towers of hanoi solver. The aim of the game
7330        is to move the disks on the first peg to last peg, using
7331        middle peg as a temporary stay. The catch is not to place a
7332        larger disk over a small disk at any time.</p>
7333
7334        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7335        JustForFun/hanoi.c</i></span></p>
7336      </div>
7337
7338      <div class="SECT2">
7339        <hr>
7340
7341        <h3 class="SECT2"><a name="QUEENS" id="QUEENS">20.4. Queens
7342        Puzzle</a></h3>
7343
7344        <p>The objective of the famous N-Queen puzzle is to put N
7345        queens on a N X N chess board without attacking each
7346        other.</p>
7347
7348        <p>This program solves it with a simple backtracking
7349        technique.</p>
7350
7351        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7352        JustForFun/queens.c</i></span></p>
7353      </div>
7354
7355      <div class="SECT2">
7356        <hr>
7357
7358        <h3 class="SECT2"><a name="SHUFFLE" id="SHUFFLE">20.5.
7359        Shuffle</a></h3>
7360
7361        <p>A fun game, if you have time to kill.</p>
7362
7363        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7364        JustForFun/shuffle.c</i></span></p>
7365      </div>
7366
7367      <div class="SECT2">
7368        <hr>
7369
7370        <h3 class="SECT2"><a name="TT" id="TT">20.6. Typing
7371        Tutor</a></h3>
7372
7373        <p>A simple typing tutor, I created more out of need than
7374        for ease of use. If you know how to put your fingers
7375        correctly on the keyboard, but lack practice, this can be
7376        helpful.</p>
7377
7378        <p><span class="emphasis"><i class="EMPHASIS">File Path:
7379        JustForFun/tt.c</i></span></p>
7380      </div>
7381    </div>
7382
7383    <div class="SECT1">
7384      <hr>
7385
7386      <h2 class="SECT1"><a name="REF" id="REF">21.
7387      References</a></h2>
7388
7389      <ul>
7390        <li>
7391          <p>NCURSES man pages</p>
7392        </li>
7393
7394        <li>
7395          <p>NCURSES FAQ at <a href=
7396          "https://invisible-island.net/ncurses/ncurses.faq.html"
7397          target=
7398          "_top">https://invisible-island.net/ncurses/ncurses.faq.html</a></p>
7399        </li>
7400
7401        <li>
7402          <p>Writing programs with NCURSES by Eric Raymond and Zeyd
7403          M. Ben-Halim at <a href=
7404          "https://invisible-island.net/ncurses/ncurses-intro.html"
7405          target=
7406          "_top">https://invisible-island.net/ncurses/ncurses-intro.html</a>
7407          - somewhat obsolete. I was inspired by this document and
7408          the structure of this HOWTO follows from the original
7409          document</p>
7410        </li>
7411      </ul>
7412    </div>
7413  </div>
7414</body>
7415</html>
7416