1
package UI::Dialog::Backend::ASCII;
2
###############################################################################
3
# Copyright (C) 2004 Kevin C. Krinke <kckrinke@opendoorsoftware.com>
5
# This library is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU Lesser General Public
7
# License as published by the Free Software Foundation; either
8
# version 2.1 of the License, or (at your option) any later version.
10
# This library is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# Lesser General Public License for more details.
15
# You should have received a copy of the GNU Lesser General Public
16
# License along with this library; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
###############################################################################
22
use UI::Dialog::Backend;
23
use Time::HiRes qw( sleep );
26
use vars qw( $VERSION @ISA );
27
@ISA = qw( UI::Dialog::Backend );
31
$| = 1; # turn on autoflush
33
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
39
my $class = ref($proto) || $proto;
40
my $cfg = ((ref($_[0]) eq "HASH") ? $_[0] : (@_) ? { @_ } : {});
43
$self->{'_state'} = {};
44
$self->{'_opts'} = {};
46
#: Dynamic path discovery...
47
my $CFG_PATH = $cfg->{'PATH'};
49
if (ref($CFG_PATH) eq "ARRAY") { $self->{'PATHS'} = $CFG_PATH; }
50
elsif ($CFG_PATH =~ m!:!) { $self->{'PATHS'} = [ split(/:/,$CFG_PATH) ]; }
51
elsif (-d $CFG_PATH) { $self->{'PATHS'} = [ $CFG_PATH ]; }
52
} elsif ($ENV{'PATH'}) { $self->{'PATHS'} = [ split(/:/,$ENV{'PATH'}) ]; }
53
else { $self->{'PATHS'} = ''; }
55
$self->{'_opts'}->{'callbacks'} = $cfg->{'callbacks'} || undef();
56
$self->{'_opts'}->{'timeout'} = $cfg->{'timeout'} || 0;
57
$self->{'_opts'}->{'wait'} = $cfg->{'wait'} || 0;
58
$self->{'_opts'}->{'debug'} = $cfg->{'debug'} || undef();
59
$self->{'_opts'}->{'title'} = $cfg->{'title'} || undef();
60
$self->{'_opts'}->{'backtitle'} = $cfg->{'backtitle'} || undef();
61
$self->{'_opts'}->{'usestderr'} = $cfg->{'usestderr'} || 0;
62
$self->{'_opts'}->{'extra-button'} = $cfg->{'extra-button'} || 0;
63
$self->{'_opts'}->{'extra-label'} = $cfg->{'extra-label'} || undef();
64
$self->{'_opts'}->{'help-button'} = $cfg->{'help-button'} || 0;
65
$self->{'_opts'}->{'help-label'} = $cfg->{'help-label'} || undef();
66
$self->{'_opts'}->{'nocancel'} = $cfg->{'nocancel'} || 0;
67
$self->{'_opts'}->{'maxinput'} = $cfg->{'maxinput'} || 0;
68
$self->{'_opts'}->{'defaultno'} = $cfg->{'defaultno'} || 0;
69
$self->{'_opts'}->{'autoclear'} = $cfg->{'autoclear'} || 0;
70
$self->{'_opts'}->{'clearbefore'} = $cfg->{'clearbefore'} || 0;
71
$self->{'_opts'}->{'clearafter'} = $cfg->{'clearafter'} || 0;
72
$self->{'_opts'}->{'beepbin'} = $cfg->{'beepbin'} || $self->_find_bin('beep') || '/usr/bin/beep';
73
$self->{'_opts'}->{'beepbefore'} = $cfg->{'beepbefore'} || 0;
74
$self->{'_opts'}->{'beepafter'} = $cfg->{'beepafter'} || 0;
75
$self->{'_opts'}->{'pager'} = ( $cfg->{'pager'} ||
76
$self->_find_bin('pager') ||
77
$self->_find_bin('less') ||
78
$self->_find_bin('more') );
79
$self->{'_opts'}->{'stty'} = $cfg->{'stty'} || $self->_find_bin('stty');
81
$self->{'_state'} = {'rv'=>0};
86
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
92
my $text = shift() || return();
94
if (ref($text) eq "ARRAY") { push(@array,@{$text}); }
95
elsif ($text =~ /\\n/) { @array = split(/\\n/,$text); }
96
else { @array = split(/\n/,$text); }
98
$text = join("\n",@array);
99
return($self->_strip_text($text));
103
my $args = (@_ % 2) ? { @_, '_odd' } : { @_ };
104
my $defs = $self->{'_opts'};
105
foreach my $def (keys(%$defs)) {
106
$args->{$def} = $defs->{$def} unless $args->{$def};
108
# alias 'filename' and 'file' to path
109
$args->{'path'} = (($args->{'filename'}) ? $args->{'filename'} :
110
($args->{'file'}) ? $args->{'file'} :
111
($args->{'path'}) ? $args->{'path'} : "");
112
$args->{'clear'} = $args->{'clearbefore'} || $args->{'clearafter'} || $args->{'autoclear'} || 0;
113
$args->{'beep'} = $args->{'beepbefore'} || $args->{'beepafter'} || $args->{'autobeep'} || 0;
117
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
121
#: this is the dynamic 'Colon Command Help'
122
sub _WRITE_HELP_TEXT {
126
Colon Commands: [':?' (This help message)], [':pg <N>' (Go to page 'N')],
127
[':n'|':next' (Go to the next page)], [':p'|':prev' (Go to the previous page)],
128
[':esc'|':escape' (Send the [Esc] signal)].
130
# $head .= ("~" x 79);
131
if ($self->{'_opts'}->{'extra-button'} || $self->{'_opts'}->{'extra-label'}) {
132
$foot .= "[':e'|':extra' (Send the [Extra] signal)]\n";
134
if (!$self->{'_opts'}->{'nocancel'}) {
135
$foot .= "[':c'|':cancel' (Send the [Cancel] signal)]\n";
137
if ($self->{'_opts'}->{'help-button'} || $self->{'_opts'}->{'help-label'}) {
138
$foot .= "[':h'|':help' (Send the [Help] signal)]\n";
140
# $foot .= ("~" x 79)."\n";
141
# $self->msgbox(title=>'Colon Command Help',text=>$head.$body.$foot);
142
$self->msgbox(title=>'Colon Command Help',text=>$body.$foot);
145
#: this returns the labels (or ' ') for the "extra", "help" and
149
my $cfg = $self->_merge_attrs(@_);
150
my ($help,$cancel,$extra) = (' ',' ',' ');
151
$extra = "Extra" if $cfg->{'extra-button'};
152
$extra = $cfg->{'extra-label'} if $cfg->{'extra-label'};
153
$extra = "':e'=[".$extra."]" if $extra and $extra ne ' ';
154
$help = "Help" if $cfg->{'help-button'};
155
$help = $self->{'help-label'} if $cfg->{'help-label'};
156
$help = "':h'=[".$help."]" if $help and $help ne ' ';
157
$cancel = "Cancel" unless $cfg->{'nocancel'};
158
$cancel = $cfg->{'cancellabel'} if $cfg->{'cancellabel'};
159
$cancel = "':c'=[".$cancel."]" if $cancel and $cancel ne ' ';
160
return($help,$cancel,$extra);
164
#: this writes a standard ascii interface to STDOUT. This is intended for use
165
#: with any non-list native ascii mode widgets.
168
my $cfg = $self->_merge_attrs(@_);
169
my $text = $self->_organize_text($cfg->{'text'}) || " ";
170
my $backtitle = $cfg->{'backtitle'} || " ";
171
my $title = $cfg->{'title'} || " ";
173
+-----------------------------------------------------------------------------+
174
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
176
+-----------------------------------------------------------------------------+
178
| +-------------------------------------------------------------------------+ |
179
| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
181
| +-------------------------------------------------------------------------+ |
182
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
184
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
186
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
188
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
190
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
192
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
194
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
196
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
198
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
200
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
202
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
204
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
206
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
208
| +-------------------------------------------------------------------------+ |
210
+-----------------------------------------------------------------------------+
214
select(STDERR) unless not $cfg->{'usestderr'};
219
select($_fh) unless not $cfg->{'usestderr'};
223
#: very much like _WRITE_TEXT() except that this is specifically for
224
#: the menu() widget only.
227
my $cfg = $self->_merge_attrs(@_);
228
my $text = $self->_organize_text($cfg->{'text'}) || " ";
229
my $backtitle = $cfg->{'backtitle'} || " ";
230
my $title = $cfg->{'title'} || " ";
231
my $menu = $cfg->{'menu'} || [];
232
my ($help,$cancel,$extra) = $self->_BUTTONS(@_);
234
+-----------------------------------------------------------------------------+
235
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
237
+-----------------------------------------------------------------------------+
239
| +-------------------------------------------------------------------------+ |
240
| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
242
| +-------------------------------------------------------------------------+ |
243
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
245
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
247
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
249
| +-------------------------------------------------------------------------+ |
250
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
251
($menu->[0]||' '),($menu->[1]||' '),($menu->[2]||' '),($menu->[3]||' '),($menu->[4]||' '),($menu->[5]||' ')
252
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
253
($menu->[6]||' '),($menu->[7]||' '),($menu->[8]||' '),($menu->[9]||' '),($menu->[10]||' '),($menu->[11]||' ')
254
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
255
($menu->[12]||' '),($menu->[13]||' '),($menu->[14]||' '),($menu->[15]||' '),($menu->[16]||' '),($menu->[17]||' ')
256
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
257
($menu->[18]||' '),($menu->[19]||' '),($menu->[20]||' '),($menu->[21]||' '),($menu->[22]||' '),($menu->[23]||' ')
258
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
259
($menu->[24]||' '),($menu->[25]||' '),($menu->[26]||' '),($menu->[27]||' '),($menu->[28]||' '),($menu->[29]||' ')
260
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
261
($menu->[30]||' '),($menu->[31]||' '),($menu->[32]||' '),($menu->[33]||' '),($menu->[34]||' '),($menu->[35]||' ')
262
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
263
($menu->[36]||' '),($menu->[37]||' '),($menu->[38]||' '),($menu->[39]||' '),($menu->[42]||' '),($menu->[43]||' ')
264
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
265
($menu->[42]||' '),($menu->[43]||' '),($menu->[44]||' '),($menu->[45]||' '),($menu->[46]||' '),($menu->[47]||' ')
266
| @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
267
($menu->[48]||' '),($menu->[49]||' '),($menu->[50]||' '),($menu->[51]||' '),($menu->[52]||' '),($menu->[53]||' ')
268
| @|||||||||||||||||||| @||||||||||||||||||| @||||||||||||||||||| |
270
| ':?' = [Colon Command Help] |
271
+-----------------------------------------------------------------------------+
275
select(STDERR) unless not $cfg->{'usestderr'};
280
select($_fh) unless not $cfg->{'usestderr'};
284
#: very much like _WRITE_MENU() except that this is specifically for
285
#: the radiolist() and checklist() widgets only.
288
my $cfg = $self->_merge_attrs(@_);
289
my $text = $self->_organize_text($cfg->{'text'}) || " ";
290
my $backtitle = $cfg->{'backtitle'} || " ";
291
my $title = $cfg->{'title'} || " ";
293
push(@{$menu},@{$cfg->{'menu'}});
294
my ($help,$cancel,$extra) = $self->_BUTTONS(@_);
298
for (my $i = 2; $i < $m; $i += 3) {
299
if ($menu->[$i] && $menu->[$i] =~ /on/i) { $menu->[$i] = '->'; }
300
else { $menu->[$i] = ' '; }
304
for (my $i = 2; $i < $m; $i += 3) {
305
if (!$mark && $menu->[$i] && $menu->[$i] =~ /on/i) { $menu->[$i] = '->'; $mark = 1; }
306
else { $menu->[$i] = ' '; }
311
+-----------------------------------------------------------------------------+
312
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
314
+-----------------------------------------------------------------------------+
316
| +-------------------------------------------------------------------------+ |
317
| | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
319
| +-------------------------------------------------------------------------+ |
320
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
322
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
324
| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
326
| +-------------------------------------------------------------------------+ |
327
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
328
($menu->[2]||' '),($menu->[0]||' '),($menu->[1]||' '), ($menu->[5]||' '),($menu->[3]||' '),($menu->[4]||' '), ($menu->[8]||' '),($menu->[6]||' '),($menu->[7]||' ')
329
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
330
($menu->[11]||' '),($menu->[9]||' '),($menu->[10]||' '), ($menu->[14]||' '),($menu->[12]||' '),($menu->[13]||' '), ($menu->[17]||' '),($menu->[15]||' '),($menu->[16]||' ')
331
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
332
($menu->[20]||' '),($menu->[18]||' '),($menu->[19]||' '), ($menu->[23]||' '),($menu->[21]||' '),($menu->[22]||' '), ($menu->[26]||' '),($menu->[24]||' '),($menu->[25]||' ')
333
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
334
($menu->[29]||' '),($menu->[27]||' '),($menu->[28]||' '), ($menu->[32]||' '),($menu->[30]||' '),($menu->[31]||' '), ($menu->[35]||' '),($menu->[33]||' '),($menu->[34]||' ')
335
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
336
($menu->[38]||' '),($menu->[36]||' '),($menu->[37]||' '), ($menu->[41]||' '),($menu->[39]||' '),($menu->[40]||' '), ($menu->[44]||' '),($menu->[42]||' '),($menu->[43]||' ')
337
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
338
($menu->[47]||' '),($menu->[45]||' '),($menu->[46]||' '), ($menu->[50]||' '),($menu->[48]||' '),($menu->[49]||' '), ($menu->[53]||' '),($menu->[51]||' '),($menu->[52]||' ')
339
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
340
($menu->[56]||' '),($menu->[54]||' '),($menu->[55]||' '), ($menu->[59]||' '),($menu->[57]||' '),($menu->[58]||' '), ($menu->[62]||' '),($menu->[60]||' '),($menu->[61]||' ')
341
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
342
($menu->[65]||' '),($menu->[63]||' '),($menu->[64]||' '), ($menu->[68]||' '),($menu->[66]||' '),($menu->[67]||' '), ($menu->[71]||' '),($menu->[69]||' '),($menu->[70]||' ')
343
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
344
($menu->[74]||' '),($menu->[72]||' '),($menu->[73]||' '), ($menu->[77]||' '),($menu->[75]||' '),($menu->[76]||' '), ($menu->[80]||' '),($menu->[78]||' '),($menu->[79]||' ')
345
|@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
346
($menu->[83]||' '),($menu->[81]||' '),($menu->[82]||' '), ($menu->[86]||' '),($menu->[84]||' '),($menu->[85]||' '), ($menu->[89]||' '),($menu->[87]||' '),($menu->[88]||' ')
347
| @|||||||||||||||||||| @||||||||||||||||||| @||||||||||||||||||| |
349
| ':?' = [Colon Command Help] |
350
+-----------------------------------------------------------------------------+
354
select(STDERR) unless not $cfg->{'usestderr'};
359
select($_fh) unless not $cfg->{'usestderr'};
365
my $stderr = shift();
373
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
377
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
378
#: Ask a binary question (Yes/No)
381
my $caller = (caller(1))[3] || 'main';
382
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
383
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
384
my $args = $self->_pre($caller,@_);
385
my ($YN,$RESP) = ('Yes|no','YES_OR_NO');
386
$YN = "yes|No" if $self->{'defaultno'};
387
while ($RESP !~ /^(y|yes|n|no)$/i) {
388
$self->_clear($args->{'clear'});
389
$self->_WRITE_TEXT(@_,text=>$args->{'text'});
390
$self->_PRINT($args->{'usestderr'},"(".$YN."): ");
391
chomp($RESP = <STDIN>);
392
if (!$RESP && $args->{'defaultno'}) { $RESP = "no"; }
393
elsif (!$RESP && !$args->{'defaultno'}) { $RESP = "yes"; }
394
if ($RESP =~ /^(y|yes)$/i) {
405
return(1) if $self->state() eq "OK";
409
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
413
my $caller = (caller(1))[3] || 'main';
414
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
415
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
416
my $args = $self->_pre($caller,@_);
417
my $length = $args->{'maxinput'} + 1;
418
my $text = $args->{'text'};
421
while ($length > $args->{'maxinput'}) {
422
$self->_clear($args->{'clear'});
423
$self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
424
$self->_PRINT($args->{'usestderr'},"input: ");
425
chomp($string = <STDIN>);
426
if ($args->{'maxinput'}) {
427
$length = length($string);
431
if ($length > $args->{'maxinput'}) {
432
$self->_PRINT($args->{'usestderr'},"error: too many charaters input,".
433
" the maximum is: ".$args->{'maxinput'}."\n");
443
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
447
my $caller = (caller(1))[3] || 'main';
448
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
449
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
450
my $args = $self->_pre($caller,@_);
451
croak("The UI::Dialog::Backend::ASCII password widget depends on the stty ".
452
"binary. This was not found or is not executable.")
453
unless -x $args->{'stty'};
454
my ($length,$key) = ($args->{'maxinput'} + 1,'');
456
my $text = $args->{'text'};
458
my $ENV_PATH = $ENV{'PATH'};
460
while ($length > $args->{'maxinput'}) {
461
$self->_clear($args->{'clear'});
462
$self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
463
$self->_PRINT($args->{'usestderr'},"input: ");
464
if ($self->_is_bsd()) { system "$args->{'stty'} cbreak </dev/tty >/dev/tty 2>&1"; }
465
else { system $args->{'stty'}, '-icanon', 'eol', "\001"; }
466
while ($key = getc(STDIN)) {
467
last if $key =~ /\n/;
468
if ($key =~ /^\x1b$/) {
469
#this could be the DELETE key (not BS or ^H)
470
# ^[[3~ or \x1b\x5b\x33\x7e (aka: ESC + [ + 3 + ~)
471
my $key2 = getc(STDIN);
472
if ($key2 =~ /^\x5b$/) {
473
my $key3 = getc(STDIN);
474
if ($key3 =~ /^\x33$/) {
475
my $key4 = getc(STDIN);
476
if ($key4 =~ /^\x7e$/) {
478
# go back five spaces and print five spaces (erase ^[[3~)
479
# go back five spaces again (backtrack),
480
# go back one space, print a space and go back (erase *)
481
if ($args->{'usestderr'}) {
482
print STDERR "\b\b\b\b\b"." "."\b\b\b\b\b"."\b \b";
484
print STDOUT "\b\b\b\b\b"." "."\b\b\b\b\b"."\b \b";
487
$key = $key.$key2.$key3.$key4;
490
$key = $key.$key2.$key3;
495
} elsif ($key =~ /^(?:\x08|\x7f)$/) {
496
# this is either a BS or ^H
498
# go back two spaces and print two spaces (erase ^H)
499
# go back two spaces again (backtrack),
500
# go back one space, print a space and go back (erase *)
501
if ($args->{'usestderr'}) {
502
print STDERR "\b\b"." "."\b\b"."\b \b";
504
print STDOUT "\b\b"." "."\b\b"."\b \b";
507
if ($args->{'usestderr'}) {
515
if ($self->_is_bsd()) { system "$args->{'stty'} -cbreak </dev/tty >/dev/tty 2>&1"; }
516
else { system $args->{'stty'}, 'icanon', 'eol', '^@'; }
517
if ($args->{'maxinput'}) { $length = length($string); }
518
else { $length = 0; }
519
if ($length > $args->{'maxinput'}) {
520
$self->_PRINT($args->{'usestderr'},"error: too many charaters input,".
521
" the maximum is: ".$args->{'maxinput'}."\n");
524
$ENV{'PATH'} = $ENV_PATH;
532
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
536
my $caller = (caller(1))[3] || 'main';
537
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
538
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
539
my $args = $self->_pre($caller,@_);
540
$self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
541
$self->_PRINT($args->{'usestderr'});
542
my $s = int(($args->{'wait'}) ? $args->{'wait'} :
543
($args->{'timeout'}) ? ($args->{'timeout'} / 1000.0) : 1.0);
552
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
556
my $caller = (caller(1))[3] || 'main';
557
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
558
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
559
my $args = $self->_pre($caller,@_);
560
$self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
561
$self->_PRINT($args->{'usestderr'},(" " x 25)."[ Press Enter to Continue ]");
571
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
575
my $caller = (caller(1))[3] || 'main';
576
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
577
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
578
my $args = $self->_pre($caller,@_);
580
if (-r $args->{'path'}) {
581
my $ENV_PATH = $ENV{'PATH'};
583
if ($ENV{'PAGER'} && -x $ENV{'PAGER'}) {
584
system($ENV{'PAGER'}." ".$args->{'path'});
586
} elsif (-x $args->{'pager'}) {
587
system($args->{'pager'}." ".$args->{'path'});
590
open(ATBFILE,"<".$args->{'path'});
592
my $data = <ATBFILE>;
594
$self->_PRINT($args->{'usestderr'},$data);
596
$ENV{'PATH'} = $ENV_PATH;
598
return($self->msgbox('title'=>'error','text'=>$args->{'path'}.' is not a readable text file.'));
600
$self->rv($rv||'null');
607
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
611
my $caller = (caller(1))[3] || 'main';
612
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
613
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
614
my $args = $self->_pre($caller,@_);
615
$args->{'menu'} = $args->{'list'} if ref($args->{'list'}) eq "ARRAY";
619
$m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
620
my ($valid,$menu,$realm) = ([],[],[]);
621
push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
623
for (my $i = 0; $i < $m; $i += 2) { push(@{$valid},$menu->[$i]); }
625
if (@{$menu} >= 60) {
629
for (my $i = 0; $i < 60; $i++) {
630
push(@{$realm->[$c]},shift(@{$menu}));
636
push(@{$realm->[0]},@{$menu});
640
$self->_WRITE_MENU(@_,'text'=>$args->{'text'},
641
'menu'=>$realm->[($pg - 1||0)]);
642
$self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
643
chomp($rs = <STDIN>);
644
if ($rs =~ /^:\?$/i) {
645
$self->_clear($args->{'clear'});
646
$self->_WRITE_HELP_TEXT();
649
} elsif ($rs =~ /^:(esc|escape)$/i) {
650
$self->_clear($args->{'clear'});
654
} elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
657
} elsif ($args->{'help-button'} && $rs =~ /^:(h|help)$/i) {
658
$self->_clear($args->{'clear'});
661
return($self->state());
662
} elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
663
$self->_clear($args->{'clear'});
666
return($self->state());
667
} elsif ($rs =~ /^:pg\s*(\d+)$/i) {
669
if ($p <= @{$realm} && $p > 0) { $pg = $p; }
671
} elsif ($rs =~ /^:(n|next)$/i) {
672
if ($pg < @{$realm}) { $pg++; }
675
} elsif ($rs =~ /^:(p|prev)$/i) {
676
if ($pg > 1) { $pg--; }
677
else { $pg = @{$realm}; }
680
if (@_ = grep { /^\Q$rs\E$/i } @{$valid}) { $rs = $_[0]; }
683
$self->_clear($args->{'clear'});
693
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
694
#: A multi-selectable list
697
my $caller = (caller(1))[3] || 'main';
698
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
699
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
700
my $args = $self->_pre($caller,@_);
701
my $menulist = ($args->{'menu'} || $args->{'list'});
703
if (ref($menulist) eq "ARRAY") {
704
#: flatten our multidimensional array
705
foreach my $item (@$menulist) {
706
if (ref($item) eq "ARRAY") {
707
pop(@{$item}) if @$item == 3;
708
push(@$menufix,@{$item});
710
push(@$menufix,$item);
714
$args->{'menu'} = $menufix;
719
$m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
720
my ($valid,$menu,$realm) = ([],[],[]);
721
push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
723
for (my $i = 0; $i < $m; $i += 3) { push(@{$valid},$menu->[$i]); }
725
if (@{$menu} >= 90) {
729
for (my $i = 0; $i < 90; $i++) {
730
push(@{$realm->[$c]},shift(@{$menu}));
736
push(@{$realm->[0]},@{$menu});
741
$self->_WRITE_LIST(@_,'wm'=>'check','text'=>$args->{'text'},'menu'=>$realm->[($pg - 1||0)]);
742
$self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
743
chomp($rs = <STDIN>);
744
if ($rs =~ /^:\?$/i) {
745
$self->_clear($args->{'clear'});
746
$self->_WRITE_HELP_TEXT();
749
} elsif ($rs =~ /^:(esc|escape)$/i) {
750
$self->_clear($args->{'clear'});
753
return($self->state());
754
} elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
755
$self->_clear($args->{'clear'});
757
return($self->state());
758
} elsif (($args->{'help-button'} || $args->{'help-label'}) && $rs =~ /^:(h|help)$/i) {
759
$self->_clear($args->{'clear'});
763
} elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
764
$self->_clear($args->{'clear'});
767
return($self->state());
768
} elsif ($rs =~ /^:pg\s*(\d+)$/i) {
770
if ($p <= @{$realm} && $p > 0) { $pg = $p; }
771
} elsif ($rs =~ /^:(n|next)$/i) {
772
if ($pg < @{$realm}) { $pg++; }
774
} elsif ($rs =~ /^:(p|prev)$/i) {
775
if ($pg > 1) { $pg--; }
776
else { $pg = @{$realm}; }
778
my @opts = split(/\,\s|\,|\s/,$rs);
780
foreach my $opt (@opts) {
781
if (@_ = grep { /^\Q$opt\E$/i } @{$valid}) { push(@good,$_[0]); }
783
if (@opts == @good) {
789
$self->_clear($args->{'clear'});
795
$self->rs(join("\n",@$ra));
800
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
801
#: A radio button based list. very much like the menu widget.
804
my $caller = (caller(1))[3] || 'main';
805
$caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
806
if ($_[0] && $_[0] eq 'caller') { shift(); $caller = shift(); }
807
my $args = $self->_pre($caller,@_);
808
my $menulist = ($args->{'menu'} || $args->{'list'});
810
if (ref($menulist) eq "ARRAY") {
811
#: flatten our multidimensional array
812
foreach my $item (@$menulist) {
813
if (ref($item) eq "ARRAY") {
814
pop(@{$item}) if @$item == 3;
815
push(@$menufix,@{$item});
817
push(@$menufix,$item);
821
$args->{'menu'} = $menufix;
824
$m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
825
my ($valid,$menu,$realm) = ([],[],[]);
826
push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
828
for (my $i = 0; $i < $m; $i += 3) { push(@{$valid},$menu->[$i]); }
830
if (@{$menu} >= 90) {
834
for (my $i = 0; $i < 90; $i++) {
835
push(@{$realm->[$c]},shift(@{$menu}));
841
push(@{$realm->[0]},@{$menu});
845
$self->_WRITE_LIST(@_,'text'=>$args->{'text'},'menu'=>$realm->[($pg - 1||0)]);
846
$self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
847
chomp($rs = <STDIN>);
848
if ($rs =~ /^:\?$/i) {
849
$self->_clear($args->{'clear'});
850
$self->_WRITE_HELP_TEXT();
853
} elsif ($rs =~ /^:(esc|escape)$/i) {
854
$self->_clear($args->{'clear'});
858
} elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
860
return($self->state());
861
} elsif (($args->{'help-button'} || $args->{'help-label'}) && $rs =~ /^:(h|help)$/i) {
862
$self->_clear($args->{'clear'});
865
return($self->state());
866
} elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
867
$self->_clear($args->{'clear'});
870
return($self->state());
871
} elsif ($rs =~ /^:pg\s*(\d+)$/i) {
873
if ($p <= @{$realm} && $p > 0) { $pg = $p; }
875
} elsif ($rs =~ /^:(n|next)$/i) {
876
if ($pg < @{$realm}) { $pg++; }
879
} elsif ($rs =~ /^:(p|prev)$/i) {
880
if ($pg > 1) { $pg--; }
881
else { $pg = @{$realm}; }
884
if (@_ = grep { /^\Q$rs\E$/i } @{$valid}) { $rs = $_[0]; }
887
$self->_clear($args->{'clear'});
898
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
899
#: Simple ASCII progress indicator :)
902
if (!$self->{'__SPIN'} || $self->{'__SPIN'} == 1) { $self->{'__SPIN'} = 2; return("\b|"); }
903
elsif ($self->{'__SPIN'} == 2) { $self->{'__SPIN'} = 3; return("\b/"); }
904
elsif ($self->{'__SPIN'} == 3) { $self->{'__SPIN'} = 4; return("\b-"); }
905
elsif ($self->{'__SPIN'} == 4) { $self->{'__SPIN'} = 1; return("\b\\"); }
908
#:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
909
#: Simple ASCII meter bar
910
# the idea of a "true" dialog like gauge widget with ASCII is not that bad and
911
# as such, I've named these methods differently so as to keep the namespace
912
# open for gauge_*() widgets.
915
my $args = $self->_merge_attrs(@_);
916
my $length = $args->{'length'} || $args->{'width'} || 74;
917
my $bar = ($args->{'bar'} || "-") x $length;
918
my $current = $args->{'current'} || 0;
919
my $total = $args->{'total'} || 0;
920
my $percent = (($current && $total) ? int($current / ($total / 100)) :
921
($args->{'percent'} || '0'));
922
$percent = int(($percent <= 100 && $percent >= 0) ? $percent : 0 );
923
my $perc = int((($length / 100) * $percent));
924
substr($bar,($perc||0),1,($args->{'mark'}||"|"));
925
my $text = (($percent =~ /^\d$/) ? " " :
926
($percent =~ /^\d\d$/) ? " " : "").$percent."% ".$bar;
927
$self->_PRINT($args->{'usestderr'},(($args->{'noCR'} && not $args->{'CR'}) ? "" : "\x0D").$text);
932
my $args = $self->_merge_attrs(@_);
933
$self->_PRINT($args->{'usestderr'},"\n");