#! /usr/bin/perl
##
use ExtUtils::testlib;
use Curses;
sub fatal {
clrtobot(0, 0);
addstr(0, 0, "@_\n");
refresh();
sleep 2;
exit 1;
}
sub driveForm($$) {
my ($fwin, $form) = @_;
while (1) {
my $ch = getch($fwin);
if ($ch == KEY_UP) {
form_driver($form, REQ_PREV_FIELD);
} elsif ($ch == KEY_DOWN or $ch eq "\t" or
$ch eq "\r" or $ch eq "\n") {
form_driver($form, REQ_NEXT_FIELD);
} elsif ($ch == KEY_LEFT) {
form_driver($form, REQ_LEFT_CHAR);
} elsif ($ch == KEY_RIGHT) {
form_driver($form, REQ_RIGHT_CHAR);
} elsif ($ch == KEY_NPAGE) {
form_driver($form, REQ_NEXT_PAGE);
} elsif ($ch == KEY_PPAGE) {
form_driver($form, REQ_PREV_PAGE);
} elsif ($ch == KEY_DC or ord($ch) == 8 or ord($ch) == 127) {
form_driver($form, REQ_DEL_PREV);
} elsif ($ch == KEY_F(1)) {
last;
} elsif ($ch =~ /^\S$/) {
form_driver($form, ord($ch));
} else {
beep();
}
}
}
sub makeFields() {
my $flist = [
[ 'L', 0, 0, 0, 8, "Form" ],
[ 'L', 0, 0, 2, 0, "First Name" ],
[ 'F', 1, 15, 2, 12, "F Name" ],
[ 'L', 0, 0, 3, 0, "Last Name" ],
[ 'F', 1, 15, 3, 12, "L Name" ],
[ 'L', 0, 0, 5, 8, "Form (pt 2)" ],
[ 'L', 0, 0, 7, 0, "# Tuits" ],
[ 'F', 1, 5, 7, 12, "Tuits" ],
[ 'L', 0, 0, 8, 0, "# Bleems" ],
[ 'F', 1, 5, 8, 12, "Bleems" ]
];
my @fl;
foreach my $F (@$flist) {
my $field;
# This is a Perl reference to a scalar number variable. The
# number is the numerical equivalent (cast) of the C pointer to the
# executable-Curses FIELD object. The reference is blessed into
# package "Curses::Field", but don't confuse it with a Perl
# object.
if ($F->[0] eq 'L') {
$field = new_field(1, length($F->[5]), $F->[3], $F->[4], 0, 0);
if ($field eq '') {
fatal("new_field $F->[5] failed");
}
set_field_buffer($field, 0, $F->[5]);
field_opts_off($field, O_ACTIVE);
field_opts_off($field, O_EDIT);
} elsif ($F->[0] eq 'F') {
$field = new_field($F->[1], $F->[2], $F->[3], $F->[4], 0, 0);
if ($field eq '') {
fatal("new_field $F->[5] failed");
}
if ($F->[5] eq "Tuits") {
set_field_buffer($field, 0, $F->[5]);
}
set_field_back($field, A_UNDERLINE);
}
push(@fl, $field);
}
return @fl;
}
sub makeForm(@) {
my @fl = @_;
my @pack;
foreach $fieldR (@fl) {
push(@pack, $ {$fieldR});
}
push(@pack, 0);
# new_form()'s argument is a list of fields. Its form is amazingly
# complex:
# The argument is a string whose ASCII encoding is an array of C
# pointers. Each pointer is to a FIELD object of the
# executable-Curses library, except the last is NULL to mark the
# end of the list. For example, assume there are two fields and
# the executable-Curses library represents them with FIELD objects
# whose addresses (pointers) are 0x11223344 and 0x0004080C. The
# argument to Curses::new_form() is a 12 character string whose
# ASCII encoding is 0x112233440004080C00000000 .
# Maybe some day we can provide an alternative where there is an
# actual Perl field object class and the argument is a reference to
# a Perl list of them.
my $form = new_form(pack('L!*', @pack));
if ($form eq '') {
fatal("new_form failed");
}
return $form;
}
sub demo() {
noecho();
eval { new_form() };
if ($@ =~ m{not defined by your vendor}) {
print STDERR "Curses was not compiled with form function.\n";
exit 1;
}
my @fl = makeFields();
my $form = makeForm(@fl);
my $rows;
my $cols;
scale_form($form, $rows, $cols);
my $fwin = newwin($rows + 2, $cols + 4, 4, 0);
my $fsub = derwin($fwin, $rows, $cols, 1, 2);
set_form_win($form, $fwin);
set_form_sub($form, $fsub);
box($fwin, 0, 0);
keypad($fwin, 1);
post_form($form);
addstr(0, 0, "Use KEY_UP/KEY_DOWN/KEY_PPAGE/KEY_NPAGE to navigate");
addstr(1, 0, "Press 'ENTER' to select item, or 'F1' to exit");
addstr(2, 0, "Other alphanumeric characters will enter data");
refresh();
driveForm($fwin, $form);
unpost_form($form);
delwin($fwin);
free_form($form);
map { free_field($_) } @fl;
}
##############################################################################
# MAINLINE
##############################################################################
initscr();
# The eval makes sure if it croaks, we have a chance to restore the
# terminal.
eval { demo() };
endwin();
if ($@) {
print STDERR "Failed. $@\n";
exit(1);
}
exit(0);