File Coverage

blib/lib/UI/Dialog/Backend/ASCII.pm
Criterion Covered Total %
statement 72 681 10.5
branch 5 292 1.7
condition 24 273 8.7
subroutine 14 34 41.1
pod 13 13 100.0
total 128 1293 9.9


line stmt bran cond sub pod time code
1             package UI::Dialog::Backend::ASCII;
2             ###############################################################################
3             # Copyright (C) 2015 Kevin C. Krinke
4             #
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.
9             #
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.
14             #
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             ###############################################################################
19 1     1   21817 use 5.006;
  1         3  
20 1     1   4 use strict;
  1         2  
  1         22  
21 1     1   5 use Carp;
  1         5  
  1         99  
22 1     1   636 use UI::Dialog::Backend;
  1         4  
  1         46  
23 1     1   7441 use Time::HiRes qw( sleep );
  1         3338  
  1         6  
24              
25             BEGIN {
26 1     1   335 use vars qw( $VERSION @ISA );
  1         3  
  1         103  
27 1     1   17 @ISA = qw( UI::Dialog::Backend );
28 1         2873 $VERSION = '1.11';
29             }
30              
31             $| = 1; # turn on autoflush
32              
33             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
34             #: Constructor Method
35             #:
36              
37             sub new {
38 1     1 1 477 my $proto = shift();
39 1   33     8 my $class = ref($proto) || $proto;
40 1 50       6 my $cfg = ((ref($_[0]) eq "HASH") ? $_[0] : (@_) ? { @_ } : {});
    50          
41 1         1 my $self = {};
42 1         19 bless($self, $class);
43 1         9 $self->{'_state'} = {};
44 1         3 $self->{'_opts'} = {};
45              
46             #: Dynamic path discovery...
47 1         3 my $CFG_PATH = $cfg->{'PATH'};
48 1 50       7 if ($CFG_PATH) {
    50          
49 0 0       0 if (ref($CFG_PATH) eq "ARRAY") {
    0          
    0          
50 0         0 $self->{'PATHS'} = $CFG_PATH;
51             }
52             elsif ($CFG_PATH =~ m!:!) {
53 0         0 $self->{'PATHS'} = [ split(/:/,$CFG_PATH) ];
54             }
55             elsif (-d $CFG_PATH) {
56 0         0 $self->{'PATHS'} = [ $CFG_PATH ];
57             }
58             }
59             elsif ($ENV{'PATH'}) {
60 1         9 $self->{'PATHS'} = [ split(/:/,$ENV{'PATH'}) ];
61             }
62             else {
63 0         0 $self->{'PATHS'} = '';
64             }
65              
66 1   50     7 $self->{'_opts'}->{'callbacks'} = $cfg->{'callbacks'} || undef();
67 1   50     6 $self->{'_opts'}->{'timeout'} = $cfg->{'timeout'} || 0;
68 1   50     6 $self->{'_opts'}->{'wait'} = $cfg->{'wait'} || 0;
69 1   50     6 $self->{'_opts'}->{'debug'} = $cfg->{'debug'} || undef();
70 1   50     5 $self->{'_opts'}->{'title'} = $cfg->{'title'} || undef();
71 1   50     7 $self->{'_opts'}->{'backtitle'} = $cfg->{'backtitle'} || undef();
72 1   50     7 $self->{'_opts'}->{'usestderr'} = $cfg->{'usestderr'} || 0;
73 1   50     7 $self->{'_opts'}->{'extra-button'} = $cfg->{'extra-button'} || 0;
74 1   50     5 $self->{'_opts'}->{'extra-label'} = $cfg->{'extra-label'} || undef();
75 1   50     13 $self->{'_opts'}->{'help-button'} = $cfg->{'help-button'} || 0;
76 1   50     6 $self->{'_opts'}->{'help-label'} = $cfg->{'help-label'} || undef();
77 1   50     6 $self->{'_opts'}->{'nocancel'} = $cfg->{'nocancel'} || 0;
78 1   50     6 $self->{'_opts'}->{'maxinput'} = $cfg->{'maxinput'} || 0;
79 1   50     10 $self->{'_opts'}->{'defaultno'} = $cfg->{'defaultno'} || 0;
80 1   50     6 $self->{'_opts'}->{'autoclear'} = $cfg->{'autoclear'} || 0;
81 1   50     6 $self->{'_opts'}->{'clearbefore'} = $cfg->{'clearbefore'} || 0;
82 1   50     6 $self->{'_opts'}->{'clearafter'} = $cfg->{'clearafter'} || 0;
83 1   50     12 $self->{'_opts'}->{'beepbin'} = $cfg->{'beepbin'} || $self->_find_bin('beep') || '/usr/bin/beep';
84 1   50     11 $self->{'_opts'}->{'beepbefore'} = $cfg->{'beepbefore'} || 0;
85 1   50     6 $self->{'_opts'}->{'beepafter'} = $cfg->{'beepafter'} || 0;
86 1   33     12 $self->{'_opts'}->{'pager'} = ( $cfg->{'pager'} ||
87             $self->_find_bin('pager') ||
88             $self->_find_bin('less') ||
89             $self->_find_bin('more') );
90 1   33     36 $self->{'_opts'}->{'stty'} = $cfg->{'stty'} || $self->_find_bin('stty');
91              
92             $self->{'_opts'}->{'trust-input'} =
93             ( exists $cfg->{'trust-input'}
94 1 50 33     13 && $cfg->{'trust-input'}==1
95             ) ? 1 : 0;
96              
97 1         7 $self->{'_state'} = {'rv'=>0};
98              
99 1         34 return($self);
100             }
101              
102             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
103             #: Iherited Overrides
104             #:
105              
106             sub _organize_text {
107 0     0     my $self = shift();
108 0   0       my $text = shift() || return();
109 0           my @array;
110 0 0         if (ref($text) eq "ARRAY") {
    0          
111 0           push(@array,@{$text});
  0            
112             }
113             elsif ($text =~ /\\n/) {
114 0           @array = split(/\\n/,$text);
115             }
116             else {
117 0           @array = split(/\n/,$text);
118             }
119 0           $text = undef();
120 0           $text = join("\n",@array);
121 0           return($self->_strip_text($text));
122             }
123             sub _merge_attrs {
124 0     0     my $self = shift();
125 0 0         my $args = (@_ % 2) ? { @_, '_odd' } : { @_ };
126 0           my $defs = $self->{'_opts'};
127 0           foreach my $def (keys(%$defs)) {
128 0 0         $args->{$def} = $defs->{$def} unless $args->{$def};
129             }
130             # alias 'filename' and 'file' to path
131             $args->{'path'} = (($args->{'filename'}) ? $args->{'filename'} :
132             ($args->{'file'}) ? $args->{'file'} :
133 0 0         ($args->{'path'}) ? $args->{'path'} : "");
    0          
    0          
134 0   0       $args->{'clear'} = $args->{'clearbefore'} || $args->{'clearafter'} || $args->{'autoclear'} || 0;
135 0   0       $args->{'beep'} = $args->{'beepbefore'} || $args->{'beepafter'} || $args->{'autobeep'} || 0;
136 0           return($args);
137             }
138              
139             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
140             #: Private Methods
141             #:
142              
143             #: this is the dynamic 'Colon Command Help'
144             sub _WRITE_HELP_TEXT {
145 0     0     my $self = shift();
146 0           my ($head,$foot);
147 0           my $body = "
148             Colon Commands: [':?' (This help message)], [':pg ' (Go to page 'N')],
149             [':n'|':next' (Go to the next page)], [':p'|':prev' (Go to the previous page)],
150             [':esc'|':escape' (Send the [Esc] signal)].
151             ";
152             # $head .= ("~" x 79);
153 0 0 0       if ($self->{'_opts'}->{'extra-button'} || $self->{'_opts'}->{'extra-label'}) {
154 0           $foot .= "[':e'|':extra' (Send the [Extra] signal)]\n";
155             }
156 0 0         if (!$self->{'_opts'}->{'nocancel'}) {
157 0           $foot .= "[':c'|':cancel' (Send the [Cancel] signal)]\n";
158             }
159 0 0 0       if ($self->{'_opts'}->{'help-button'} || $self->{'_opts'}->{'help-label'}) {
160 0           $foot .= "[':h'|':help' (Send the [Help] signal)]\n";
161             }
162             # $foot .= ("~" x 79)."\n";
163             # $self->msgbox(title=>'Colon Command Help',text=>$head.$body.$foot);
164 0           $self->msgbox(title=>'Colon Command Help',text=>$body.$foot);
165             }
166              
167             #: this returns the labels (or ' ') for the "extra", "help" and
168             #: "cancel" buttons.
169             sub _BUTTONS {
170 0     0     my $self = shift();
171 0           my $cfg = $self->_merge_attrs(@_);
172 0           my ($help,$cancel,$extra) = (' ',' ',' ');
173 0 0         $extra = "Extra" if $cfg->{'extra-button'};
174 0 0         $extra = $cfg->{'extra-label'} if $cfg->{'extra-label'};
175 0 0 0       $extra = "':e'=[".$extra."]" if $extra and $extra ne ' ';
176 0 0         $help = "Help" if $cfg->{'help-button'};
177 0 0         $help = $self->{'help-label'} if $cfg->{'help-label'};
178 0 0 0       $help = "':h'=[".$help."]" if $help and $help ne ' ';
179 0 0         $cancel = "Cancel" unless $cfg->{'nocancel'};
180 0 0         $cancel = $cfg->{'cancellabel'} if $cfg->{'cancellabel'};
181 0 0 0       $cancel = "':c'=[".$cancel."]" if $cancel and $cancel ne ' ';
182 0           return($help,$cancel,$extra);
183             }
184              
185              
186             #: this writes a standard ascii interface to STDOUT. This is intended for use
187             #: with any non-list native ascii mode widgets.
188 0           sub _WRITE_TEXT {
189 0     0     my $self = shift();
190 0           my $cfg = $self->_merge_attrs(@_);
191 0           my $text = "";
192 0 0         if ($cfg->{'literal'}) {
193 0   0       $text = $cfg->{'text'} || '';
194             }
195             else {
196 0   0       $text = $self->_organize_text($cfg->{'text'}) || "";
197             }
198 0           $self->clean_format($cfg->{'trust-input'},\$text);
199 0   0       my $backtitle = $cfg->{'backtitle'} || " ";
200 0   0       my $title = $cfg->{'title'} || " ";
201             format ASCIIPGTXT =
202             +-----------------------------------------------------------------------------+
203             | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
204             $backtitle
205             +-----------------------------------------------------------------------------+
206             | |
207             | +-------------------------------------------------------------------------+ |
208             | | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
209             $title
210             | +-------------------------------------------------------------------------+ |
211             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
212             $text
213             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
214             $text
215             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
216             $text
217             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
218             $text
219             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
220             $text
221             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
222             $text
223             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
224             $text
225             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
226             $text
227             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
228             $text
229             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
230             $text
231             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
232             $text
233             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
234             $text
235             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
236             $text
237             | +-------------------------------------------------------------------------+ |
238             | |
239             +-----------------------------------------------------------------------------+
240             .
241 1     1   10 no strict 'subs';
  1         17  
  1         173  
242 0           my $_fh = select();
243 0 0         select(STDERR) unless not $cfg->{'usestderr'};
244 0           my $LFMT = $~;
245 0           $~ = ASCIIPGTXT;
246 0           write();
247 0           $~= $LFMT;
248 0 0         select($_fh) unless not $cfg->{'usestderr'};
249 1     1   8 use strict 'subs';
  1         2  
  1         1056  
250             }
251              
252             #: very much like _WRITE_TEXT() except that this is specifically for
253             #: the menu() widget only.
254 0           sub _WRITE_MENU {
255 0     0     my $self = shift();
256 0           my $cfg = $self->_merge_attrs(@_);
257 0           my $text = "";
258 0 0         if ($cfg->{'literal'}) {
259 0   0       $text = $cfg->{'text'} || '';
260             }
261             else {
262 0   0       $text = $self->_organize_text($cfg->{'text'}) || "";
263             }
264 0           $self->clean_format($cfg->{'trust-input'},\$text);
265 0   0       my $backtitle = $cfg->{'backtitle'} || " ";
266 0   0       my $title = $cfg->{'title'} || " ";
267 0   0       my $menu = $cfg->{'menu'} || [];
268 0           my ($help,$cancel,$extra) = $self->_BUTTONS(@_);
269 0           for (my $i=0;$i<@{$menu};$i++) {
  0            
270 0           $self->clean_format($cfg->{'trust-input'},\$menu->[$i]);
271             }
272             format ASCIIPGMNU =
273             +-----------------------------------------------------------------------------+
274             | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
275             $backtitle
276             +-----------------------------------------------------------------------------+
277             | |
278             | +-------------------------------------------------------------------------+ |
279             | | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
280             $title
281             | +-------------------------------------------------------------------------+ |
282             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
283             $text
284             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
285             $text
286             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
287             $text
288             | +-------------------------------------------------------------------------+ |
289             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
290             ($menu->[0]||' '),($menu->[1]||' '),($menu->[2]||' '),($menu->[3]||' '),($menu->[4]||' '),($menu->[5]||' ')
291             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
292             ($menu->[6]||' '),($menu->[7]||' '),($menu->[8]||' '),($menu->[9]||' '),($menu->[10]||' '),($menu->[11]||' ')
293             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
294             ($menu->[12]||' '),($menu->[13]||' '),($menu->[14]||' '),($menu->[15]||' '),($menu->[16]||' '),($menu->[17]||' ')
295             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
296             ($menu->[18]||' '),($menu->[19]||' '),($menu->[20]||' '),($menu->[21]||' '),($menu->[22]||' '),($menu->[23]||' ')
297             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
298             ($menu->[24]||' '),($menu->[25]||' '),($menu->[26]||' '),($menu->[27]||' '),($menu->[28]||' '),($menu->[29]||' ')
299             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
300             ($menu->[30]||' '),($menu->[31]||' '),($menu->[32]||' '),($menu->[33]||' '),($menu->[34]||' '),($menu->[35]||' ')
301             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
302             ($menu->[36]||' '),($menu->[37]||' '),($menu->[38]||' '),($menu->[39]||' '),($menu->[42]||' '),($menu->[43]||' ')
303             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
304             ($menu->[42]||' '),($menu->[43]||' '),($menu->[44]||' '),($menu->[45]||' '),($menu->[46]||' '),($menu->[47]||' ')
305             | @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<<< @<<<< @<<<<<<<<<<<<<< |
306             ($menu->[48]||' '),($menu->[49]||' '),($menu->[50]||' '),($menu->[51]||' '),($menu->[52]||' '),($menu->[53]||' ')
307             | @|||||||||||||||||||| @||||||||||||||||||| @||||||||||||||||||| |
308             $extra,$cancel,$help
309             | ':?' = [Colon Command Help] |
310             +-----------------------------------------------------------------------------+
311             .
312 1     1   9 no strict 'subs';
  1         2  
  1         141  
313 0           my $_fh = select();
314 0 0         select(STDERR) unless not $cfg->{'usestderr'};
315 0           my $LFMT = $~;
316 0           $~ = ASCIIPGMNU;
317 0           write();
318 0           $~= $LFMT;
319 0 0         select($_fh) unless not $cfg->{'usestderr'};
320 1     1   8 use strict 'subs';
  1         2  
  1         1653  
321             }
322              
323             #: very much like _WRITE_MENU() except that this is specifically for
324             #: the radiolist() and checklist() widgets only.
325 0           sub _WRITE_LIST {
326 0     0     my $self = shift();
327 0           my $cfg = $self->_merge_attrs(@_);
328 0           my $text = "";
329 0 0         if ($cfg->{'literal'}) {
330 0   0       $text = $cfg->{'text'} || '';
331             }
332             else {
333 0   0       $text = $self->_organize_text($cfg->{'text'}) || "";
334             }
335 0           $self->clean_format($cfg->{'trust-input'},\$text);
336              
337 0   0       my $backtitle = $cfg->{'backtitle'} || " ";
338 0   0       my $title = $cfg->{'title'} || " ";
339 0           my $menu = [];
340 0           push(@{$menu},@{$cfg->{'menu'}});
  0            
  0            
341 0           my ($help,$cancel,$extra) = $self->_BUTTONS(@_);
342 0           my $m = @{$menu};
  0            
343              
344 0 0         if ($cfg->{'wm'}) {
345 0           for (my $i = 2; $i < $m; $i += 3) {
346 0 0 0       if ($menu->[$i] && $menu->[$i] =~ /on/i) {
347 0           $menu->[$i] = '->';
348             }
349             else {
350 0           $menu->[$i] = ' ';
351             }
352             }
353             }
354             else {
355 0           my $mark;
356 0           for (my $i = 2; $i < $m; $i += 3) {
357 0 0 0       if (!$mark && $menu->[$i] && $menu->[$i] =~ /on/i) {
      0        
358 0           $menu->[$i] = '->'; $mark = 1;
  0            
359             }
360             else {
361 0           $menu->[$i] = ' ';
362             }
363             }
364             }
365              
366             format ASCIIPGLST =
367             +-----------------------------------------------------------------------------+
368             | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
369             $backtitle
370             +-----------------------------------------------------------------------------+
371             | |
372             | +-------------------------------------------------------------------------+ |
373             | | @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | |
374             $title
375             | +-------------------------------------------------------------------------+ |
376             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
377             $text
378             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
379             $text
380             | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
381             $text
382             | +-------------------------------------------------------------------------+ |
383             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
384             ($menu->[2]||' '),($menu->[0]||' '),($menu->[1]||' '), ($menu->[5]||' '),($menu->[3]||' '),($menu->[4]||' '), ($menu->[8]||' '),($menu->[6]||' '),($menu->[7]||' ')
385             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
386             ($menu->[11]||' '),($menu->[9]||' '),($menu->[10]||' '), ($menu->[14]||' '),($menu->[12]||' '),($menu->[13]||' '), ($menu->[17]||' '),($menu->[15]||' '),($menu->[16]||' ')
387             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
388             ($menu->[20]||' '),($menu->[18]||' '),($menu->[19]||' '), ($menu->[23]||' '),($menu->[21]||' '),($menu->[22]||' '), ($menu->[26]||' '),($menu->[24]||' '),($menu->[25]||' ')
389             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
390             ($menu->[29]||' '),($menu->[27]||' '),($menu->[28]||' '), ($menu->[32]||' '),($menu->[30]||' '),($menu->[31]||' '), ($menu->[35]||' '),($menu->[33]||' '),($menu->[34]||' ')
391             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
392             ($menu->[38]||' '),($menu->[36]||' '),($menu->[37]||' '), ($menu->[41]||' '),($menu->[39]||' '),($menu->[40]||' '), ($menu->[44]||' '),($menu->[42]||' '),($menu->[43]||' ')
393             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
394             ($menu->[47]||' '),($menu->[45]||' '),($menu->[46]||' '), ($menu->[50]||' '),($menu->[48]||' '),($menu->[49]||' '), ($menu->[53]||' '),($menu->[51]||' '),($menu->[52]||' ')
395             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
396             ($menu->[56]||' '),($menu->[54]||' '),($menu->[55]||' '), ($menu->[59]||' '),($menu->[57]||' '),($menu->[58]||' '), ($menu->[62]||' '),($menu->[60]||' '),($menu->[61]||' ')
397             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
398             ($menu->[65]||' '),($menu->[63]||' '),($menu->[64]||' '), ($menu->[68]||' '),($menu->[66]||' '),($menu->[67]||' '), ($menu->[71]||' '),($menu->[69]||' '),($menu->[70]||' ')
399             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
400             ($menu->[74]||' '),($menu->[72]||' '),($menu->[73]||' '), ($menu->[77]||' '),($menu->[75]||' '),($menu->[76]||' '), ($menu->[80]||' '),($menu->[78]||' '),($menu->[79]||' ')
401             |@<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<<< @<<@<<<< @<<<<<<<<<<<<<< |
402             ($menu->[83]||' '),($menu->[81]||' '),($menu->[82]||' '), ($menu->[86]||' '),($menu->[84]||' '),($menu->[85]||' '), ($menu->[89]||' '),($menu->[87]||' '),($menu->[88]||' ')
403             | @|||||||||||||||||||| @||||||||||||||||||| @||||||||||||||||||| |
404             $extra,$cancel,$help
405             | ':?' = [Colon Command Help] |
406             +-----------------------------------------------------------------------------+
407             .
408 1     1   9 no strict 'subs';
  1         3  
  1         163  
409 0           my $_fh = select();
410 0 0         select(STDERR) unless not $cfg->{'usestderr'};
411 0           my $LFMT = $~;
412 0           $~ = ASCIIPGLST;
413 0           write();
414 0           $~= $LFMT;
415 0 0         select($_fh) unless not $cfg->{'usestderr'};
416 1     1   8 use strict 'subs';
  1         2  
  1         7743  
417             }
418              
419             sub _PRINT {
420 0     0     my $self = shift();
421 0           my $stderr = shift();
422 0 0         if ($stderr) {
423 0           print STDERR @_;
424             }
425             else {
426 0           print STDOUT @_;
427             }
428             }
429              
430             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
431             #: Public Methods
432             #:
433              
434             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
435             #: Ask a binary question (Yes/No)
436             sub yesno {
437 0     0 1   my $self = shift();
438 0   0       my $caller = (caller(1))[3] || 'main';
439 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
440 0 0 0       if ($_[0] && $_[0] eq 'caller') {
441 0           shift(); $caller = shift();
  0            
442             }
443 0           my $args = $self->_pre($caller,@_);
444 0           my ($YN,$RESP) = ('Yes|no','YES_OR_NO');
445 0 0         $YN = "yes|No" if $self->{'defaultno'};
446 0           while ($RESP !~ /^(y|yes|n|no)$/i) {
447 0           $self->_clear($args->{'clear'});
448 0           $self->_WRITE_TEXT(@_,text=>$args->{'text'});
449 0           $self->_PRINT($args->{'usestderr'},"(".$YN."): ");
450 0           chomp($RESP = );
451 0 0 0       if (!$RESP && $args->{'defaultno'}) {
    0 0        
452 0           $RESP = "no";
453             }
454             elsif (!$RESP && !$args->{'defaultno'}) {
455 0           $RESP = "yes";
456             }
457 0 0         if ($RESP =~ /^(y|yes)$/i) {
458 0           $self->ra("YES");
459 0           $self->rs("YES");
460 0           $self->rv('null');
461             }
462             else {
463 0           $self->ra("NO");
464 0           $self->rs("NO");
465 0           $self->rv(1);
466             }
467             }
468 0           $self->_post($args);
469 0 0         return(1) if $self->state() eq "OK";
470 0           return(0);
471             }
472              
473             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
474             #: Text entry
475             sub inputbox {
476 0     0 1   my $self = shift();
477 0   0       my $caller = (caller(1))[3] || 'main';
478 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
479 0 0 0       if ($_[0] && $_[0] eq 'caller') {
480 0           shift(); $caller = shift();
  0            
481             }
482 0           my $args = $self->_pre($caller,@_);
483 0           my $length = $args->{'maxinput'} + 1;
484 0           my $text = $args->{'text'};
485 0           my $string;
486 0           chomp($text);
487 0           while ($length > $args->{'maxinput'}) {
488 0           $self->_clear($args->{'clear'});
489 0           $self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
490 0           $self->_PRINT($args->{'usestderr'},"input: ");
491 0           chomp($string = );
492 0 0         if ($args->{'maxinput'}) {
493 0           $length = length($string);
494             }
495             else {
496 0           $length = 0;
497             }
498 0 0         if ($length > $args->{'maxinput'}) {
499             $self->_PRINT($args->{'usestderr'},"error: too many charaters input,".
500 0           " the maximum is: ".$args->{'maxinput'}."\n");
501             }
502             }
503 0           $self->rv('null');
504 0           $self->ra($string);
505 0           $self->rs($string);
506 0           $self->_post($args);
507 0           return($string);
508             }
509              
510             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
511             #: Password entry
512             sub password {
513 0     0 1   my $self = shift();
514 0   0       my $caller = (caller(1))[3] || 'main';
515 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
516 0 0 0       if ($_[0] && $_[0] eq 'caller') {
517 0           shift(); $caller = shift();
  0            
518             }
519 0           my $args = $self->_pre($caller,@_);
520             croak("The UI::Dialog::Backend::ASCII password widget depends on the stty ".
521             "binary. This was not found or is not executable.")
522 0 0         unless -x $args->{'stty'};
523 0           my ($length,$key) = ($args->{'maxinput'} + 1,'');
524 0           my $string;
525 0           my $text = $args->{'text'};
526 0           chomp($text);
527 0           my $ENV_PATH = $ENV{'PATH'};
528 0           $ENV{'PATH'} = "";
529 0           while ($length > $args->{'maxinput'}) {
530 0           $self->_clear($args->{'clear'});
531 0           $self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
532 0           $self->_PRINT($args->{'usestderr'},"input: ");
533 0 0         if ($self->_is_bsd()) {
534 0           system "$args->{'stty'} cbreak /dev/tty 2>&1";
535             }
536             else {
537 0           system $args->{'stty'}, '-icanon', 'eol', "\001";
538             }
539 0           while ($key = getc(STDIN)) {
540 0 0         last if $key =~ /\n/;
541 0 0         if ($key =~ /^\x1b$/) {
    0          
542             #this could be the DELETE key (not BS or ^H)
543             # ^[[3~ or \x1b\x5b\x33\x7e (aka: ESC + [ + 3 + ~)
544 0           my $key2 = getc(STDIN);
545 0 0         if ($key2 =~ /^\x5b$/) {
546 0           my $key3 = getc(STDIN);
547 0 0         if ($key3 =~ /^\x33$/) {
548 0           my $key4 = getc(STDIN);
549 0 0         if ($key4 =~ /^\x7e$/) {
550 0           chop($string);
551             # go back five spaces and print five spaces (erase ^[[3~)
552             # go back five spaces again (backtrack),
553             # go back one space, print a space and go back (erase *)
554 0 0         if ($args->{'usestderr'}) {
555 0           print STDERR "\b\b\b\b\b"." "."\b\b\b\b\b"."\b \b";
556             }
557             else {
558 0           print STDOUT "\b\b\b\b\b"." "."\b\b\b\b\b"."\b \b";
559             }
560             }
561             else {
562 0           $key = $key.$key2.$key3.$key4;
563             }
564             }
565             else {
566 0           $key = $key.$key2.$key3;
567             }
568             }
569             else {
570 0           $key = $key.$key2;
571             }
572             }
573             elsif ($key =~ /^(?:\x08|\x7f)$/) {
574             # this is either a BS or ^H
575 0           chop($string);
576             # go back two spaces and print two spaces (erase ^H)
577             # go back two spaces again (backtrack),
578             # go back one space, print a space and go back (erase *)
579 0 0         if ($args->{'usestderr'}) {
580 0           print STDERR "\b\b"." "."\b\b"."\b \b";
581             }
582             else {
583 0           print STDOUT "\b\b"." "."\b\b"."\b \b";
584             }
585             }
586             else {
587 0 0         if ($args->{'usestderr'}) {
588 0           print STDERR "\b*";
589             }
590             else {
591 0           print STDOUT "\b*";
592             }
593 0           $string .= $key;
594             }
595             }
596 0 0         if ($self->_is_bsd()) {
597 0           system "$args->{'stty'} -cbreak /dev/tty 2>&1";
598             }
599             else {
600 0           system $args->{'stty'}, 'icanon', 'eol', '^@';
601             }
602 0 0         if ($args->{'maxinput'}) {
603 0           $length = length($string);
604             }
605             else {
606 0           $length = 0;
607             }
608 0 0         if ($length > $args->{'maxinput'}) {
609             $self->_PRINT($args->{'usestderr'},"error: too many charaters input,".
610 0           " the maximum is: ".$args->{'maxinput'}."\n");
611             }
612             }
613 0           $ENV{'PATH'} = $ENV_PATH;
614 0           $self->rv('null');
615 0           $self->ra($string);
616 0           $self->rs($string);
617 0           $self->_post($args);
618 0           return($string);
619             }
620              
621             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
622             #: Information box
623             sub infobox {
624 0     0 1   my $self = shift();
625 0   0       my $caller = (caller(1))[3] || 'main';
626 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
627 0 0 0       if ($_[0] && $_[0] eq 'caller') {
628 0           shift(); $caller = shift();
  0            
629             }
630 0           my $args = $self->_pre($caller,@_);
631 0           $self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
632 0           $self->_PRINT($args->{'usestderr'});
633             my $s = int(($args->{'wait'}) ? $args->{'wait'} :
634 0 0         ($args->{'timeout'}) ? ($args->{'timeout'} / 1000.0) : 1.0);
    0          
635 0           sleep($s);
636 0           $self->rv('null');
637 0           $self->ra('null');
638 0           $self->rs('null');
639 0           $self->_post($args);
640 0           return(1);
641             }
642              
643             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
644             #: Message box
645             sub msgbox {
646 0     0 1   my $self = shift();
647 0   0       my $caller = (caller(1))[3] || 'main';
648 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
649 0 0 0       if ($_[0] && $_[0] eq 'caller') {
650 0           shift(); $caller = shift();
  0            
651             }
652 0           my $args = $self->_pre($caller,@_);
653 0           $self->_WRITE_TEXT(@_,'text'=>$args->{'text'});
654 0           $self->_PRINT($args->{'usestderr'},(" " x 25)."[ Press Enter to Continue ]");
655 0           my $junk = ;
656 0           $self->rv('null');
657 0           $self->ra('null');
658 0           $self->rs('null');
659 0           $self->_post($args);
660 0           return(1);
661             }
662              
663              
664             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
665             #: Text box
666             sub textbox {
667 0     0 1   my $self = shift();
668 0   0       my $caller = (caller(1))[3] || 'main';
669 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
670 0 0 0       if ($_[0] && $_[0] eq 'caller') {
671 0           shift(); $caller = shift();
  0            
672             }
673 0           my $args = $self->_pre($caller,@_);
674 0           my $rv = 0;
675 0 0         if (-r $args->{'path'}) {
676 0           my $ENV_PATH = $ENV{'PATH'};
677 0           $ENV{'PATH'} = "";
678 0 0 0       if ($ENV{'PAGER'} && -x $ENV{'PAGER'}) {
    0          
679 0           system($ENV{'PAGER'}." ".$args->{'path'});
680 0           $rv = $? >> 8;
681             }
682             elsif (-x $args->{'pager'}) {
683 0           system($args->{'pager'}." ".$args->{'path'});
684 0           $rv = $? >> 8;
685             }
686             else {
687 0           open(ATBFILE,"<".$args->{'path'});
688 0           local $/;
689 0           my $data = ;
690 0           close(ATBFILE);
691 0           $self->_PRINT($args->{'usestderr'},$data);
692             }
693 0           $ENV{'PATH'} = $ENV_PATH;
694             }
695             else {
696 0           return($self->msgbox('title'=>'error','text'=>$args->{'path'}.' is not a readable text file.'));
697             }
698 0   0       $self->rv($rv||'null');
699 0           $self->ra('null');
700 0           $self->rs('null');
701 0           $self->_post($args);
702 0           return($rv);
703             }
704              
705             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
706             #: A simple menu
707             sub menu {
708 0     0 1   my $self = shift();
709 0   0       my $caller = (caller(1))[3] || 'main';
710 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
711 0 0 0       if ($_[0] && $_[0] eq 'caller') {
712 0           shift(); $caller = shift();
  0            
713             }
714 0           my $args = $self->_pre($caller,@_);
715 0 0         $args->{'menu'} = $args->{'list'} if ref($args->{'list'}) eq "ARRAY";
716 0           my $string;
717 0           my $rs = '';
718 0           my $m;
719 0 0         $m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
  0            
720 0           my ($valid,$menu,$realm) = ([],[],[]);
721 0 0         push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
  0            
  0            
722              
723 0           for (my $i = 0; $i < $m; $i += 2) {
724 0           push(@{$valid},$menu->[$i]);
  0            
725             }
726              
727 0 0         if (@{$menu} >= 60) {
  0            
728 0           my $c = 0;
729 0           while (@{$menu}) {
  0            
730 0           $realm->[$c] = [];
731 0           for (my $i = 0; $i < 60; $i++) {
732 0           push(@{$realm->[$c]},shift(@{$menu}));
  0            
  0            
733             }
734 0           $c++;
735             }
736             }
737             else {
738 0           $realm->[0] = [];
739 0           push(@{$realm->[0]},@{$menu});
  0            
  0            
740             }
741 0           my $pg = 1;
742 0           while (!$rs) {
743 0   0       $self->_WRITE_MENU(@_,'text'=>$args->{'text'},
744             'menu'=>$realm->[($pg - 1||0)]);
745 0           $self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
  0            
746 0           chomp($rs = );
747 0 0 0       if ($rs =~ /^:\?$/i) {
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
    0          
748 0           $self->_clear($args->{'clear'});
749 0           $self->_WRITE_HELP_TEXT();
750 0           undef($rs);
751 0           next;
752             }
753             elsif ($rs =~ /^:(esc|escape)$/i) {
754 0           $self->_clear($args->{'clear'});
755 0           undef($rs);
756 0           $self->rv(255);
757 0           return(0);
758             }
759             elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
760 0           $self->rv(3);
761 0           return('EXTRA');
762             }
763             elsif ($args->{'help-button'} && $rs =~ /^:(h|help)$/i) {
764 0           $self->_clear($args->{'clear'});
765 0           undef($rs);
766 0           $self->rv(2);
767 0           return($self->state());
768             }
769             elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
770 0           $self->_clear($args->{'clear'});
771 0           undef($rs);
772 0           $self->rv(1);
773 0           return($self->state());
774             }
775             elsif ($rs =~ /^:pg\s*(\d+)$/i) {
776 0           my $p = $1;
777 0 0 0       if ($p <= @{$realm} && $p > 0) {
  0            
778 0           $pg = $p;
779             }
780 0           undef($rs);
781             }
782             elsif ($rs =~ /^:(n|next)$/i) {
783 0 0         if ($pg < @{$realm}) {
  0            
784 0           $pg++;
785             }
786             else {
787 0           $pg = 1;
788             }
789 0           undef($rs);
790             }
791             elsif ($rs =~ /^:(p|prev)$/i) {
792 0 0         if ($pg > 1) {
793 0           $pg--;
794             }
795             else {
796 0           $pg = @{$realm};
  0            
797             }
798 0           undef($rs);
799             }
800             else {
801 0 0         if (@_ = grep { /^\Q$rs\E$/i } @{$valid}) {
  0            
  0            
802 0           $rs = $_[0];
803             }
804             else {
805 0           undef($rs);
806             }
807             }
808 0           $self->_clear($args->{'clear'});
809             }
810              
811 0           $self->rv('null');
812 0           $self->ra($rs);
813 0           $self->rs($rs);
814 0           $self->_post($args);
815 0           return($rs);
816             }
817              
818             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
819             #: A multi-selectable list
820             sub checklist {
821 0     0 1   my $self = shift();
822 0   0       my $caller = (caller(1))[3] || 'main';
823 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
824 0 0 0       if ($_[0] && $_[0] eq 'caller') {
825 0           shift(); $caller = shift();
  0            
826             }
827 0           my $args = $self->_pre($caller,@_);
828 0   0       my $menulist = ($args->{'menu'} || $args->{'list'});
829 0           my $menufix = [];
830 0 0         if (ref($menulist) eq "ARRAY") {
831             #: flatten our multidimensional array
832 0           foreach my $item (@$menulist) {
833 0 0         if (ref($item) eq "ARRAY") {
834 0 0         pop(@{$item}) if @$item == 3;
  0            
835 0           push(@$menufix,@{$item});
  0            
836             }
837             else {
838 0           push(@$menufix,$item);
839             }
840             }
841             }
842 0           $args->{'menu'} = $menufix;
843              
844 0           my $ra = [];
845 0           my $rs = '';
846 0           my $m;
847 0 0         $m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
  0            
848 0           my ($valid,$menu,$realm) = ([],[],[]);
849 0 0         push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
  0            
  0            
850              
851 0           for (my $i = 0; $i < $m; $i += 3) {
852 0           push(@{$valid},$menu->[$i]);
  0            
853             }
854              
855 0 0         if (@{$menu} >= 90) {
  0            
856 0           my $c = 0;
857 0           while (@{$menu}) {
  0            
858 0           $realm->[$c] = [];
859 0           for (my $i = 0; $i < 90; $i++) {
860 0           push(@{$realm->[$c]},shift(@{$menu}));
  0            
  0            
861             }
862 0           $c++;
863             }
864             }
865             else {
866 0           $realm->[0] = [];
867 0           push(@{$realm->[0]},@{$menu});
  0            
  0            
868             }
869 0           my $go = "GO";
870 0           my $pg = 1;
871 0           while ($go) {
872 0   0       $self->_WRITE_LIST(@_,'wm'=>'check','text'=>$args->{'text'},'menu'=>$realm->[($pg - 1||0)]);
873 0           $self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
  0            
874 0           chomp($rs = );
875 0 0 0       if ($rs =~ /^:\?$/i) {
    0 0        
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
876 0           $self->_clear($args->{'clear'});
877 0           $self->_WRITE_HELP_TEXT();
878 0           undef($rs);
879 0           next;
880             }
881             elsif ($rs =~ /^:(esc|escape)$/i) {
882 0           $self->_clear($args->{'clear'});
883 0           undef($rs);
884 0           $self->rv(255);
885 0           return($self->state());
886             }
887             elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
888 0           $self->_clear($args->{'clear'});
889 0           $self->rv(3);
890 0           return($self->state());
891             }
892             elsif (($args->{'help-button'} || $args->{'help-label'}) && $rs =~ /^:(h|help)$/i) {
893 0           $self->_clear($args->{'clear'});
894 0           undef($rs);
895 0           $self->rv(2);
896 0           return($self->rv());
897             }
898             elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
899 0           $self->_clear($args->{'clear'});
900 0           undef($rs);
901 0           $self->rv(1);
902 0           return($self->state());
903             }
904             elsif ($rs =~ /^:pg\s*(\d+)$/i) {
905 0           my $p = $1;
906 0 0 0       if ($p <= @{$realm} && $p > 0) {
  0            
907 0           $pg = $p;
908             }
909             }
910             elsif ($rs =~ /^:(n|next)$/i) {
911 0 0         if ($pg < @{$realm}) {
  0            
912 0           $pg++;
913             }
914             else {
915 0           $pg = 1;
916             }
917             }
918             elsif ($rs =~ /^:(p|prev)$/i) {
919 0 0         if ($pg > 1) {
920 0           $pg--;
921             }
922             else {
923 0           $pg = @{$realm};
  0            
924             }
925             }
926             else {
927 0           my @opts = split(/\,\s|\,|\s/,$rs);
928 0           my @good;
929 0           foreach my $opt (@opts) {
930 0 0         if (@_ = grep { /^\Q$opt\E$/i } @{$valid}) {
  0            
  0            
931 0           push(@good,$_[0]);
932             }
933             }
934 0 0         if (@opts == @good) {
935 0           undef($go);
936 0           $ra = [];
937 0           push(@{$ra},@good);
  0            
938             }
939             }
940 0           $self->_clear($args->{'clear'});
941 0           undef($rs);
942             }
943              
944 0           $self->rv('null');
945 0           $self->ra($ra);
946 0           $self->rs(join("\n",@$ra));
947 0           $self->_post($args);
948 0           return(@{$ra});
  0            
949             }
950              
951             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
952             #: A radio button based list. very much like the menu widget.
953             sub radiolist {
954 0     0 1   my $self = shift();
955 0   0       my $caller = (caller(1))[3] || 'main';
956 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
957 0 0 0       if ($_[0] && $_[0] eq 'caller') {
958 0           shift(); $caller = shift();
  0            
959             }
960 0           my $args = $self->_pre($caller,@_);
961 0   0       my $menulist = ($args->{'menu'} || $args->{'list'});
962 0           my $menufix = [];
963 0 0         if (ref($menulist) eq "ARRAY") {
964             #: flatten our multidimensional array
965 0           foreach my $item (@$menulist) {
966 0 0         if (ref($item) eq "ARRAY") {
967 0 0         pop(@{$item}) if @$item == 3;
  0            
968 0           push(@$menufix,@{$item});
  0            
969             }
970             else {
971 0           push(@$menufix,$item);
972             }
973             }
974             }
975 0           $args->{'menu'} = $menufix;
976 0           my $rs = '';
977 0           my $m;
978 0 0         $m = @{$args->{'menu'}} if ref($args->{'menu'}) eq "ARRAY";
  0            
979 0           my ($valid,$menu,$realm) = ([],[],[]);
980 0 0         push(@{$menu},@{$args->{'menu'}}) if ref($args->{'menu'}) eq "ARRAY";
  0            
  0            
981              
982 0           for (my $i = 0; $i < $m; $i += 3) {
983 0           push(@{$valid},$menu->[$i]);
  0            
984             }
985              
986 0 0         if (@{$menu} >= 90) {
  0            
987 0           my $c = 0;
988 0           while (@{$menu}) {
  0            
989 0           $realm->[$c] = [];
990 0           for (my $i = 0; $i < 90; $i++) {
991 0           push(@{$realm->[$c]},shift(@{$menu}));
  0            
  0            
992             }
993 0           $c++;
994             }
995             }
996             else {
997 0           $realm->[0] = [];
998 0           push(@{$realm->[0]},@{$menu});
  0            
  0            
999             }
1000 0           my $pg = 1;
1001 0           while (!$rs) {
1002 0   0       $self->_WRITE_LIST(@_,'text'=>$args->{'text'},'menu'=>$realm->[($pg - 1||0)]);
1003 0           $self->_PRINT($args->{'usestderr'},"(".$pg."/".@{$realm}."): ");
  0            
1004 0           chomp($rs = );
1005 0 0 0       if ($rs =~ /^:\?$/i) {
    0 0        
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
1006 0           $self->_clear($args->{'clear'});
1007 0           $self->_WRITE_HELP_TEXT();
1008 0           undef($rs);
1009 0           next;
1010             }
1011             elsif ($rs =~ /^:(esc|escape)$/i) {
1012 0           $self->_clear($args->{'clear'});
1013 0           undef($rs);
1014 0           $self->rv(255);
1015 0           return($self->rv());
1016             }
1017             elsif (($args->{'extra-button'} || $args->{'extra-label'}) && $rs =~ /^:(e|extra)$/i) {
1018 0           $self->rv(3);
1019 0           return($self->state());
1020             }
1021             elsif (($args->{'help-button'} || $args->{'help-label'}) && $rs =~ /^:(h|help)$/i) {
1022 0           $self->_clear($args->{'clear'});
1023 0           undef($rs);
1024 0           $self->rv(2);
1025 0           return($self->state());
1026             }
1027             elsif (!$args->{'nocancel'} && $rs =~ /^:(c|cancel)$/i) {
1028 0           $self->_clear($args->{'clear'});
1029 0           undef($rs);
1030 0           $self->rv(1);
1031 0           return($self->state());
1032             }
1033             elsif ($rs =~ /^:pg\s*(\d+)$/i) {
1034 0           my $p = $1;
1035 0 0 0       if ($p <= @{$realm} && $p > 0) {
  0            
1036 0           $pg = $p;
1037             }
1038 0           undef($rs);
1039             }
1040             elsif ($rs =~ /^:(n|next)$/i) {
1041 0 0         if ($pg < @{$realm}) {
  0            
1042 0           $pg++;
1043             }
1044             else {
1045 0           $pg = 1;
1046             }
1047 0           undef($rs);
1048             }
1049             elsif ($rs =~ /^:(p|prev)$/i) {
1050 0 0         if ($pg > 1) {
1051 0           $pg--;
1052             }
1053             else {
1054 0           $pg = @{$realm};
  0            
1055             }
1056 0           undef($rs);
1057             }
1058             else {
1059 0 0         if (@_ = grep { /^\Q$rs\E$/i } @{$valid}) {
  0            
  0            
1060 0           $rs = $_[0];
1061             }
1062             else {
1063 0           undef($rs);
1064             }
1065             }
1066 0           $self->_clear($args->{'clear'});
1067             }
1068              
1069 0           $self->rv('null');
1070 0           $self->ra($rs);
1071 0           $self->rs($rs);
1072 0           $self->_post($args);
1073 0           return($rs);
1074             }
1075              
1076              
1077             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1078             #: Simple ASCII progress indicator :)
1079             sub spinner {
1080 0     0 1   my $self = shift();
1081 0 0 0       if (!$self->{'__SPIN'} || $self->{'__SPIN'} == 1) {
    0          
    0          
    0          
1082 0           $self->{'__SPIN'} = 2; return("\b|");
  0            
1083             }
1084             elsif ($self->{'__SPIN'} == 2) {
1085 0           $self->{'__SPIN'} = 3; return("\b/");
  0            
1086             }
1087             elsif ($self->{'__SPIN'} == 3) {
1088 0           $self->{'__SPIN'} = 4; return("\b-");
  0            
1089             }
1090             elsif ($self->{'__SPIN'} == 4) {
1091 0           $self->{'__SPIN'} = 1; return("\b\\");
  0            
1092             }
1093             }
1094              
1095             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1096             #: Simple ASCII meter bar
1097             # the idea of a "true" dialog like gauge widget with ASCII is not that bad and
1098             # as such, I've named these methods differently so as to keep the namespace
1099             # open for gauge_*() widgets.
1100             sub draw_gauge {
1101 0     0 1   my $self = shift();
1102 0           my $args = $self->_merge_attrs(@_);
1103 0   0       my $length = $args->{'length'} || $args->{'width'} || 74;
1104 0   0       my $bar = ($args->{'bar'} || "-") x $length;
1105 0   0       my $current = $args->{'current'} || 0;
1106 0   0       my $total = $args->{'total'} || 0;
1107             my $percent = (($current && $total) ? int($current / ($total / 100)) :
1108 0 0 0       ($args->{'percent'} || '0'));
      0        
1109 0 0 0       $percent = int(($percent <= 100 && $percent >= 0) ? $percent : 0 );
1110 0           my $perc = int((($length / 100) * $percent));
1111 0   0       substr($bar,($perc||0),1,($args->{'mark'}||"|"));
      0        
1112 0 0         my $text = (($percent =~ /^\d$/) ? " " :
    0          
1113             ($percent =~ /^\d\d$/) ? " " : "").$percent."% ".$bar;
1114 0 0 0       $self->_PRINT($args->{'usestderr'},(($args->{'noCR'} && not $args->{'CR'}) ? "" : "\x0D").$text);
1115 0   0       return($percent||1);
1116             }
1117             sub end_gauge {
1118 0     0 1   my $self = shift();
1119 0           my $args = $self->_merge_attrs(@_);
1120 0           $self->_PRINT($args->{'usestderr'},"\n");
1121             }
1122              
1123             1;