]> git.ipfire.org Git - thirdparty/newt.git/blob - tutorial.sgml
install python modules to purelib and platlib
[thirdparty/newt.git] / tutorial.sgml
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.31, 2003-Jan-06</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 Red Hat.</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 its 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 its 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 its 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 its 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 of the 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 in 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 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 than 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, its 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 its 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 its 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 its 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 its 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