~ubuntu-branches/ubuntu/dapper/newt/dapper

« back to all changes in this revision

Viewing changes to tutorial.sgml

  • Committer: Bazaar Package Importer
  • Author(s): Alastair McKinstry
  • Date: 2004-11-27 09:49:00 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20041127094900-mf7cbmb00g7t8xow
Tags: 0.51.6-20
Upgrade bug; lbnewt0.51 was supplying /usr/lib/libnewt.so in conflict
with libnewt-dev. Closes: #283185.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<!DOCTYPE Article PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
2
 
 
3
 
<article>
4
 
 
5
 
<artheader>
6
 
<title>Writing Programs Using <literal remap="tt">newt</literal></title>
7
 
<author> 
8
 
<firstname>Erik Troan, &lt;ewt@redhat.com&gt;</firstname>
9
 
</author>
10
 
 
11
 
<pubdate>v0.30, 13 May 1998</pubdate>
12
 
 
13
 
<abstract>
14
 
 
15
 
<para>
16
 
The <literal remap="tt">newt</literal> windowing system is a terminal-based window and widget
17
 
library designed for writing applications with a simple, but user-friendly,
18
 
interface. While <literal remap="tt">newt</literal> is not intended to provide the rich feature
19
 
set advanced applications may require, it has proven to be flexible enough
20
 
for a wide range of applications (most notably, Red Hat's installation
21
 
process). This tutorial explains the design philosophy behind <literal remap="tt">newt</literal> and
22
 
how to use <literal remap="tt">newt</literal> from your programs.
23
 
</para>
24
 
 
25
 
</abstract>
26
 
</artheader>
27
 
 
28
 
 
29
 
 
30
 
<sect1><title>Introduction</title>
31
 
 
32
 
<para>
33
 
<literal remap="tt">Newt</literal> has a definite design philosophy behind it, and knowing that design
34
 
makes it significantly easier to craft robust <literal remap="tt">newt</literal> applications. This
35
 
tutorial documents <literal remap="tt">newt</literal> 0.30 --- older versions of <literal remap="tt">newt</literal> had
36
 
annoying inconsistencies in it (which writing this tutorial pointed out),
37
 
which were removed while this tutorial was written. The latest version of
38
 
<literal remap="tt">newt</literal> is always available from <ulink url="ftp://ftp.redhat.com/pub/redhat/code/newt">ftp.redhat.com</ulink>.</para>
39
 
 
40
 
<sect2><title>Background</title>
41
 
 
42
 
<para>
43
 
<literal remap="tt">Newt</literal> was originally designed for use in the install code for
44
 
Red Hat Linux. As this install code runs in an environment with limited
45
 
resources (most importantly limited filesystem space), <literal remap="tt">newt</literal>'s size
46
 
was immediately an issue. To help minimize its size, the following design
47
 
decisions were made early in it's implementation:
48
 
</para>
49
 
 
50
 
<itemizedlist>
51
 
<listitem>
52
 
 
53
 
<para>
54
 
 <literal remap="tt">newt</literal> does not use an event-driven architecture.
55
 
</para>
56
 
</listitem>
57
 
<listitem>
58
 
<para>
59
 
 <literal remap="tt">newt</literal> is written in C, not C++. While there has been interest
60
 
in constructing C++ wrapper classes around the <literal remap="tt">newt</literal> API, nothing has
61
 
yet come of those ideas.</para>
62
 
</listitem>
63
 
<listitem>
64
 
 
65
 
<para>
66
 
 Windows must be created and destroyed as a stack (in other words, all
67
 
<literal remap="tt">newt</literal> windows behave as modal dialogs). This is probably
68
 
the greatest functionality restriction of <literal remap="tt">newt</literal>.</para>
69
 
</listitem>
70
 
<listitem>
71
 
<para>
72
 
 The tty keyboard is the only supported input device.</para>
73
 
</listitem>
74
 
<listitem>
75
 
 
76
 
<para>
77
 
 Many behaviours, such as widget traversal order, are difficult
78
 
or impossible to change.
79
 
</para>
80
 
</listitem>
81
 
</itemizedlist>
82
 
 
83
 
<para>
84
 
While <literal remap="tt">newt</literal> provides a complete API, it does not handle the low-level
85
 
screen drawing itself. Instead, <literal remap="tt">newt</literal> is layered on top of the screen
86
 
management capabilities of John E. Davis's 
87
 
<ulink url="ftp://space.mit.edu/pub/davis/slang/">S-Lang</ulink> library.</para></sect2>
88
 
 
89
 
 
90
 
<sect2><title>Designing <literal remap="tt">newt</literal> applications</title>
91
 
<para>
92
 
As <literal remap="tt">newt</literal> is not event driven and forces modal windows (forcing window
93
 
order to behave like a stack), newt applications tend to look quite like
94
 
other text-mode programs. It is quite straightforward to convert a command
95
 
line program which uses simple user prompts into a <literal remap="tt">newt</literal> application.
96
 
Some of the programs run as part of the Red Hat installation process
97
 
(such as <literal remap="tt">Xconfigurator</literal> and <literal remap="tt">mouseconfig</literal>) were originally written
98
 
as simple terminal mode programs which used line-oriented menus to get
99
 
input from the user and were later converted into <literal remap="tt">newt</literal> applications
100
 
(through a process affectionately known as newtering). Such a conversion
101
 
does not require changes to the control flow of most applications.
102
 
 
103
 
Programming <literal remap="tt">newt</literal> is dramatically different from writing programs for
104
 
most other windowing systems as <literal remap="tt">newt</literal>'s API is not event driven. This
105
 
means that <literal remap="tt">newt</literal> applications look dramatically different from programs
106
 
written for event-driven architectures such as Motif, <literal remap="tt">gtk</literal>, or even
107
 
Borland's old TurboVision libraries.
108
 
 
109
 
When you're designing your <literal remap="tt">newt</literal> program, keep this differentiation
110
 
in mind. As long as you plan your application to call a function to
111
 
get input and then continue (rather then having your program called
112
 
when input is ready), programming with the newt libraries should be
113
 
simple.</para></sect2>
114
 
 
115
 
 
116
 
<sect2><title>Components</title>
117
 
 
118
 
<para>
119
 
Displayable items in <literal remap="tt">newt</literal> are known as <emphasis remap="bf">components</emphasis>, which are
120
 
analogous to the widgets provided by most Unix widget sets. There are
121
 
two main types of components in <literal remap="tt">newt</literal>, forms and everything else.
122
 
Forms logically group components into functional sets. When an application
123
 
is ready to get input from a user, it ``runs a form'', which makes the
124
 
form active and lets the user enter information into the components the
125
 
form contains. A form may contain any other component, including other
126
 
forms. Using subforms in this manner lets the application change the details
127
 
of how the user tabs between components on the form, scroll regions of the
128
 
screen, and control background colors for portions of windows.
129
 
 
130
 
Every component is of type <literal remap="tt">newtComponent</literal>, which is an opaque type. It's
131
 
guaranteed to be a pointer though, which lets applications move it through
132
 
void pointers if the need arises. Variables of type <literal remap="tt">newtComponent</literal> should
133
 
never be directly manipulated -- they should only be passed to <literal remap="tt">newt</literal>
134
 
functions. As <literal remap="tt">newtComponent</literal> variables are pointers, remember that
135
 
they are always passed by value -- if you pass a <literal remap="tt">newtComponent</literal> to
136
 
a function which manipulates it, that component is manipulated everywhere,
137
 
not just inside of that function (which is nearly always the behaviour
138
 
you want).</para></sect2>
139
 
 
140
 
 
141
 
<sect2><title>Conventions</title>
142
 
 
143
 
<para>
144
 
<literal remap="tt">Newt</literal> uses a number of conventions to make it easier for programmers
145
 
to use. 
146
 
 
147
 
 
148
 
<itemizedlist>
149
 
<listitem>
150
 
 
151
 
<para>
152
 
 All functions which manipulate data structures take the data
153
 
structure being modified as their first parameter. For example, all
154
 
of the functions which manipulate forms expect the <literal remap="tt">newtComponent</literal>
155
 
for that form to be the first parameter.</para></listitem>
156
 
<listitem>
157
 
 
158
 
<para>
159
 
 As <literal remap="tt">newt</literal> is loosely typed (forcing all of the components into
160
 
a single variable makes coding easier, but nullifies the value of type
161
 
checking), <literal remap="tt">newt</literal> functions include the name of the type they are
162
 
manipulating. An example of this is <literal remap="tt">newtFormAddComponent()</literal>, which
163
 
adds a component to a form. Note that the first parameter to this function
164
 
is a form, as the name would suggest.</para></listitem>
165
 
<listitem>
166
 
 
167
 
<para>
168
 
 When screen coordinates are passed into a function, the 
169
 
x location precedes the y location. To help keep this clear,
170
 
we'll use the words ``left'' and ``top'' to describe those indicators (with
171
 
left corresponding to the x position).</para></listitem>
172
 
<listitem>
173
 
 
174
 
<para>
175
 
 When box sizes are passed, the horizontal width precedes the vertical
176
 
width.</para></listitem>
177
 
<listitem>
178
 
 
179
 
<para>
180
 
 When both a screen location and a box size are being passed, the
181
 
screen location precedes the box size.</para></listitem>
182
 
<listitem>
183
 
 
184
 
<para>
185
 
 When any component other then a form is created, the first two
186
 
parameters are always the (left, right) location.</para></listitem>
187
 
<listitem>
188
 
 
189
 
<para>
190
 
 Many functions take a set of flags as the final parameter. These
191
 
flags may be logically ORed together to pass more then one flag at a time.</para></listitem>
192
 
<listitem>
193
 
 
194
 
<para>
195
 
 <literal remap="tt">Newt</literal> uses <emphasis remap="bf">callback</emphasis> functions to convey certain events to
196
 
the application. While callbacks differ slightly in their parameters, most
197
 
of them allow the application to specify an arbitrary argument to be passed
198
 
to the callback when the callback is invoked. This argument is always a 
199
 
<literal remap="tt">void *</literal>, which allows the application great flexibility.
200
 
</para>
201
 
</listitem>
202
 
</itemizedlist>
203
 
</para></sect2></sect1>
204
 
 
205
 
 
206
 
 
207
 
<sect1><title>Basic <literal remap="tt">Newt</literal> Functions</title>
208
 
 
209
 
<para>
210
 
While most <literal remap="tt">newt</literal> functions are concerned with widgets or groups
211
 
of widgets (called grids and forms), some parts of the <literal remap="tt">newt</literal> API
212
 
deal with more global issues, such as initializing <literal remap="tt">newt</literal> or writing
213
 
to the root window.</para>
214
 
 
215
 
 
216
 
<sect2><title>Starting and Ending <literal remap="tt">newt</literal> Services</title>
217
 
 
218
 
<para>
219
 
There are three functions which nearly every <literal remap="tt">newt</literal> application use. The
220
 
first two are used to initialize the system.
221
 
 
222
 
 
223
 
<screen>
224
 
int newtInit(void);
225
 
void newtCls(void);
226
 
</screen>
227
 
 
228
 
 
229
 
<literal remap="tt">newtInit()</literal> should be the first function called by every <literal remap="tt">newt</literal>
230
 
program. It initializes internal data structures and places the terminal
231
 
in raw mode. Most applications invoke <literal remap="tt">newtCls()</literal> immediately after
232
 
<literal remap="tt">newtInit()</literal>, which causes the screen to be cleared. It's not
233
 
necessary to call <literal remap="tt">newtCls()</literal> to use any of <literal remap="tt">newt</literal>'s features, but
234
 
doing so will normally give a much neater appearance.
235
 
 
236
 
When a <literal remap="tt">newt</literal> program is ready to exit, it should call <literal remap="tt">newtFinished()</literal>.
237
 
 
238
 
 
239
 
<screen>
240
 
int newtFinished(void);
241
 
</screen>
242
 
 
243
 
 
244
 
<literal remap="tt">newtFinished()</literal> restores the terminal to it's appearance when
245
 
<literal remap="tt">newtInit()</literal> was called (if possible -- on some terminals the cursor will
246
 
be moved to the bottom, but it won't be possible to remember the original
247
 
terminal contents) and places the terminal in it's original input state.
248
 
If this function isn't called, the terminal will probably need to be
249
 
reset with the <literal remap="tt">reset</literal> command before it can be used easily.</para></sect2>
250
 
 
251
 
 
252
 
<sect2><title>Handling Keyboard Input</title>
253
 
 
254
 
<para>
255
 
Normally, <literal remap="tt">newt</literal> programs don't read input directly from the
256
 
user. Instead, they let <literal remap="tt">newt</literal> read the input and hand it to the
257
 
program in a semi-digested form. <literal remap="tt">Newt</literal> does provide a couple of simple
258
 
functions which give programs (a bit of) control over the terminal.
259
 
 
260
 
 
261
 
<screen>
262
 
void newtWaitForKey(void);
263
 
void newtClearKeyBuffer(void);
264
 
</screen></para>
265
 
 
266
 
 
267
 
 
268
 
<para>
269
 
The first of these, <literal remap="tt">newtWaitForKey()</literal>, doesn't return until a key
270
 
has been pressed. The keystroke is then ignored. If a key is already in
271
 
the terminal's buffer, <literal remap="tt">newtWaitForKey()</literal> discards a keystroke and
272
 
returns immediately.
273
 
 
274
 
<literal remap="tt">newtClearKeyBuffer()</literal> discards the contents of the terminal's input
275
 
buffer without waiting for additional input.</para></sect2> 
276
 
 
277
 
 
278
 
<sect2><title>Drawing on the Root Window</title>
279
 
 
280
 
<para>
281
 
The background of the terminal's display (the part without any windows 
282
 
covering it) is known as the <emphasis remap="bf">root window</emphasis> (it's the parent of all
283
 
windows, just like the system's root directory is the parent of all 
284
 
subdirectories). Normally, applications don't use the root window, instead
285
 
drawing all of their text inside of windows (<literal remap="tt">newt</literal> doesn't require
286
 
this though -- widgets may be placed directly on the root window without
287
 
difficulty). It is often desirable to display some text, such as a
288
 
program's name or copyright information, on the root window, however.
289
 
<literal remap="tt">Newt</literal> provides two ways of displaying text on the root window. These
290
 
functions may be called at any time. They are the only <literal remap="tt">newt</literal> functions
291
 
which are meant to write outside of the current window.
292
 
 
293
 
 
294
 
<screen>
295
 
void newtDrawRootText(int left, int top, const char * text);
296
 
</screen></para>
297
 
 
298
 
 
299
 
 
300
 
<para>
301
 
This function is straightforward. It displays the string <literal remap="tt">text</literal> at
302
 
the position indicated. If either the <literal remap="tt">left</literal> or <literal remap="tt">top</literal> is
303
 
negative, the position is measured from the opposite side of the
304
 
screen. The final measurement will seem to be off by one though. For
305
 
example, a <literal remap="tt">top</literal> of -1 indicates the last line on the screen, and
306
 
one of -2 is the line above that.
307
 
 
308
 
As it's common to use the last line on the screen to display help information,
309
 
<literal remap="tt">newt</literal> includes special support for doing exactly that. The last
310
 
line on the display is known as the <emphasis remap="bf">help line</emphasis>, and is treated as a
311
 
stack. As the value of the help line normally relates to the window
312
 
currently displayed, using the same structure for window order and the
313
 
help line is very natural. Two functions are provided to manipulate the
314
 
help line.
315
 
 
316
 
 
317
 
<screen>
318
 
void newtPushHelpLine(const char * text);
319
 
void newtPopHelpLine(void);
320
 
</screen>
321
 
 
322
 
 
323
 
The first function, <literal remap="tt">newtPushHelpLine()</literal>, saves the current help line
324
 
on a stack (which is independent of the window stack) and displays the
325
 
new line. If <literal remap="tt">text</literal> is <literal remap="tt">NULL</literal>, <literal remap="tt">newt</literal>'s default help line is
326
 
displayed (which provides basic instructions on using <literal remap="tt">newt</literal>). If
327
 
<literal remap="tt">text</literal> is a string of length 0, the help line is cleared. For all
328
 
other values of <literal remap="tt">text</literal>, the passed string is displayed at the bottom,
329
 
left-hand corner of the display. The space between the end of the displayed
330
 
string the the right-hand edge of the terminal is cleared.
331
 
 
332
 
<literal remap="tt">newtPopHelpLine()</literal> replaces the current help line with the one it
333
 
replaced. It's important not to call tt/newtPopHelpLine()/ more then
334
 
<literal remap="tt">newtPushHelpLine()</literal>!
335
 
 
336
 
<literal remap="tt">Suspending Newt Applications</literal>
337
 
 
338
 
By default, <literal remap="tt">newt</literal> programs cannot be suspended by the user (compare
339
 
this to most Unix programs which can be suspended by pressing the suspend
340
 
key (normally <literal remap="tt">^Z</literal>).  Instead, programs can specify a <emphasis remap="bf">callback</emphasis>
341
 
function which gets invoked when the user presses the suspend key. 
342
 
 
343
 
 
344
 
<screen>
345
 
typedef void (*newtSuspendCallback)(void);
346
 
 
347
 
void newtSetSuspendCallback(newtSuspendCallback cb);
348
 
</screen>
349
 
 
350
 
 
351
 
The suspend function neither expects nor returns any value, and can
352
 
do whatever it likes to when it is invoked. If no suspend callback
353
 
is registered, the suspend keystroke is ignored.
354
 
 
355
 
If the application should suspend and continue like most user applications,
356
 
the suspend callback needs two other <literal remap="tt">newt</literal> functions.
357
 
 
358
 
 
359
 
<screen>
360
 
void newtSuspend(void);
361
 
void newtResume(void);
362
 
</screen>
363
 
 
364
 
 
365
 
<literal remap="tt">newtSuspend()</literal> tells <literal remap="tt">newt</literal> to return the terminal to it's initial
366
 
state. Once this is done, the application can suspend itself (by
367
 
sending itself a <literal remap="tt">SIGTSTP</literal>, fork a child program, or do whatever
368
 
else it likes. When it wants to resume using the <literal remap="tt">newt</literal> interface,
369
 
it must call <literal remap="tt">newtResume</literal> before doing so. 
370
 
 
371
 
Note that suspend callbacks are not signal handlers. When <literal remap="tt">newtInit()</literal>
372
 
takes over the terminal, it disables the part of the terminal interface
373
 
which sends the suspend signal. Instead, if <literal remap="tt">newt</literal> sees the suspend
374
 
keystroke during normal input processing, it immediately calls the suspend
375
 
callback if one has been set. This means that suspending newt applications
376
 
is not asynchronous.</para></sect2>
377
 
 
378
 
 
379
 
<sect2><title>Refreshing the Screen</title>
380
 
 
381
 
<para>
382
 
To increase performance, S-Lang only updates the display when it needs
383
 
to, not when the program tells S-Lang to write to the terminal. ``When it
384
 
needs to'' is implemented as ``right before the we wait for the user to
385
 
press a key''. While this allows for optimized screen displays most of
386
 
the time, this optimization makes things difficult for programs which
387
 
want to display progress messages without forcing the user to input 
388
 
characters. Applications can force S-Lang to immediately update modified
389
 
portions of the screen by calling <literal remap="tt">newtRefresh</literal>.
390
 
 
391
 
 
392
 
<orderedlist>
393
 
<listitem>
394
 
 
395
 
<para>
396
 
The program wants to display a progress message, without forcing
397
 
for the user to enter any characters.</para></listitem>
398
 
<listitem>
399
 
 
400
 
<para>
401
 
A misfeature of the program causes part of the screen to be
402
 
corrupted. Ideally, the program would be fixed, but that may not 
403
 
always be practical.
404
 
</para>
405
 
</listitem></orderedlist>
406
 
</para></sect2>
407
 
 
408
 
 
409
 
 
410
 
<sect2><title>Other Miscellaneous Functions</title>
411
 
 
412
 
<para>
413
 
As always, some function defy characterization. Two of <literal remap="tt">newt</literal>'s general
414
 
function fit this oddball category.
415
 
 
416
 
 
417
 
<screen>
418
 
void newtBell(void);
419
 
void newtGetScreenSize(int * cols, int * rows);
420
 
</screen>
421
 
 
422
 
 
423
 
The first sends a beep to the terminal. Depending on the terminal's
424
 
settings, this been may or may not be audible. The second function,
425
 
<literal remap="tt">newtGetScreenSize()</literal>, fills in the passed pointers with the
426
 
current size of the terminal.</para></sect2>
427
 
 
428
 
 
429
 
<sect2><title>Basic <literal remap="tt">newt</literal> Example</title>
430
 
 
431
 
<para>
432
 
To help illustrate the functions presented in this section here is a short
433
 
sample <literal remap="tt">newt</literal> program which uses many of them. While it doesn't do
434
 
anything interesting, it does show the basic structure of <literal remap="tt">newt</literal> programs.
435
 
 
436
 
 
437
 
<screen>
438
 
#include &#60;newt.h&#62;
439
 
#include &#60;stdlib.h&#62;
440
 
 
441
 
int main(void) {
442
 
    newtInit();
443
 
    newtCls();
444
 
 
445
 
    newtDrawRootText(0, 0, "Some root text");
446
 
    newtDrawRootText(-25, -2, "Root text in the other corner");
447
 
 
448
 
    newtPushHelpLine(NULL);
449
 
    newtRefresh();
450
 
    sleep(1);
451
 
 
452
 
    newtPushHelpLine("A help line");
453
 
    newtRefresh();
454
 
    sleep(1);
455
 
 
456
 
    newtPopHelpLine();
457
 
    newtRefresh();
458
 
    sleep(1);
459
 
 
460
 
    newtFinished();
461
 
}
462
 
</screen></para></sect2></sect1>
463
 
 
464
 
 
465
 
 
466
 
<sect1><title>Windows</title>
467
 
 
468
 
<para>
469
 
While most <literal remap="tt">newt</literal> applications do use windows, <literal remap="tt">newt</literal>'s window
470
 
support is actually extremely limited. Windows must be destroyed in the
471
 
opposite order they were created, and only the topmost window may be
472
 
active. Corollaries to this are:
473
 
 
474
 
 
475
 
<itemizedlist>
476
 
<listitem>
477
 
 
478
 
<para>
479
 
The user may not switch between windows.</para></listitem>
480
 
<listitem>
481
 
 
482
 
<para>
483
 
Only the top window may be destroyed.
484
 
</para>
485
 
</listitem></itemizedlist>
486
 
 
487
 
While this is quite a severe limitation, adopting it greatly simplifies
488
 
both writing <literal remap="tt">newt</literal> applications and developing <literal remap="tt">newt</literal> itself, as it
489
 
separates <literal remap="tt">newt</literal> from the world of event-driven programming. However,
490
 
this tradeoff between function and simplicity may make <literal remap="tt">newt</literal>
491
 
unsuitable for some tasks.
492
 
</para>
493
 
 
494
 
<sect2><title>Creating Windows</title>
495
 
 
496
 
<para>
497
 
There are two main ways of opening <literal remap="tt">newt</literal> windows; with or without
498
 
explicit sizings. When grids (which will be introduced later is this
499
 
tutorial) are used, a window may be made to just fit the grid. When
500
 
grids are not used, explicit sizing must be given.
501
 
 
502
 
 
503
 
<screen>
504
 
int newtCenteredWindow(int width, int height, const char * title);
505
 
int newtOpenWindow(int left, int top, int width, int height, 
506
 
                   const char * title);
507
 
</screen>
508
 
 
509
 
 
510
 
The first of these functions open a centered window of the specified
511
 
size. The <literal remap="tt">title</literal> is optional -- if it is <literal remap="tt">NULL</literal>, then no title
512
 
is used. <literal remap="tt">newtOpenWindow*(</literal> is similar, but it requires a specific
513
 
location for the upper left-hand corner of the window.</para></sect2>
514
 
 
515
 
 
516
 
<sect2><title>Destroying Windows</title>
517
 
 
518
 
<para>
519
 
All windows are destroyed in the same manner, no matter how the windows
520
 
were originally created.
521
 
 
522
 
 
523
 
<screen>
524
 
void newtPopWindow(void);
525
 
</screen>
526
 
 
527
 
 
528
 
This function removes the top window from the display, and redraws the
529
 
display areas which the window overwrote.</para></sect2></sect1> 
530
 
 
531
 
 
532
 
<sect1><title>Components</title>
533
 
 
534
 
<para>
535
 
Components are the basic user interface element <literal remap="tt">newt</literal> provides. A
536
 
single component may be (for example) a listbox, push button checkbox,
537
 
a collection of other components. Most components are used to display
538
 
information in a window, provide a place for the user to enter data, or a
539
 
combination of these two functions. 
540
 
 
541
 
Forms, however, are a component whose primary purpose is not noticed by
542
 
the user at all. Forms are collections of components (a form may contain
543
 
another form) which logically relate the components to one another. Once
544
 
a form is created and had all of its constituent components added to it,
545
 
applications normally then run the form.  This gives control of the
546
 
application to the form, which then lets the user enter data onto the
547
 
form. When the user is done (a number of different events qualify as
548
 
``done''), the form returns control to the part of the application which
549
 
invoked it. The application may then read the information the user provided
550
 
and continue appropriately.
551
 
 
552
 
All <literal remap="tt">newt</literal> components are stored in a common data type, a
553
 
<literal remap="tt">newtComponent</literal> (some of the particulars of <literal remap="tt">newtComponent</literal>s have
554
 
already been mentioned. While this makes it easy for programmers to pass
555
 
components around, it does force them to make sure they use they don't pass
556
 
entry boxes to routines expecting push buttons, as the compiler can't
557
 
ensure that for them.
558
 
 
559
 
We start off with a brief introduction to forms. While not terribly
560
 
complete, this introduction is enough to let us illustrate the rest of
561
 
the components with some sample code. We'll then discuss the remainder of
562
 
the components, and end this section with a more exhaustive description of
563
 
forms.</para>
564
 
 
565
 
 
566
 
<sect2><title>Introduction to Forms</title>
567
 
 
568
 
<para>
569
 
As we've mentioned, forms are simply collections of components. As only one
570
 
form can be active (or running) at a time, every component which the user
571
 
should be able to access must be on the running form (or on a subform of
572
 
the running form). A form is itself a component, which means forms are
573
 
stored in <literal remap="tt">newtComponent</literal> data structures.
574
 
 
575
 
 
576
 
<screen>
577
 
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
578
 
</screen>
579
 
 
580
 
 
581
 
To create a form, call <literal remap="tt">newtForm()</literal>. The first parameter is a vertical
582
 
scrollbar which should be associated with the form. For now, that should
583
 
always be <literal remap="tt">NULL</literal> (we'll discuss how to create scrolling forms later in
584
 
this section). The second parameter, <literal remap="tt">help</literal>, is currently unused and
585
 
should always be <literal remap="tt">NULL</literal>. The <literal remap="tt">flags</literal> is normally 0, and other values
586
 
it can take will be discussed later. Now that we've waved away the
587
 
complexity of this function, creating a form boils down to simply:
588
 
 
589
 
 
590
 
<screen>
591
 
newtComponent myForm;
592
 
 
593
 
myForm = newtForm(NULL, NULL, 0);
594
 
</screen>
595
 
 
596
 
 
597
 
After a form is created, components need to be added to it --- after all,
598
 
an empty form isn't terribly useful. There are two functions which add
599
 
components to a form.
600
 
 
601
 
 
602
 
<screen>
603
 
void newtFormAddComponent(newtComponent form, newtComponent co);
604
 
void newtFormAddComponents(newtComponent form, ...);
605
 
</screen>
606
 
 
607
 
 
608
 
The first function, <literal remap="tt">newtFormAddComponent()</literal>, adds a single component
609
 
to the form which is passed as the first parameter. The second function
610
 
is simply a convenience function. After passing the form to
611
 
<literal remap="tt">newtFormAddComponents()</literal>, an arbitrary number of components is then
612
 
passed, followed by <literal remap="tt">NULL</literal>. Every component passed is added to the form.
613
 
 
614
 
Once a form has been created and components have been added to it, it's
615
 
time to run the form.
616
 
 
617
 
 
618
 
<screen>
619
 
newtComponent newtRunForm(newtComponent form);
620
 
</screen>
621
 
 
622
 
 
623
 
This function runs the form passed to it, and returns the component which
624
 
caused the form to stop running. For now, we'll ignore the return value
625
 
completely.
626
 
 
627
 
Notice that this function doesn't fit in with <literal remap="tt">newt</literal>'s normal
628
 
naming convention. It is an older interface which will not work for all
629
 
forms. It was left in <literal remap="tt">newt</literal> only for legacy applications. It is a
630
 
simpler interface then the new <literal remap="tt">newtFormRun()</literal> though, and is still used
631
 
quite often as a result.
632
 
 
633
 
When an application is done with a form, it destroys the form and
634
 
all of the components the form contains.
635
 
 
636
 
 
637
 
<screen>
638
 
void newtFormDestroy(newtComponent form);       
639
 
</screen>
640
 
 
641
 
 
642
 
This function frees the memory resources used by the form and all of the
643
 
components which have been added to the form (including those components
644
 
which are on subforms). Once a form has been destroyed, none of the form's
645
 
components can be used.</para></sect2>
646
 
 
647
 
 
648
 
<sect2><title>Components</title>
649
 
 
650
 
<para>
651
 
Non-form components are the most important user-interface component for
652
 
users. They determine how users interact with <literal remap="tt">newt</literal> and how information
653
 
is presented to them.</para></sect2>
654
 
 
655
 
 
656
 
<sect2><title>General Component Manipulation</title>
657
 
 
658
 
<para>
659
 
There are a couple of functions which work on more then one type of
660
 
components. The description of each component indicates which (if any)
661
 
of these functions are valid for that particular component.
662
 
 
663
 
 
664
 
<screen>
665
 
typedef void (*newtCallback)(newtComponent, void *);
666
 
 
667
 
void newtComponentAddCallback(newtComponent co, newtCallback f, void * data);
668
 
void newtComponentTakesFocus(newtComponent co, int val);
669
 
</screen>
670
 
 
671
 
 
672
 
The first registers a callback function for that component. A callback
673
 
function is a function the application provides which <literal remap="tt">newt</literal> calls for a
674
 
particular component. Exactly when (if ever) the callback is invoked
675
 
depends on the type of component the callback is attached to, and will be
676
 
discussed for the components which support callbacks.
677
 
 
678
 
<literal remap="tt">newtComponentTakesFocus()</literal> works on all components. It allows the
679
 
application to change which components the user is allowed to select as the
680
 
current component, and hence provide input to. Components which do not
681
 
take focus are skipped over during form traversal, but they are displayed
682
 
on the terminal. Some components should never be set to take focus, such
683
 
as those which display static text.</para></sect2>
684
 
 
685
 
 
686
 
<sect2><title>Buttons</title>
687
 
 
688
 
<para>
689
 
Nearly all forms contain at least one button. <literal remap="tt">Newt</literal> buttons come in two
690
 
flavors, full buttons and compact buttons. Full buttons take up quit a bit
691
 
of screen space, but look much better then the single-row compact buttons.
692
 
Other then their size, both button styles behave identically. Different
693
 
functions are used to create the two types of buttons.
694
 
 
695
 
 
696
 
<screen>
697
 
newtComponent newtButton(int left, int top, const char * text);
698
 
newtComponent newtCompactButton(int left, int top, const char * text);
699
 
</screen>
700
 
 
701
 
 
702
 
Both functions take identical parameters. The first two parameters are the
703
 
location of the upper left corner of the button, and the final parameter is
704
 
the text which should be displayed in the button (such as ``Ok'' or
705
 
``Cancel'').</para>
706
 
 
707
 
 
708
 
<sect3><title>Button Example</title>
709
 
 
710
 
<para>
711
 
Here is a simple example of both full and compact buttons. It also
712
 
illustrates opening and closing windows, as well a simple form.
713
 
 
714
 
 
715
 
<screen>
716
 
#include &#60;newt.h&#62;
717
 
#include &#60;stdlib.h&#62;
718
 
 
719
 
void main(void) {
720
 
    newtComponent form, b1, b2;
721
 
    newtInit();
722
 
    newtCls();
723
 
 
724
 
    newtOpenWindow(10, 5, 40, 6, "Button Sample");
725
 
 
726
 
    b1 = newtButton(10, 1, "Ok");
727
 
    b2 = newtCompactButton(22, 2, "Cancel");
728
 
    form = newtForm(NULL, NULL, 0);
729
 
    newtFormAddComponents(form, b1, b2, NULL);
730
 
 
731
 
    newtRunForm(form);
732
 
 
733
 
    newtFormDestroy(form);
734
 
    newtFinished();
735
 
}
736
 
</screen></para></sect3></sect2>
737
 
 
738
 
 
739
 
 
740
 
<sect2><title>Labels</title>
741
 
 
742
 
<para>
743
 
Labels are <literal remap="tt">newt</literal>'s simplest component. They display some given text and
744
 
don't allow any user input.
745
 
 
746
 
 
747
 
<screen>
748
 
newtComponent newtLabel(int left, int top, const char * text);
749
 
void newtLabelSetText(newtComponent co, const char * text);
750
 
</screen>
751
 
 
752
 
 
753
 
Creating a label is just like creating a button; just pass the location of
754
 
the label and the text it should display. Unlike buttons, labels do let the
755
 
application change the text in the label with <literal remap="tt">newtLabelSetText</literal>. When
756
 
the label's text is changed, the label automatically redraws itself. It
757
 
does not clear out any old text which may be leftover from the previous
758
 
time is was displayed, however, so be sure that the new text is at least
759
 
as long as the old text.</para></sect2>
760
 
 
761
 
 
762
 
<sect2><title>Entry Boxes</title>
763
 
 
764
 
<para>
765
 
Entry boxes allow the user to enter a text string into the form which the
766
 
application can later retrieve.
767
 
 
768
 
 
769
 
<screen>
770
 
typedef int (*newtEntryFilter)(newtComponent entry, void * data, int ch,
771
 
                               int cursor);
772
 
 
773
 
newtComponent newtEntry(int left, int top, const char * initialValue, int width,
774
 
                        char ** resultPtr, int flags);
775
 
void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd);
776
 
char * newtEntryGetValue(newtComponent co);
777
 
void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data);
778
 
</screen></para>
779
 
 
780
 
 
781
 
 
782
 
<para>
783
 
<literal remap="tt">newtEntry()</literal> creates a new entry box. After the location of the entry
784
 
box, the initial value for the entry box is passed, which may be <literal remap="tt">NULL</literal>
785
 
if the box should start off empty. Next, the width of the physical box is
786
 
given. This width may or may not limit the length of the string the user is
787
 
allowed to enter; that depends on the <literal remap="tt">flags</literal>. The <literal remap="tt">resultPtr</literal> must
788
 
be the address of a <literal remap="tt">char *</literal>. Until the entry box is destroyed by
789
 
<literal remap="tt">newtFormDestroy()</literal>, that <literal remap="tt">char *</literal> will point to the current value
790
 
of the entry box. It's important that applications make a copy of that
791
 
value before destroying the form if they need to use it later. The
792
 
<literal remap="tt">resultPtr</literal> may be <literal remap="tt">NULL</literal>, in which case the user must use the
793
 
<literal remap="tt">newtEntryGetValue()</literal> function to get the value of the entry box.
794
 
 
795
 
Entry boxes support a number of flags:
796
 
 
797
 
<variablelist>
798
 
 
799
 
<varlistentry>
800
 
<term>NEWT_ENTRY_SCROLL</term>
801
 
<listitem>
802
 
<para>If this flag is not specified, the user cannot
803
 
enter text into the entry box which is wider then the entry box itself.
804
 
This flag removes this limitation, and lets the user enter data of an
805
 
arbitrary length.</para></listitem>
806
 
</varlistentry>
807
 
<varlistentry>
808
 
<term>NEWT_FLAG_HIDDEN</term>
809
 
<listitem>
810
 
<para>If this flag is specified, the value of the entry box
811
 
is not displayed. This is useful when the application needs to read a
812
 
password, for example.</para></listitem>
813
 
</varlistentry>
814
 
<varlistentry>
815
 
<term>NEWT_FLAG_RETURNEXIT</term>
816
 
<listitem>
817
 
<para>When this flag is given, the entry box will cause
818
 
the form to stop running if the user pressed return inside of the entry
819
 
box. This can provide a nice shortcut for users.</para>
820
 
</listitem>
821
 
</varlistentry>
822
 
</variablelist>
823
 
 
824
 
 
825
 
After an entry box has been created, it's contents can be set by
826
 
<literal remap="tt">newtEntrySet()</literal>. After the entry box itself, the new string to place
827
 
in the entry box is passed. The final parameter, <literal remap="tt">cursorAtEnd</literal>, controls
828
 
where the cursor will appear in the entry box. If it is zero, the cursor
829
 
remains at it's present location; a nonzero value moves the cursor to the
830
 
end of the entry box's new value.
831
 
 
832
 
While the simplest way to find the value of an entry box is by using a
833
 
<literal remap="tt">resultPtr</literal>, doing so complicates some applications.
834
 
<literal remap="tt">newtEntryGetValue()</literal> returns a pointer to the string which the entry
835
 
box currently contains. The returned pointer may not be valid once the
836
 
user further modifies the entry box, and will not be valid after the 
837
 
entry box has been destroyed, so be sure to save it's value in a more
838
 
permanent location if necessary.
839
 
 
840
 
Entry boxes allow applications to filter characters as they are entered.
841
 
This allows programs to ignore characters which are invalid (such as
842
 
entering a ^ in the middle of a phone number) and provide intelligent aids
843
 
to the user (such as automatically adding a '.' after the user has typed in
844
 
the first three numbers in an IP address). 
845
 
 
846
 
When a filter is registered through <literal remap="tt">newtEntrySetFilter()</literal>, both the
847
 
filter itself and an arbitrary <literal remap="tt">void *</literal>, which passed to the filter
848
 
whenever it is invoked, are recorded. This data pointer isn't used for any
849
 
other purpose, and may be <literal remap="tt">NULL</literal>. Entry filters take four arguments.
850
 
 
851
 
 
852
 
<orderedlist>
853
 
<listitem>
854
 
 
855
 
<para>
856
 
The entry box which had data entered into it</para></listitem>
857
 
<listitem>
858
 
 
859
 
<para>
860
 
The data pointer which was registered along with the filter</para></listitem>
861
 
<listitem>
862
 
 
863
 
<para>
864
 
The new character which <literal remap="tt">newt</literal> is considering inserting into the
865
 
entry box</para></listitem>
866
 
<listitem>
867
 
 
868
 
<para>
869
 
The current cursor position (0 is the leftmost position)
870
 
</para>
871
 
</listitem>
872
 
</orderedlist>
873
 
 
874
 
The filter returns 0 if the character should be ignored, or the value of
875
 
the character which should be inserted into the entry box. Filter functions
876
 
which want to do complex manipulations of the string should use
877
 
<literal remap="tt">newtEntrySet()</literal> to update the entry box and then return 0 to prevent
878
 
the new character from being inserted.
879
 
 
880
 
When a callback is attached to a entry box, the callback is invoked
881
 
whenever the user moves off of the callback and on to another component.
882
 
 
883
 
Here is a sample program which illustrates the use of both labels and
884
 
entry boxes.
885
 
 
886
 
 
887
 
<screen>
888
 
#include &#60;newt.h&#62;
889
 
#include &#60;stdlib.h&#62;
890
 
#include &#60;stdio.h&#62;
891
 
 
892
 
void main(void) {
893
 
    newtComponent form, label, entry, button;
894
 
    char * entryValue;
895
 
 
896
 
    newtInit();
897
 
    newtCls();
898
 
 
899
 
    newtOpenWindow(10, 5, 40, 8, "Entry and Label Sample");
900
 
 
901
 
    label = newtLabel(1, 1, "Enter a string");
902
 
    entry = newtEntry(16, 1, "sample", 20, &amp;entryValue, 
903
 
                      NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
904
 
    button = newtButton(17, 3, "Ok");
905
 
    form = newtForm(NULL, NULL, 0);
906
 
    newtFormAddComponents(form, label, entry, button, NULL);
907
 
 
908
 
    newtRunForm(form);
909
 
 
910
 
    newtFinished();
911
 
 
912
 
    printf("Final string was: %s\n", entryValue);
913
 
 
914
 
    /* We cannot destroy the form until after we've used the value
915
 
       from the entry widget. */
916
 
    newtFormDestroy(form);
917
 
}
918
 
</screen></para></sect2>
919
 
 
920
 
 
921
 
 
922
 
<sect2><title>Checkboxes</title>
923
 
 
924
 
<para>
925
 
Most widget sets include checkboxes which toggle between two value (checked
926
 
or not checked). <literal remap="tt">Newt</literal> checkboxes are more flexible. When the user
927
 
presses the space bar on a checkbox, the checkbox's value changes to the
928
 
next value in an arbitrary sequence (which wraps). Most checkboxes have
929
 
two items in that sequence, checked or not, but <literal remap="tt">newt</literal> allows an
930
 
arbitrary number of value. This is useful when the user must pick from a
931
 
limited number of choices.
932
 
 
933
 
Each item in the sequence is a single character, and the sequence itself is
934
 
represented as a string. The checkbox components displays the character
935
 
which currently represents its value the left of a text label, and returns
936
 
the same character as its current value. The default sequence for
937
 
checkboxes is <literal remap="tt">" *"</literal>, with <literal remap="tt">' '</literal> indicating false and <literal remap="tt">'*'</literal> true.
938
 
 
939
 
 
940
 
<screen>
941
 
newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
942
 
                           const char * seq, char * result);
943
 
char newtCheckboxGetValue(newtComponent co);
944
 
</screen></para>
945
 
 
946
 
 
947
 
 
948
 
<para>
949
 
Like most components, the position of the checkbox is the first thing
950
 
passed to the function that creates one. The next parameter, <literal remap="tt">text</literal>, is
951
 
the text which is displayed to the right of the area which is checked.  The
952
 
<literal remap="tt">defValue</literal> is the initial value for the checkbox, and <literal remap="tt">seq</literal> is the
953
 
sequence which the checkbox should go through (<literal remap="tt">defValue</literal> must be
954
 
in <literal remap="tt">seq</literal>. <literal remap="tt">seq</literal> may be <literal remap="tt">NULL</literal>, in which case <literal remap="tt">" *"</literal> is used.
955
 
The final parameter, <literal remap="tt">result</literal>, should point to a character which the
956
 
checkbox should always record it's current value in. If <literal remap="tt">result</literal> is
957
 
<literal remap="tt">NULL</literal>, <literal remap="tt">newtCheckboxGetValue()</literal> must be used to get the current
958
 
value of the checkbox.
959
 
 
960
 
<literal remap="tt">newtCheckboxGetValue()</literal> is straightforward, returning the character
961
 
in the sequence which indicates the current value of the checkbox
962
 
 
963
 
If a callback is attached to a checkbox, the callback is invoked whenever
964
 
the checkbox responds to a user's keystroke. The entry box may respond by
965
 
taking focus or giving up focus, as well as by changing its current value.</para></sect2>
966
 
 
967
 
 
968
 
<sect2><title>Radio Buttons</title>
969
 
 
970
 
<para>
971
 
Radio buttons look very similar to checkboxes. The key difference between
972
 
the two is that radio buttons are grouped into sets, and exactly one radio
973
 
button in that set may be turned on. If another radio button is selected,
974
 
the button which was selected is automatically deselected.
975
 
 
976
 
 
977
 
 
978
 
<screen>
979
 
newtComponent newtRadiobutton(int left, int top, const char * text, 
980
 
                              int isDefault, newtComponent prevButton);
981
 
newtComponent newtRadioGetCurrent(newtComponent setMember);
982
 
</screen>
983
 
 
984
 
 
985
 
Each radio button is created by calling <literal remap="tt">newtRadiobutton()</literal>. After
986
 
the position of the radio button, the text displayed with the button
987
 
is passed. <literal remap="tt">isDefault</literal> should be nonzero if the radio button is to
988
 
be turned on by default. The final parameter, <literal remap="tt">prevMember</literal> is used
989
 
to group radio buttons into sets. If <literal remap="tt">prevMember</literal> is <literal remap="tt">NULL</literal>, the 
990
 
radio button is assigned to a new set. If the radio button should belong
991
 
to a preexisting set, <literal remap="tt">prevMember</literal> must be the previous radio button
992
 
added to that set.
993
 
 
994
 
Discovering which radio button in a set is currently selected necessitates
995
 
<literal remap="tt">newtRadioGetCurrent()</literal>. It may be passed any radio button in the set
996
 
you're interested in, and it returns the radio button component currently
997
 
selected.
998
 
 
999
 
Here is an example of both checkboxes and radio buttons.
1000
 
 
1001
 
 
1002
 
<screen>
1003
 
#include &#60;newt.h&#62;
1004
 
#include &#60;stdlib.h&#62;
1005
 
#include &#60;stdio.h&#62;
1006
 
 
1007
 
void main(void) {
1008
 
    newtComponent form, checkbox, rb[3], button;
1009
 
    char cbValue;
1010
 
    int i;
1011
 
 
1012
 
    newtInit();
1013
 
    newtCls();
1014
 
 
1015
 
    newtOpenWindow(10, 5, 40, 11, "Checkboxes and Radio buttons");
1016
 
 
1017
 
    checkbox = newtCheckbox(1, 1, "A checkbox", ' ', " *X", &amp;cbValue);
1018
 
 
1019
 
    rb[0] = newtRadiobutton(1, 3, "Choice 1", 1, NULL);
1020
 
    rb[1] = newtRadiobutton(1, 4, "Choice 2", 0, rb[0]);
1021
 
    rb[2] = newtRadiobutton(1, 5, "Choice 3", 0, rb[1]);
1022
 
 
1023
 
    button = newtButton(1, 7, "Ok");
1024
 
 
1025
 
    form = newtForm(NULL, NULL, 0);
1026
 
    newtFormAddComponent(form, checkbox);
1027
 
    for (i = 0; i &#60; 3; i++)
1028
 
        newtFormAddComponent(form, rb[i]);
1029
 
    newtFormAddComponent(form, button);
1030
 
 
1031
 
    newtRunForm(form);
1032
 
    newtFinished();
1033
 
 
1034
 
    /* We cannot destroy the form until after we've found the current
1035
 
       radio button */
1036
 
 
1037
 
    for (i = 0; i &#60; 3; i++)
1038
 
        if (newtRadioGetCurrent(rb[0]) == rb[i])
1039
 
            printf("radio button picked: %d\n", i);
1040
 
    newtFormDestroy(form);
1041
 
 
1042
 
    /* But the checkbox's value is stored locally */
1043
 
    printf("checkbox value: '%c'\n", cbValue);
1044
 
}
1045
 
</screen></para></sect2>
1046
 
 
1047
 
 
1048
 
 
1049
 
<sect2><title>Scales</title>
1050
 
 
1051
 
<para>
1052
 
It's common for programs to need to display a progress meter on the
1053
 
terminal while it performs some length operation (it behaves like an
1054
 
anesthetic). The scale component is a simple way of doing this. It
1055
 
displays a horizontal bar graph which the application can update as the
1056
 
operation continues.
1057
 
 
1058
 
 
1059
 
<screen>
1060
 
newtComponent newtScale(int left, int top, int width, long long fullValue);
1061
 
void newtScaleSet(newtComponent co, unsigned long long amount);
1062
 
</screen>
1063
 
 
1064
 
 
1065
 
When the scale is created with <literal remap="tt">newtScale</literal>, it is given the width of the
1066
 
scale itself as well as the value which means that the scale should be
1067
 
drawn as full. When the position of the scale is set with
1068
 
<literal remap="tt">newtScaleSet()</literal>, the scale is told the amount of the scale which should
1069
 
be filled in relative to the <literal remap="tt">fullAmount</literal>. For example, if the
1070
 
application is copying a file, <literal remap="tt">fullValue</literal> could be the number of bytes
1071
 
in the file, and when the scale is updated <literal remap="tt">newtScaleSet()</literal> would be
1072
 
passed the number of bytes which have been copied so far.</para></sect2>
1073
 
 
1074
 
 
1075
 
<sect2><title>Textboxes</title>
1076
 
 
1077
 
<para>
1078
 
Textboxes display a block of text on the terminal, and is appropriate for
1079
 
display large amounts of text. 
1080
 
 
1081
 
 
1082
 
<screen>
1083
 
newtComponent newtTextbox(int left, int top, int width, int height, int flags);
1084
 
void newtTextboxSetText(newtComponent co, const char * text);
1085
 
</screen>
1086
 
 
1087
 
 
1088
 
<literal remap="tt">newtTextbox()</literal> creates a new textbox, but does not fill it with data.
1089
 
The function is passed the location for the textbox on the screen, the
1090
 
width and height of the textbox (in characters), and zero or more of the
1091
 
following flags:
1092
 
 
1093
 
<variablelist>
1094
 
 
1095
 
<varlistentry>
1096
 
<term>NEWT_FLAG_WRAP</term>
1097
 
<listitem>
1098
 
<para>All text in the textbox should be wrapped to fit
1099
 
the width of the textbox. If this flag is not specified, each newline
1100
 
delimited line in the text is truncated if it is too long to fit.
1101
 
 
1102
 
When <literal remap="tt">newt</literal> wraps text, it tries not to break lines on spaces or tabs.
1103
 
Literal newline characters are respected, and may be used to force line
1104
 
breaks.</para>
1105
 
<variablelist>
1106
 
 
1107
 
<varlistentry>
1108
 
<term>NEWT_FLAG_SCROLL</term>
1109
 
<listitem>
1110
 
<para>The text box should be scrollable. When this option
1111
 
is used, the scrollbar which is added increases the width of the area used
1112
 
by the textbox by 2 characters; that is the textbox is 2 characters wider
1113
 
then the width passed to <literal remap="tt">newtTextbox()</literal>.
1114
 
</para></listitem>
1115
 
</varlistentry>
1116
 
</variablelist>
1117
 
 
1118
 
 
1119
 
 
1120
 
<para>
1121
 
After a textbox has been created, text may be added to it through
1122
 
<literal remap="tt">newtTextboxSetText()</literal>, which takes only the textbox and the new text as
1123
 
parameters. If the textbox already contained text, that text is replaced by
1124
 
the new text. The textbox makes its own copy of the passed text, so these
1125
 
is no need to keep the original around unless it's convenient.</para></listitem></varlistentry></variablelist></para>
1126
 
 
1127
 
 
1128
 
<sect3><title>Reflowing Text</title>
1129
 
 
1130
 
<para>
1131
 
When applications need to display large amounts of text, it's common not to
1132
 
know exactly where the linebreaks should go. While textboxes are quite
1133
 
willing to scroll the text, the programmer still must know what width the
1134
 
text will look ``best'' at (where ``best'' means most exactly rectangular;
1135
 
no lines much shorter or much longer then the rest). This common is
1136
 
especially prevalent in internationalized programs, which need to make a
1137
 
wide variety of message string look god on a screen.
1138
 
 
1139
 
To help with this, <literal remap="tt">newt</literal> provides routines to reformat text to look
1140
 
good. It tries different widths to figure out which one will look ``best''
1141
 
to the user. As these commons are almost always used to format text for
1142
 
textbox components, <literal remap="tt">newt</literal> makes it easy to construct a textbox with
1143
 
reflowed text.
1144
 
 
1145
 
 
1146
 
<screen>
1147
 
char * newtReflowText(char * text, int width, int flexDown, int flexUp,
1148
 
                      int * actualWidth, int * actualHeight);
1149
 
newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
1150
 
                                  int flexDown, int flexUp, int flags);
1151
 
int newtTextboxGetNumLines(newtComponent co);
1152
 
</screen></para>
1153
 
 
1154
 
 
1155
 
 
1156
 
<para>
1157
 
<literal remap="tt">newtReflowText()</literal> reflows the <literal remap="tt">text</literal> to a target width of
1158
 
<literal remap="tt">width</literal>. The actual width of the longest line in the returned string is
1159
 
between <literal remap="tt">width - flexDown</literal> and <literal remap="tt">width + flexUp</literal>; the actual maximum
1160
 
line length is chosen to make the displayed check look rectangular. 
1161
 
The <literal remap="tt">int</literal>s pointed to by <literal remap="tt">actualWidth</literal> and <literal remap="tt">actualHeight</literal> are set
1162
 
to the width of the longest line and the number of lines in in the
1163
 
returned text, respectively. Either one may be <literal remap="tt">NULL</literal>. The return
1164
 
value points to the reflowed text, and is allocated through <literal remap="tt">malloc()</literal>.
1165
 
 
1166
 
When the reflowed text is being placed in a textbox it may be easier to use
1167
 
<literal remap="tt">newtTextboxReflowed()</literal>, which creates a textbox, reflows the text, and
1168
 
places the reflowed text in the listbox. It's parameters consist of the
1169
 
position of the final textbox, the width and flex values for the text
1170
 
(which are identical to the parameters passed to <literal remap="tt">newtReflowText()</literal>,
1171
 
and the flags for the textbox (which are the same as the flags for
1172
 
<literal remap="tt">newtTextbox()</literal>. This function does not let you limit the height of the
1173
 
textbox, however, making limiting it's use to constructing textboxes which
1174
 
don't need to scroll.
1175
 
 
1176
 
To find out how tall the textbox created by <literal remap="tt">newtTextboxReflowed()</literal> is, 
1177
 
use <literal remap="tt">newtTextboxGetNumLines()</literal>, which returns the number of lines in the
1178
 
textbox. For textboxes created by <literal remap="tt">newtTextboxReflowed()</literal>, this is
1179
 
always the same as the height of the textbox.
1180
 
 
1181
 
Here's a simple program which uses a textbox to display a message.
1182
 
 
1183
 
 
1184
 
<screen>
1185
 
#include &#60;newt.h&#62;
1186
 
#include &#60;stdlib.h&#62;
1187
 
 
1188
 
char message[] = "This is a pretty long message. It will be displayed "
1189
 
                 "in a newt textbox, and illustrates how to construct "
1190
 
                 "a textbox from arbitrary text which may not have "
1191
 
                 "very good line breaks.\n\n"
1192
 
                 "Notice how literal \\n characters are respected, and "
1193
 
                 "may be used to force line breaks and blank lines.";
1194
 
 
1195
 
void main(void) {
1196
 
    newtComponent form, text, button;
1197
 
 
1198
 
    newtInit();
1199
 
    newtCls();
1200
 
 
1201
 
    text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0);
1202
 
    button = newtButton(12, newtTextboxGetNumLines(text) + 2, "Ok");
1203
 
 
1204
 
    newtOpenWindow(10, 5, 37,
1205
 
                   newtTextboxGetNumLines(text) + 7, "Textboxes");
1206
 
 
1207
 
    form = newtForm(NULL, NULL, 0);
1208
 
    newtFormAddComponents(form, text, button, NULL);
1209
 
 
1210
 
    newtRunForm(form);
1211
 
    newtFormDestroy(form);
1212
 
    newtFinished();
1213
 
}
1214
 
</screen></para></sect3></sect2>
1215
 
 
1216
 
 
1217
 
 
1218
 
<sect2><title>Scrollbars</title>
1219
 
 
1220
 
<para>
1221
 
Scrollbars (which, currently, are always vertical in <literal remap="tt">newt</literal>), may be
1222
 
attached to forms to let them contain more data then they have space for.
1223
 
While the actual process of making scrolling forms is discussed at the end 
1224
 
of this section, we'll go ahead and introduce scrollbars now so you'll be
1225
 
ready.
1226
 
 
1227
 
 
1228
 
<screen>
1229
 
newtComponent newtVerticalScrollbar(int left, int top, int height,
1230
 
                                    int normalColorset, int thumbColorset);
1231
 
</screen>
1232
 
 
1233
 
 
1234
 
When a scrollbar is created, it is given a position on the screen, a
1235
 
height, and two colors. The first color is the color used for drawing the
1236
 
scrollbar, and the second color is used for drawing the thumb. This is the
1237
 
only place in newt where an application specifically sets colors for a
1238
 
component. It's done here to let the colors a scrollbar use match the
1239
 
colors of the component the scrollbar is mated too. When a scrollbar is
1240
 
being used with a form, <literal remap="tt">normalColorset</literal> is often
1241
 
<literal remap="tt">NEWT_COLORSET_WINDOW</literal> and <literal remap="tt">thumbColorset</literal>
1242
 
<literal remap="tt">NEWT_COLORSET_ACTCHECKBOX</literal>. Of course, feel free to peruse
1243
 
<literal remap="tt">&lt;newt.h&gt;</literal> and pick your own colors.
1244
 
 
1245
 
As the scrollbar is normally updated by the component it is mated with,
1246
 
there is no public interface for moving the thumb.</para></sect2>
1247
 
 
1248
 
 
1249
 
<sect2><title>Listboxes</title>
1250
 
<para>
1251
 
Listboxes are the most complicated components 
1252
 
<literal remap="tt">newt</literal> provides. They can
1253
 
allow a single selection or multiple selection, and are easy to update.
1254
 
Unfortunately, their API is also the least consistent of <literal remap="tt">newt</literal>'s
1255
 
components. Each entry in a listbox is a ordered pair of the text which should be
1256
 
displayed for that item and a <emphasis remap="bf">key</emphasis>, which is a <literal remap="tt">void *</literal> that
1257
 
uniquely identifies that listbox item. Many applications pass integers in
1258
 
as keys, but using arbitrary pointers makes many applications significantly
1259
 
easier to code.</para>
1260
 
 
1261
 
<sect3><title>Basic Listboxes</title>
1262
 
 
1263
 
<para>
1264
 
Let's start off by looking at the most important listbox functions.
1265
 
 
1266
 
 
1267
 
<screen>
1268
 
newtComponent newtListbox(int left, int top, int height, int flags);
1269
 
int newtListboxAppendEntry(newtComponent co, const char * text, 
1270
 
                           const void * data);
1271
 
void * newtListboxGetCurrent(newtComponent co);
1272
 
void newtListboxSetWidth(newtComponent co, int width);
1273
 
void newtListboxSetCurrent(newtComponent co, int num);
1274
 
void newtListboxSetCurrentByKey(newtComponent co, void * key);
1275
 
</screen></para>
1276
 
 
1277
 
 
1278
 
 
1279
 
<para>
1280
 
A listbox is created at a certain position and a given height. The
1281
 
<literal remap="tt">height</literal> is used for two things. First of all, it is the minimum
1282
 
height the listbox will use. If there are less items in the listbox then
1283
 
the height, suggests the listbox will still take up that minimum amount
1284
 
of space. Secondly, if the listbox is set to be scrollable (by setting
1285
 
the <literal remap="tt">NEWT_FLAG_SCROLL flag</literal>, the <literal remap="tt">height</literal> is also the maximum height
1286
 
of the listbox. If the listbox may not scroll, it increases its height to
1287
 
display all of its items.
1288
 
 
1289
 
The following flags may be used when creating a listbox:
1290
 
 
1291
 
<variablelist>
1292
 
 
1293
 
<varlistentry>
1294
 
<term>NEWT_FLAG_SCROLL</term>
1295
 
<listitem>
1296
 
<para>The listbox should scroll to display all of the
1297
 
items it contains.</para></listitem>
1298
 
</varlistentry>
1299
 
<varlistentry>
1300
 
<term>NEWT_FLAG_RETURNEXIT</term>
1301
 
<listitem>
1302
 
<para>When the user presses return on an item in the
1303
 
list, the form should return.</para></listitem>
1304
 
</varlistentry>
1305
 
<varlistentry>
1306
 
<term>NEWT_FLAG_BORDER</term>
1307
 
<listitem>
1308
 
<para>A frame is drawn around the listbox, which can make
1309
 
it easier to see which listbox has the focus when a form contains multiple
1310
 
listboxes.</para></listitem>
1311
 
</varlistentry>
1312
 
<varlistentry>
1313
 
<term>NEWT_FLAG_MULTIPLE</term>
1314
 
<listitem>
1315
 
<para>By default, a listbox only lets the user select
1316
 
one item in the list at a time. When this flag is specified, they may
1317
 
select multiple items from the list.</para></listitem></varlistentry>
1318
 
</variablelist></para>
1319
 
 
1320
 
 
1321
 
<para>
1322
 
Once a listbox has been created, items are added to it by invoking
1323
 
<literal remap="tt">newtListboxAppendEntry()</literal>, which adds new items to the end of the list.
1324
 
In addition to the listbox component, <literal remap="tt">newtListboxAppendEntry()</literal> needs
1325
 
both elements of the (text, key) ordered pair. 
1326
 
 
1327
 
For lists which only allow a single selection, <literal remap="tt">newtListboxGetCurrent()</literal>
1328
 
should be used to find out which listbox item is currently selected. It
1329
 
returns the key of the currently selected item.
1330
 
 
1331
 
Normally, a listbox is as wide as it's widest element, plus space for a
1332
 
scrollbar if the listbox is supposed to have one. To make the listbox
1333
 
any larger then that, use <literal remap="tt">newtListboxSetWidth()</literal>, which overrides the
1334
 
natural list of the listbox. Once the width has been set, it's fixed. The
1335
 
listbox will no longer grow to accommodate new entries, so bad things may
1336
 
happen! 
1337
 
 
1338
 
An application can change the current position of the listbox (where the
1339
 
selection bar is displayed) by calling <literal remap="tt">newtListboxSetCurrent()</literal> or
1340
 
<literal remap="tt">newtListboxSetCurrentByKey()</literal>. The first sets the current position to the
1341
 
entry number which is passed as the second argument, with 0 indicating
1342
 
the first entry. <literal remap="tt">newtListboxSetCurrentByKey()</literal> sets the current position
1343
 
to the entry whose <literal remap="tt">key</literal> is passed into the function.</para></sect3>
1344
 
 
1345
 
 
1346
 
<sect3><title>Manipulating Listbox Contents</title>
1347
 
 
1348
 
<para>
1349
 
While the contents of many listboxes never need to change, some applications
1350
 
need to change the contents of listboxes regularly. <literal remap="tt">Newt</literal> includes
1351
 
complete support for updating listboxes. These new functions are in
1352
 
addition to <literal remap="tt">newtListboxAppendEntry()</literal>, which was already discussed.
1353
 
 
1354
 
 
1355
 
<screen>
1356
 
void newtListboxSetEntry(newtComponent co, void * key, const char * text);
1357
 
int newtListboxInsertEntry(newtComponent co, const char * text, 
1358
 
                           const void * data, void * key);
1359
 
int newtListboxDeleteEntry(newtComponent co, void * key);
1360
 
void newtListboxClear(newtComponent co);
1361
 
</screen></para>
1362
 
 
1363
 
 
1364
 
 
1365
 
<para>
1366
 
The first of these, <literal remap="tt">newtListboxSetEntry()</literal>, updates the text for a
1367
 
key which is already in the listbox. The <literal remap="tt">key</literal> specifies which listbox
1368
 
entry should be modified, and <literal remap="tt">text</literal> becomes the new text for that entry
1369
 
in the listbox.
1370
 
 
1371
 
<literal remap="tt">newtListboxInsertEntry()</literal> inserts a new listbox entry <emphasis remap="bf">after</emphasis> an
1372
 
already existing entry, which is specified by the <literal remap="tt">key</literal> parameter.
1373
 
The <literal remap="tt">text</literal> and <literal remap="tt">data</literal> parameters specify the new entry which should
1374
 
be added.
1375
 
 
1376
 
Already-existing entries are removed from a listbox with
1377
 
<literal remap="tt">newtListboxDeleteEntry()</literal>. It removes the listbox entry with the
1378
 
specified <literal remap="tt">key</literal>. If you want to remove all of the entries from a
1379
 
listbox, use <literal remap="tt">newtListboxClear()</literal>.</para></sect3> 
1380
 
 
1381
 
 
1382
 
<sect3><title>Multiple Selections</title>
1383
 
 
1384
 
<para>
1385
 
When a listbox is created with <literal remap="tt">NEWT_FLAG_MULTIPLE</literal>, the user can select
1386
 
multiple items from the list. When this option is used, a different set of
1387
 
functions must be used to manipulate the listbox selection.
1388
 
 
1389
 
 
1390
 
<screen>
1391
 
void newtListboxClearSelection(newtComponent co);
1392
 
void **newtListboxGetSelection(newtComponent co, int *numitems);
1393
 
void newtListboxSelectItem(newtComponent co, const void * key,
1394
 
                           enum newtFlagsSense sense);
1395
 
</screen>
1396
 
 
1397
 
 
1398
 
The simplest of these is <literal remap="tt">newtListboxClearSelection()</literal>, which deselects
1399
 
all of the items in the list (listboxes which allow multiple selections
1400
 
also allow zero selections). <literal remap="tt">newtListboxGetSelection()</literal> returns a
1401
 
pointer to an array which contains the keys for all of the items in the
1402
 
listbox currently selected. The <literal remap="tt">int</literal> pointed to by <literal remap="tt">numitems</literal> is
1403
 
set to the number of items currently selected (and hence the number of
1404
 
items in the returned array). The returned array is dynamically allocated,
1405
 
and must be released through <literal remap="tt">free()</literal>.
1406
 
 
1407
 
<literal remap="tt">newtListboxSelectItem()</literal> lets the program select and deselect specific
1408
 
listbox entries. The <literal remap="tt">key</literal> of the listbox entry is being affected is
1409
 
passed, and <literal remap="tt">sense</literal> is one of <literal remap="tt">NEWT_FLAGS_RESET</literal>, which deselects
1410
 
the entry, <literal remap="tt">NEWT_FLAGS_SET</literal>, which selects the entry, or
1411
 
<literal remap="tt">NEWT_FLAGS_TOGGLE</literal>, which reverses the current selection status.</para></sect3></sect2>
1412
 
 
1413
 
 
1414
 
 
1415
 
<sect2><title>Advanced Forms</title>
1416
 
 
1417
 
<para>
1418
 
Forms, which tie components together, are quite important in the world of
1419
 
<literal remap="tt">newt</literal>. While we've already discussed the basics of forms, we've omitted
1420
 
many of the details.</para>
1421
 
 
1422
 
 
1423
 
<sect3><title>Exiting From Forms</title>
1424
 
 
1425
 
<para>
1426
 
Forms return control to the application for a number of reasons:
1427
 
 
1428
 
 
1429
 
<itemizedlist>
1430
 
<listitem>
1431
 
 
1432
 
<para>
1433
 
A component can force the form to exit. Buttons do this whenever they
1434
 
are pushed, and other components exit when <literal remap="tt">NEWT_FLAG_RETURNEXIT</literal> has
1435
 
been specified.</para></listitem>
1436
 
<listitem>
1437
 
 
1438
 
<para>
1439
 
Applications can setup hot keys which cause the form to exit when
1440
 
they are pressed.</para></listitem>
1441
 
<listitem>
1442
 
 
1443
 
<para>
1444
 
<literal remap="tt">Newt</literal> can exit when file descriptors are ready to be read or
1445
 
ready to be written to.
1446
 
</para>
1447
 
</listitem></itemizedlist>
1448
 
 
1449
 
By default, <literal remap="tt">newt</literal> forms exit when the F12 key is pressed (F12 is setup
1450
 
as a hot key by default). <literal remap="tt">Newt</literal> applications should treat F12 as an
1451
 
``Ok'' button. If applications don't want F12 to exit the form, they can
1452
 
specify <literal remap="tt">NEWT_FLAG_NOF12</literal> as flag when creating the form with 
1453
 
<literal remap="tt">newtForm</literal>.
1454
 
 
1455
 
 
1456
 
<screen>
1457
 
void newtFormAddHotKey(newtComponent co, int key);
1458
 
void newtFormWatchFd(newtComponent form, int fd, int fdFlags);
1459
 
</screen>
1460
 
 
1461
 
 
1462
 
 
1463
 
<screen>
1464
 
void newtDrawForm(newtComponent form);
1465
 
newtComponent newtFormGetCurrent(newtComponent co);
1466
 
void newtFormSetCurrent(newtComponent co, newtComponent subco);
1467
 
void newtFormRun(newtComponent co, struct newtExitStruct * es);
1468
 
</screen>
1469
 
 
1470
 
 
1471
 
 
1472
 
<screen>
1473
 
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
1474
 
void newtFormSetBackground(newtComponent co, int color);
1475
 
void newtFormSetHeight(newtComponent co, int height);
1476
 
void newtFormSetWidth(newtComponent co, int width);
1477
 
</screen>
1478
 
</para>
1479
 
</sect3>
1480
 
</sect2>
1481
 
</sect1>
1482
 
</article>
1483