File Coverage

blib/lib/UI/Dialog/Backend/CDialog.pm
Criterion Covered Total %
statement 63 577 10.9
branch 7 216 3.2
condition 19 283 6.7
subroutine 12 40 30.0
pod 21 24 87.5
total 122 1140 10.7


line stmt bran cond sub pod time code
1             package UI::Dialog::Backend::CDialog;
2             ###############################################################################
3             # Copyright (C) 2004-2016 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 6     6   15277 use 5.006;
  6         12  
20 6     6   18 use strict;
  6         5  
  6         107  
21 6     6   16 use warnings;
  6         5  
  6         133  
22 6     6   41 use Carp;
  6         6  
  6         315  
23 6     6   25 use Config;
  6         5  
  6         184  
24 6     6   2383 use FileHandle;
  6         44644  
  6         35  
25 6     6   1547 use Cwd qw( abs_path );
  6         9  
  6         242  
26 6     6   2926 use Time::HiRes qw( sleep );
  6         5938  
  6         21  
27 6     6   3170 use UI::Dialog::Backend;
  6         13  
  6         206  
28              
29             BEGIN {
30 6     6   31 use vars qw( $VERSION @ISA );
  6         5  
  6         285  
31 6     6   39 @ISA = qw( UI::Dialog::Backend );
32 6         26770 $VERSION = '1.21';
33             }
34              
35             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
36             #: Constructor Method
37             #:
38              
39             sub new {
40 1     1 1 419 my $proto = shift();
41 1   33     6 my $class = ref($proto) || $proto;
42 1 50       7 my $cfg = ((ref($_[0]) eq "HASH") ? $_[0] : (@_) ? { @_ } : {});
    50          
43 1         2 my $self = {};
44 1         2 bless($self, $class);
45 1         8 $self->{'_state'} = {};
46 1         3 $self->{'_opts'} = {};
47              
48             #: Dynamic path discovery...
49 1         11 my $path_sep = $Config::Config{path_sep};
50 1         3 my $CFG_PATH = $cfg->{'PATH'};
51 1 50       5 if ($CFG_PATH) {
    50          
52 0 0       0 if (ref($CFG_PATH) eq "ARRAY") {
    0          
    0          
53 0         0 $self->{'PATHS'} = $CFG_PATH;
54             }
55             elsif ($CFG_PATH =~ m!$path_sep!) {
56 0         0 $self->{'PATHS'} = [ split(/$path_sep/,$CFG_PATH) ];
57             }
58             elsif (-d $CFG_PATH) {
59 0         0 $self->{'PATHS'} = [ $CFG_PATH ];
60             }
61             }
62             elsif ($ENV{'PATH'}) {
63 1         16 $self->{'PATHS'} = [ split(/$path_sep/,$ENV{'PATH'}) ];
64             }
65             else {
66 0         0 $self->{'PATHS'} = '';
67             }
68              
69 1   50     7 $self->{'_opts'}->{'literal'} = $cfg->{'literal'} || 0;
70 1   50     7 $self->{'_opts'}->{'callbacks'} = $cfg->{'callbacks'} || undef();
71 1   50     6 $self->{'_opts'}->{'timeout'} = $cfg->{'timeout'} || 0;
72 1   50     5 $self->{'_opts'}->{'wait'} = $cfg->{'wait'} || 0;
73 1   50     7 $self->{'_opts'}->{'debug'} = $cfg->{'debug'} || undef();
74 1   50     5 $self->{'_opts'}->{'title'} = $cfg->{'title'} || undef();
75 1   50     4 $self->{'_opts'}->{'backtitle'} = $cfg->{'backtitle'} || undef();
76 1   50     4 $self->{'_opts'}->{'width'} = $cfg->{'width'} || 65;
77 1   50     5 $self->{'_opts'}->{'height'} = $cfg->{'height'} || 10;
78 1   50     6 $self->{'_opts'}->{'percentage'} = $cfg->{'percentage'} || 1;
79 1 50 33     5 $self->{'_opts'}->{'colours'} = ($cfg->{'colours'} || $cfg->{'colors'}) ? 1 : 0;
80 1   33     11 $self->{'_opts'}->{'bin'} ||= $self->_find_bin('dialog');
81 1 50 0     7 $self->{'_opts'}->{'bin'} ||= $self->_find_bin('dialog.exe') if $^O =~ /win32/i;
82 1   50     7 $self->{'_opts'}->{'autoclear'} = $cfg->{'autoclear'} || 0;
83 1   50     10 $self->{'_opts'}->{'clearbefore'} = $cfg->{'clearbefore'} || 0;
84 1   50     5 $self->{'_opts'}->{'clearafter'} = $cfg->{'clearafter'} || 0;
85 1   50     7 $self->{'_opts'}->{'beepbin'} = $cfg->{'beepbin'} || $self->_find_bin('beep') || '/usr/bin/beep';
86 1   50     5 $self->{'_opts'}->{'beepbefore'} = $cfg->{'beepbefore'} || 0;
87 1   50     5 $self->{'_opts'}->{'beepafter'} = $cfg->{'beepafter'} || 0;
88 1 50       16 unless (-x $self->{'_opts'}->{'bin'}) {
89 1         194 croak("the dialog binary could not be found at: ".$self->{'_opts'}->{'bin'});
90             }
91 0   0       $self->{'_opts'}->{'DIALOGRC'} = $cfg->{'DIALOGRC'} || undef();
92 0           my $beginref = $cfg->{'begin'};
93 0 0         $self->{'_opts'}->{'begin'} = (ref($beginref) eq "ARRAY") ? $beginref : undef();
94 0   0       $self->{'_opts'}->{'cancel-label'} = $cfg->{'cancel-label'} || undef();
95 0   0       $self->{'_opts'}->{'defaultno'} = $cfg->{'defaultno'} || 0;
96 0   0       $self->{'_opts'}->{'default-item'} = $cfg->{'default-item'} || undef();
97 0   0       $self->{'_opts'}->{'exit-label'} = $cfg->{'exit-label'} || undef();
98 0   0       $self->{'_opts'}->{'extra-button'} = $cfg->{'extra-button'} || 0;
99 0   0       $self->{'_opts'}->{'extra-label'} = $cfg->{'extra-label'} || undef();
100 0   0       $self->{'_opts'}->{'help-button'} = $cfg->{'help-button'} || 0;
101 0   0       $self->{'_opts'}->{'help-label'} = $cfg->{'help-label'} || undef();
102 0   0       $self->{'_opts'}->{'max-input'} = $cfg->{'max-input'} || 0;
103 0   0       $self->{'_opts'}->{'no-cancel'} = $cfg->{'no-cancel'} || $cfg->{'nocancel'} || 0;
104 0   0       $self->{'_opts'}->{'no-collapse'} = $cfg->{'no-collapse'} || 0;
105 0   0       $self->{'_opts'}->{'no-shadow'} = $cfg->{'no-shadow'} || 0;
106 0   0       $self->{'_opts'}->{'ok-label'} = $cfg->{'ok-label'} || undef();
107 0   0       $self->{'_opts'}->{'shadow'} = $cfg->{'shadow'} || 0;
108 0   0       $self->{'_opts'}->{'tab-correct'} = $cfg->{'tab-correct'} || 0;
109 0   0       $self->{'_opts'}->{'tab-len'} = $cfg->{'tab-len'} || 0;
110 0   0       $self->{'_opts'}->{'listheight'} = $cfg->{'listheight'} || $cfg->{'menuheight'} || 5;
111 0   0       $self->{'_opts'}->{'formheight'} = $cfg->{'formheight'} || $cfg->{'listheight'} || 5;
112 0   0       $self->{'_opts'}->{'yes-label'} = $cfg->{'yes-label'} || undef();
113 0   0       $self->{'_opts'}->{'no-label'} = $cfg->{'no-label'} || undef();
114              
115 0   0       $self->{'_opts'}->{'trust-input'} = $cfg->{'trust-input'} || 0;
116              
117 0           $self->_determine_dialog_variant();
118              
119 0 0         $self->{'test_mode'} = $cfg->{'test_mode'} if exists $cfg->{'test_mode'};
120 0           $self->{'test_mode_result'} = '';
121              
122 0           return($self);
123             }
124              
125             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
126             #: Private Methods
127             #:
128             sub _determine_dialog_variant {
129 0     0     my $self = $_[0];
130 0           my $str = `$self->{'_opts'}->{'bin'} --help 2>&1`;
131 0 0         if ($str =~ /version\s0\.[34]/m) {
    0          
132             # this version does not support colours, so far just FreeBSD 4.8 has this
133             # ancient binary. Bugreport from Jeroen Bulten indicates that he's
134             # got a version 0.3 (patched to 0.4) installed. ugh...
135 0           $self->{'_variant'} = "dialog";
136             # the separate-output option seems to be the culprit of FreeBSD failure.
137 0           $self->{'_opts'}->{'force-no-separate-output'} = 1;
138             }
139             elsif ($str =~ /cdialog\s\(ComeOn\sDialog\!\)\sversion\s(\d+\.\d+.+)/) {
140             # We consider cdialog to be a colour supporting dialog variant all others
141             # are non-colourized and support only the base functionality :(
142 0           my $ver = $1;
143 0 0         if ($ver =~ /-20(?:0[3-9]|\d\d)/) {
144 0           $self->{'_variant'} = "cdialog";
145             # these versions support colours :)
146 0           $self->{'_opts'}->{'colours'} = 1;
147             }
148             else {
149 0           $self->{'_variant'} = "dialog";
150             }
151             }
152             else {
153 0           $self->{'_variant'} = "dialog";
154             }
155 0           undef($str);
156             }
157              
158             my $SIG_CODE = {};
159             sub _del_gauge {
160 0     0     my $CODE = $SIG_CODE->{$$};
161 0 0         unless (not ref($CODE)) {
162 0           delete($CODE->{'_GAUGE'});
163 0           $CODE->rv('1');
164 0           $CODE->rs('null');
165 0           $CODE->ra('null');
166 0           $SIG_CODE->{$$} = "";
167             }
168             }
169              
170             sub append_format_base {
171 0     0 0   my ($self,$args,$fmt) = @_;
172 0 0 0       $ENV{'DIALOGRC'} ||= ($args->{'DIALOGRC'} && -r $args->{'DIALOGRC'}) ? $args->{'DIALOGRC'} : "";
      0        
173 0           $ENV{'DIALOG_CANCEL'} = '1';
174 0           $ENV{'DIALOG_ERROR'} = '254';
175 0           $ENV{'DIALOG_ESC'} = '255';
176 0           $ENV{'DIALOG_EXTRA'} = '3';
177 0           $ENV{'DIALOG_HELP'} = '2';
178 0           $ENV{'DIALOG_OK'} = '0';
179 0           $fmt = $self->append_format_check($args,$fmt,'backtitle','--backtitle {{backtitle}}');
180 0           $fmt = $self->append_format_check($args,$fmt,"defaultno","--defaultno");
181 0           $fmt = $self->append_format_check($args,$fmt,"extra-button","--extra-button");
182 0           $fmt = $self->append_format_check($args,$fmt,"help-button","--help-button");
183 0           $fmt = $self->append_format_check($args,$fmt,"no-cancel","--no-cancel");
184 0           $fmt = $self->append_format_check($args,$fmt,"no-collapse","--no-collapse");
185 0           $fmt = $self->append_format_check($args,$fmt,"no-shadow","--no-shadow");
186 0           $fmt = $self->append_format_check($args,$fmt,"shadow","--shadow");
187 0           $fmt = $self->append_format_check($args,$fmt,"tab-correct","--tab-correct");
188 0           $fmt = $self->append_format_check($args,$fmt,"cancel-label","--cancel-label {{cancel-label}}");
189 0           $fmt = $self->append_format_check($args,$fmt,"default-item","--default-item {{default-item}}");
190 0           $fmt = $self->append_format_check($args,$fmt,"exit-label","--exit-label {{exit-label}}");
191 0           $fmt = $self->append_format_check($args,$fmt,"extra-label","--extra-label {{extra-label}}");
192 0           $fmt = $self->append_format_check($args,$fmt,"help-label","--help-label {{help-label}}");
193 0           $fmt = $self->append_format_check($args,$fmt,"max-input","--max-input {{max-input}}");
194 0           $fmt = $self->append_format_check($args,$fmt,"ok-label","--ok-label {{ok-label}}");
195 0           $fmt = $self->append_format_check($args,$fmt,"tab-len","--tab-len {{tab-len}}");
196 0           $fmt = $self->append_format_check($args,$fmt,"yes-label","--yes-label {{yes-label}}");
197 0           $fmt = $self->append_format_check($args,$fmt,"no-label","--no-label {{no-label}}");
198              
199 0 0         if ($self->{'_opts'}->{'force-no-separate-output'}) {
200 0           delete $args->{'separate-output'};
201             } else {
202 0           $fmt = $self->append_format_check($args,$fmt,"separate-output","--separate-output");
203             }
204 0 0         if ($self->is_cdialog()) {
205 0           $fmt = $self->append_format($fmt,'--colors');
206 0           $fmt = $self->append_format($fmt,'--cr-wrap');
207 0 0         if (exists $args->{'begin'}) {
208 0           my $begin = $args->{'begin'};
209 0 0         if (ref($begin) eq "ARRAY") {
210 0           $fmt = $self->append_format($fmt,'--begin '.$begin->[0].' '.$begin->[1]);
211             }
212             }
213             }
214 0           return $fmt;
215             }
216              
217             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
218             #: Override Inherited Methods
219             #:
220             sub _organize_text {
221 0     0     my $self = $_[0];
222 0   0       my $text = $_[1] || return();
223 0   0       my $width = $_[2] || 65;
224 0 0 0       my $trust = (exists $_[3] && defined $_[3]) ? $_[3] : '0';
225 0           my @array;
226              
227 0 0         if (ref($text) eq "ARRAY") {
    0          
228 0           push(@array,@{$text});
  0            
229             }
230             elsif ($text =~ /\\n/) {
231 0           @array = split(/\\n/,$text);
232             }
233             else {
234 0           @array = split(/\n/,$text);
235             }
236 0           $text = undef();
237              
238 0           @array = $self->word_wrap($width,"","",@array);
239 0           my $max = @array;
240 0           for (my $i = 0; $i < $max; $i++) {
241 0           $self->clean_format($trust,\$array[$i]);
242             }
243              
244 0 0         if ($self->{'scale'}) {
245 0           foreach my $line (@array) {
246 0           my $s_line = $line; #$self->__TRANSLATE_CLEAN($line);
247 0           $s_line =~ s!\[A\=\w+\]!!gi;
248             $self->{'width'} = length($s_line) + 5
249             if ($self->{'width'} - 5) < length($s_line)
250 0 0 0       && (length($s_line) <= $self->{'max-scale'});
251             }
252             }
253              
254 0 0         my $new_line = $^O =~ /win32/i ? '\n' : "\n";
255 0           foreach my $line (@array) {
256 0           my $pad;
257 0           my $s_line = $self->_strip_text($line);
258 0 0         if ($line =~ /\[A\=(\w+)\]/i) {
259 0           my $align = $1;
260 0           $line =~ s!\[A\=\w+\]!!gi;
261 0 0 0       if (uc($align) eq "CENTER" || uc($align) eq "C") {
    0 0        
    0 0        
262 0           $pad = ((($self->{'_opts'}->{'width'} - 5) - length($s_line)) / 2);
263             }
264             elsif (uc($align) eq "LEFT" || uc($align) eq "L") {
265 0           $pad = 0;
266             }
267             elsif (uc($align) eq "RIGHT" || uc($align) eq "R") {
268 0           $pad = (($self->{'_opts'}->{'width'} - 5) - length($s_line));
269             }
270             }
271 0 0         if ($pad) {
272 0           $text .= (" " x $pad).$new_line;
273             }
274             else {
275 0           $text .= $line . $new_line;
276             }
277             }
278 0           chomp($text);
279 0           return($self->_filter_text($text));
280             }
281             sub _strip_text {
282 0     0     my $self = shift();
283 0           my $text = shift();
284 0           $text =~ s!\\Z0!!gmi;
285 0           $text =~ s!\\Z1!!gmi;
286 0           $text =~ s!\\Z2!!gmi;
287 0           $text =~ s!\\Z3!!gmi;
288 0           $text =~ s!\\Z4!!gmi;
289 0           $text =~ s!\\Z5!!gmi;
290 0           $text =~ s!\\Z6!!gmi;
291 0           $text =~ s!\\Z7!!gmi;
292 0           $text =~ s!\\Zb!!gmi;
293 0           $text =~ s!\\ZB!!gmi;
294 0           $text =~ s!\\Zu!!gmi;
295 0           $text =~ s!\\ZU!!gmi;
296 0           $text =~ s!\\Zr!!gmi;
297 0           $text =~ s!\\ZR!!gmi;
298 0           $text =~ s!\\Zn!!gmi;
299 0           $text =~ s!\[C=black\]!!gmi;
300 0           $text =~ s!\[C=red\]!!gmi;
301 0           $text =~ s!\[C=green\]!!gmi;
302 0           $text =~ s!\[C=yellow\]!!gmi;
303 0           $text =~ s!\[C=blue\]!!gmi;
304 0           $text =~ s!\[C=magenta\]!!gmi;
305 0           $text =~ s!\[C=cyan\]!!gmi;
306 0           $text =~ s!\[C=white\]!!gmi;
307 0           $text =~ s!\[B\]!!gmi;
308 0           $text =~ s!\[/B\]!!gmi;
309 0           $text =~ s!\[U\]!!gmi;
310 0           $text =~ s!\[/U\]!!gmi;
311 0           $text =~ s!\[R\]!!gmi;
312 0           $text =~ s!\[/R\]!!gmi;
313 0           $text =~ s!\[N\]!!gmi;
314 0           $text =~ s!\[A=\w+\]!!gmi;
315 0           return($text);
316             }
317             sub _filter_text {
318 0     0     my $self = shift();
319 0   0       my $text = shift() || return();
320 0 0 0       if ($self->is_cdialog() && $self->{'_opts'}->{'colours'}) {
321 0           $text =~ s!\[C=black\]!\\Z0!gmi;
322 0           $text =~ s!\[C=red\]!\\Z1!gmi;
323 0           $text =~ s!\[C=green\]!\\Z2!gmi;
324 0           $text =~ s!\[C=yellow\]!\\Z3!gmi;
325 0           $text =~ s!\[C=blue\]!\\Z4!gmi;
326 0           $text =~ s!\[C=magenta\]!\\Z5!gmi;
327 0           $text =~ s!\[C=cyan\]!\\Z6!gmi;
328 0           $text =~ s!\[C=white\]!\\Z7!gmi;
329 0           $text =~ s!\[B\]!\\Zb!gmi;
330 0           $text =~ s!\[/B\]!\\ZB!gmi;
331 0           $text =~ s!\[U\]!\\Zu!gmi;
332 0           $text =~ s!\[/U\]!\\ZU!gmi;
333 0           $text =~ s!\[R\]!\\Zr!gmi;
334 0           $text =~ s!\[/R\]!\\ZR!gmi;
335 0           $text =~ s!\[N\]!\\Zn!gmi;
336 0           $text =~ s!\[A=\w+\]!!gmi;
337 0           return($text);
338             }
339             else {
340 0           return($self->_strip_text($text));
341             }
342             }
343              
344              
345             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
346             #: Public Methods
347             #:
348              
349             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
350             #: test for the good stuff
351             sub is_cdialog {
352 0     0 0   my $self = $_[0];
353 0 0 0       return(1) if $self->{'_variant'} && $self->{'_variant'} eq "cdialog";
354 0           return(0);
355             }
356              
357             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
358             #: Ask a binary question (Yes/No)
359             sub yesno {
360 0     0 1   my $self = shift();
361 0   0       my $caller = (caller(1))[3] || 'main';
362 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
363 0 0 0       if ($_[0] && $_[0] eq 'caller') {
364 0           shift(); $caller = shift();
  0            
365             }
366 0           my $args = $self->_pre($caller,@_);
367              
368 0           my $fmt = $self->prepare_format($args);
369 0           $fmt = $self->append_format_base($args,$fmt);
370 0           $fmt = $self->append_format($fmt,'--yesno {{text}} {{height}} {{width}}');
371             my $command = $self->prepare_command
372             ( $args, $fmt,
373 0           text => $self->make_kvt($args,$args->{'text'}),
374             );
375              
376 0           my $rv = $self->command_state($command);
377 0 0 0       if ($rv && $rv >= 1) {
378 0           $self->ra("NO");
379 0           $self->rs("NO");
380 0           $self->rv($rv);
381             }
382             else {
383 0           $self->ra("YES");
384 0           $self->rs("YES");
385 0           $self->rv('null');
386             }
387 0           $self->_post($args);
388 0 0         return($rv == 0 ? 1 : 0);
389             }
390              
391             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
392             #: Text entry
393             sub inputbox {
394 0     0 1   my $self = shift();
395 0   0       my $caller = (caller(1))[3] || 'main';
396 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
397 0 0 0       if ($_[0] && $_[0] eq 'caller') {
398 0           shift(); $caller = shift();
  0            
399             }
400 0           my $args = $self->_pre($caller,@_);
401              
402 0           my $fmt = $self->prepare_format($args);
403 0           $fmt = $self->append_format_base($args,$fmt);
404 0 0         if ($args->{'password'}) {
405 0 0         if ($args->{'entry'}) {
406 0           $fmt = $self->append_format($fmt,'--insecure');
407             } else {
408 0           $fmt = $self->append_format_check($args,$fmt,'insecure','--insecure');
409             }
410 0           $fmt = $self->append_format($fmt,'--passwordbox');
411             }
412             else {
413 0           $fmt = $self->append_format($fmt,'--inputbox');
414             }
415 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}} {{entry}}');
416             my $command = $self->prepare_command
417             ( $args, $fmt,
418             text => $self->make_kvt($args,$args->{'text'}),
419 0   0       entry => $self->make_kvl($args,($args->{'init'}||$args->{'entry'})),
420             );
421              
422 0           my ($rv,$text) = $self->command_string($command);
423 0           $self->_post($args);
424 0 0         return($rv == 0 ? $text : 0);
425             }
426             #: password boxes aren't supported by gdialog
427             sub password {
428 0     0 1   my $self = shift();
429 0   0       return($self->inputbox('caller',((caller(1))[3]||'main'),@_,'password',1));
430             }
431              
432             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
433             #: Text box
434             sub msgbox {
435 0     0 1   my $self = shift();
436 0   0       my $caller = (caller(1))[3] || 'main';
437 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
438 0 0 0       if ($_[0] && $_[0] eq 'caller') {
439 0           shift(); $caller = shift();
  0            
440             }
441 0           my $args = $self->_pre($caller,@_);
442              
443 0   0       $args->{'msgbox'} ||= 'msgbox';
444              
445 0           my $fmt = $self->prepare_format($args);
446 0           $fmt = $self->append_format_base($args,$fmt);
447 0 0         if ($args->{'infobox'}) {
448 0           $fmt = $self->append_format($fmt,'--infobox');
449             }
450             else {
451 0           $fmt = $self->append_format($fmt,'--msgbox');
452             }
453 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}}');
454             my $command = $self->prepare_command
455             ( $args, $fmt,
456 0           text => $self->make_kvt($args,$args->{'text'}),
457             );
458              
459 0           my $rv = $self->command_state($command);
460 0 0         if ($args->{'infobox'}) {
461 0           my $sec = 0;
462 0 0         if ($args->{'timeout'}) {
    0          
463 0 0         $sec = int($args->{'timeout'} ? ($args->{'timeout'} / 1000.0) : 1.0);
464 0           $self->_debug("Will sleep for timeout=".$sec);
465             } elsif ($args->{'wait'}) {
466 0 0         $sec = int($args->{'wait'} ? $args->{'wait'} : 1);
467 0           $self->_debug("Will sleep for wait=".$sec);
468             }
469 0 0         sleep($sec) if $sec;
470             }
471 0           $self->_post($args);
472 0 0         return($rv == 0 ? 1 : 0);
473             }
474             sub infobox {
475 0     0 1   my $self = shift();
476 0   0       return($self->msgbox('caller',((caller(1))[3]||'main'),@_,'infobox',1));
477             }
478              
479             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480             #: File box
481             sub textbox {
482 0     0 1   my $self = shift();
483 0   0       my $caller = (caller(1))[3] || 'main';
484 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
485 0 0 0       if ($_[0] && $_[0] eq 'caller') {
486 0           shift(); $caller = shift();
  0            
487             }
488 0           my $args = $self->_pre($caller,@_);
489              
490 0           my $fmt = $self->prepare_format($args);
491 0           $fmt = $self->append_format_base($args,$fmt);
492 0           $fmt = $self->append_format($fmt,'--scrolltext');
493 0           $fmt = $self->append_format($fmt,'--textbox');
494 0           $fmt = $self->append_format($fmt,'{{path}} {{height}} {{width}}');
495             my $command = $self->prepare_command
496             ( $args, $fmt,
497 0   0       path => $self->make_kvl($args,($args->{'path'}||'.')),
498             );
499              
500 0           my ($rv,$text) = $self->command_string($command);
501 0           $self->_post($args);
502 0 0         return($rv == 0 ? 1 : 0);
503             }
504              
505             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
506             #: a simple menu
507             sub menu {
508 0     0 1   my $self = shift();
509 0   0       my $caller = (caller(1))[3] || 'main';
510 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
511 0 0 0       if ($_[0] && $_[0] eq 'caller') {
512 0           shift(); $caller = shift();
  0            
513             }
514 0           my $args = $self->_pre($caller,@_);
515              
516             $args->{'listheight'} = $args->{'menuheight'}
517 0 0         if exists $args->{'menuheight'};
518              
519 0           my $fmt = $self->prepare_format($args);
520 0           $fmt = $self->append_format_base($args,$fmt);
521 0           $fmt = $self->append_format($fmt,'--menu');
522 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}} {{listheight}} {{list}}');
523             my $command = $self->prepare_command
524             ( $args, $fmt,
525 0           text => $self->make_kvt($args,$args->{'text'}),
526             );
527              
528 0           my ($rv,$selected) = $self->command_string($command);
529 0           $self->_post($args);
530 0 0         return($rv == 0 ? $selected : 0);
531             }
532              
533             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
534             #: a check list
535             sub checklist {
536 0     0 1   my $self = shift();
537 0   0       my $caller = (caller(1))[3] || 'main';
538 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
539 0 0 0       if ($_[0] && $_[0] eq 'caller') {
540 0           shift(); $caller = shift();
  0            
541             }
542 0           my $args = $self->_pre($caller,@_);
543              
544             $args->{'listheight'} = $args->{'menuheight'}
545 0 0         if exists $args->{'menuheight'};
546              
547 0           my $fmt = $self->prepare_format($args);
548 0           $fmt = $self->append_format_base($args,$fmt);
549 0   0       $args->{radiolist} ||= 0;
550 0 0         if ($args->{radiolist}) {
551 0           $fmt = $self->append_format($fmt,'--radiolist');
552             }
553             else {
554 0           $fmt = $self->append_format($fmt,'--separate-output');
555 0           $fmt = $self->append_format($fmt,'--checklist');
556             }
557 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}} {{listheight}} {{list}}');
558             my $command = $self->prepare_command
559             ( $args, $fmt,
560 0           text => $self->make_kvt($args,$args->{'text'}),
561             );
562              
563 0 0         if ($args->{radiolist}) {
564 0           my ($rv,$selected) = $self->command_string($command);
565 0 0         return($rv == 0 ? $selected : 0);
566             }
567 0           my ($rv,$selected) = $self->command_array($command);
568 0 0         return($rv == 0 ? @{$selected} : 0);
  0            
569             }
570             #: a radio button list
571             sub radiolist {
572 0     0 1   my $self = shift();
573 0   0       return($self->checklist('caller',((caller(1))[3]||'main'),@_,'radiolist',1));
574             }
575              
576             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
577             #: file select
578             sub fselect {
579 0     0 1   my $self = shift();
580 0 0         unless ($self->is_cdialog()) {
581 0           return($self->SUPER::fselect(@_));
582             }
583 0   0       my $caller = (caller(1))[3] || 'main';
584 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
585 0 0 0       if ($_[0] && $_[0] eq 'caller') {
586 0           shift(); $caller = shift();
  0            
587             }
588 0           my $args = $self->_pre($caller,@_);
589              
590 0           my $fmt = $self->prepare_format($args);
591 0           $fmt = $self->append_format_base($args,$fmt);
592 0           $fmt = $self->append_format($fmt,'--fselect');
593 0           $fmt = $self->append_format($fmt,'{{path}} {{height}} {{width}}');
594              
595             my $command = $self->prepare_command
596             ( $args, $fmt,
597 0   0       path => $self->make_kvl($args,($args->{'path'}||'.')),
598             );
599              
600 0           my ($rv,$file) = $self->command_string($command);
601 0           $self->_post($args);
602 0 0         return($rv == 0 ? $file : 0);
603             }
604              
605             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
606             #: calendar
607              
608             sub calendar {
609 0     0 1   my $self = shift();
610 0   0       my $caller = (caller(1))[3] || 'main';
611 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
612 0 0 0       if ($_[0] && $_[0] eq 'caller') {
613 0           shift(); $caller = shift();
  0            
614             }
615 0           my $args = $self->_pre($caller,@_);
616 0   0       $args->{'day'} ||= '1';
617 0   0       $args->{'month'} ||= '1';
618 0   0       $args->{'year'} ||= '1970';
619              
620 0           my $fmt = $self->prepare_format($args);
621 0           $fmt = $self->append_format_base($args,$fmt);
622 0           $fmt = $self->append_format($fmt,'--calendar {{text}} {{listheight}} {{width}} {{day}} {{month}} {{year}}');
623             my $command = $self->prepare_command
624             ( $args, $fmt,
625 0           text => $self->make_kvt($args,$args->{'text'}),
626             );
627              
628 0           my ($rv,$date) = $self->command_string($command);
629 0 0         if ($rv == 0) {
630 0           $self->ra(split(m!/!,$date));
631             }
632 0           $self->_post($args);
633 0 0 0       return($rv == 0 ? $date : 0) unless defined wantarray and wantarray;
    0          
634 0 0         return($rv == 0 ? $self->ra() : (0,0,0));
635             }
636              
637             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
638             #: timebox
639              
640             sub timebox {
641 0     0 1   my $self = shift();
642 0   0       my $caller = (caller(1))[3] || 'main';
643 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
644 0 0 0       if ($_[0] && $_[0] eq 'caller') {
645 0           shift(); $caller = shift();
  0            
646             }
647 0           my $args = $self->_pre($caller,@_);
648 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
649 0   0       $args->{'hour'} ||= $hour;
650 0   0       $args->{'minute'} ||= $min;
651 0   0       $args->{'second'} ||= $sec;
652              
653 0           my $fmt = $self->prepare_format($args);
654 0           $fmt = $self->append_format_base($args,$fmt);
655 0           $fmt = $self->append_format($fmt,'--timebox {{text}} {{height}} {{width}} {{hour}} {{minute}} {{second}}');
656             my $command = $self->prepare_command
657             ( $args, $fmt,
658 0           text => $self->make_kvt($args,$args->{'text'}),
659             );
660              
661 0           my ($rv,$time) = $self->command_string($command);
662 0 0         if ($rv == 0) {
663 0           $self->ra(split(m!\:!,$time));
664             }
665 0           $self->_post($args);
666 0 0 0       return($rv == 0 ? $time : 0) unless defined wantarray and wantarray;
    0          
667 0 0         return($rv == 0 ? $self->ra() : (0,0,0));
668             }
669              
670             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
671             #: tailbox
672              
673             sub tailbox {
674 0     0 1   my $self = shift();
675 0   0       my $caller = (caller(1))[3] || 'main';
676 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
677 0 0 0       if ($_[0] && $_[0] eq 'caller') {
678 0           shift(); $caller = shift();
  0            
679             }
680 0           my $args = $self->_pre($caller,@_);
681              
682 0           my $fmt = $self->prepare_format($args);
683 0           $fmt = $self->append_format_base($args,$fmt);
684 0           $fmt = $self->append_format($fmt,'--tailbox');
685 0           $fmt = $self->append_format($fmt,'{{path}} {{height}} {{width}}');
686             my $command = $self->prepare_command
687             ( $args, $fmt,
688 0   0       path => $self->make_kvl($args,($args->{'path'}||'.')),
689             );
690              
691 0           my ($rv) = $self->command_state($command);
692 0           $self->_post($args);
693 0 0         return($rv == 0 ? 1 : 0);
694             }
695              
696             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
697             #: tailboxbg
698              
699             sub tailboxbg {
700 0     0 0   my $self = shift();
701 0   0       my $caller = (caller(1))[3] || 'main';
702 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
703 0 0 0       if ($_[0] && $_[0] eq 'caller') {
704 0           shift(); $caller = shift();
  0            
705             }
706 0           my $args = $self->_pre($caller,@_);
707              
708 0           my $fmt = $self->prepare_format($args);
709 0           $fmt = $self->append_format_base($args,$fmt);
710 0           $fmt = $self->append_format($fmt,'--tailboxbg');
711 0           $fmt = $self->append_format($fmt,'{{path}} {{height}} {{width}}');
712             my $command = $self->prepare_command
713             ( $args, $fmt,
714 0   0       path => $self->make_kvl($args,($args->{'path'}||'.')),
715             );
716              
717 0           my ($rv) = $self->command_state($command);
718 0           $self->_post($args);
719 0 0         return($rv == 0 ? 1 : 0);
720             }
721              
722             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
723             #: an editable form (wow is this useful! holy cripes!)
724             sub form {
725 0     0 1   my $self = shift();
726 0   0       my $caller = (caller(1))[3] || 'main';
727 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
728 0 0 0       if ($_[0] && $_[0] eq 'caller') {
729 0           shift(); $caller = shift();
  0            
730             }
731 0           my $args = $self->_pre($caller,@_);
732              
733             $args->{'listheight'} = $args->{'menuheight'}
734 0 0         if exists $args->{'menuheight'};
735             $args->{'listheight'} = $args->{'formheight'}
736 0 0         if exists $args->{'formheight'};
737              
738 0           my $fmt = $self->prepare_format($args);
739 0           $fmt = $self->append_format_base($args,$fmt);
740 0           $fmt = $self->append_format($fmt,'--form');
741 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}} {{listheight}} {{list}}');
742              
743 0           my $list = '';
744 0           while (@{$args->{'list'}}) {
  0            
745 0           my $item = shift(@{$args->{'list'}});
  0            
746 0           my $info = shift(@{$args->{'list'}});
  0            
747 0           $self->clean_format($args->{'trust-input'},\$item->[0]);
748 0           $self->clean_format($args->{'trust-input'},\$item->[1]);
749 0           $self->clean_format($args->{'trust-input'},\$item->[2]);
750 0           $self->clean_format($args->{'trust-input'},\$info->[0]);
751 0           $self->clean_format($args->{'trust-input'},\$info->[1]);
752 0           $self->clean_format($args->{'trust-input'},\$info->[2]);
753 0           $self->clean_format($args->{'trust-input'},\$info->[3]);
754 0           $self->clean_format($args->{'trust-input'},\$info->[4]);
755 0   0       $list .= ' "'.($item->[0]||' ').'" "'.$item->[1].'" "'.$item->[2].'" "'.($info->[0]||' ').'" "'.$info->[1].'" "'.$info->[2].'" "'.$info->[3].'" "'.$info->[4].'"';
      0        
756             }
757 0           delete $args->{'list'};
758 0           $args->{'list'} = $list;
759              
760             my $command = $self->prepare_command
761             ( $args, $fmt,
762 0           list => $self->make_kvl($args,$args->{'list'}),
763             );
764              
765 0           my ($rv,$selected) = $self->command_array($command);
766 0           $self->_post($args);
767 0 0 0       return($rv == 0 ? $selected : 0) unless defined wantarray and wantarray;
    0          
768 0 0         return($rv == 0 ? $self->ra() : (0));
769             }
770              
771             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
772             #: progress meter
773             sub gauge_start {
774 0     0 1   my $self = shift();
775 0   0       my $caller = (caller(1))[3] || 'main';
776 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
777 0 0 0       if ($_[0] && $_[0] eq 'caller') {
778 0           shift(); $caller = shift();
  0            
779             }
780 0           my $args = $self->_pre($caller,@_);
781              
782 0   0       $self->{'_GAUGE'} ||= {};
783 0           $self->{'_GAUGE'}->{'ARGS'} = $args;
784              
785 0 0         if (defined $self->{'_GAUGE'}->{'FH'}) {
786 0           $self->rv(129);
787 0           $self->_post($args);
788 0           return(0);
789             }
790              
791 0           my $fmt = $self->prepare_format($args);
792 0           $fmt = $self->append_format_base($args,$fmt);
793 0           $fmt = $self->append_format($fmt,'--gauge');
794 0           $fmt = $self->append_format($fmt,'{{text}} {{height}} {{width}} {{percentage}}');
795             my $command = $self->prepare_command
796             ( $args, $fmt,
797             text => $self->make_kvt($args,$args->{'text'}),
798 0   0       percentage => $self->make_kvl($args,$args->{'percentage'}||'0'),
799             );
800              
801 0   0       $self->{'_GAUGE'}->{'PERCENT'} = ($args->{'percentage'} || '0');
802 0           $self->{'_GAUGE'}->{'FH'} = new FileHandle;
803 0           $self->{'_GAUGE'}->{'FH'}->open("| $command");
804 0           my $rv = $? >> 8;
805 0           $self->{'_GAUGE'}->{'FH'}->autoflush(1);
806 0   0       $self->rv($rv||'null');
807 0           $self->ra('null');
808 0           $self->rs('null');
809 0   0       return($rv && $rv >= 1);
810             }
811             sub gauge_inc {
812 0     0 1   my $self = $_[0];
813 0   0       my $incr = $_[1] || 1;
814              
815 0 0         return(0) unless defined $self->{'_GAUGE'}->{'FH'};
816              
817 0           my $fh = $self->{'_GAUGE'}->{'FH'};
818 0           $self->{'_GAUGE'}->{'PERCENT'} += $incr;
819 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
820 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
821 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
822             }
823             sub gauge_dec {
824 0     0 1   my $self = $_[0];
825 0   0       my $decr = $_[1] || 1;
826              
827 0 0         return(0) unless defined $self->{'_GAUGE'}->{'FH'};
828              
829 0           my $fh = $self->{'_GAUGE'}->{'FH'};
830 0           $self->{'_GAUGE'}->{'PERCENT'} -= $decr;
831 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
832 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
833 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
834             }
835             sub gauge_set {
836 0     0 1   my $self = $_[0];
837 0   0       my $perc = $_[1] || $self->{'_GAUGE'}->{'PERCENT'} || 1;
838              
839 0 0         return(0) unless $self->{'_GAUGE'}->{'FH'};
840              
841 0           my $fh = $self->{'_GAUGE'}->{'FH'};
842 0           $self->{'_GAUGE'}->{'PERCENT'} = $perc;
843 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
844 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
845 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
846             }
847             # funky flicker... grr
848             sub gauge_text {
849 0     0 1   my $self = $_[0];
850 0   0       my $mesg = $_[1] || return(0);
851              
852 0 0         return(0) unless $self->{'_GAUGE'}->{'FH'};
853              
854 0           my $fh = $self->{'_GAUGE'}->{'FH'};
855 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
856 0           print $fh "\nXXX\n\n".$mesg."\n\nXXX\n\n".$self->{'_GAUGE'}->{'PERCENT'}."\n";
857 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
858             }
859             sub gauge_stop {
860 0     0 1   my $self = $_[0];
861              
862 0 0         return(0) unless $self->{'_GAUGE'}->{'FH'};
863              
864 0           my $args = $self->{'_GAUGE'}->{'ARGS'};
865 0           my $fh = $self->{'_GAUGE'}->{'FH'};
866 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
867 0           $self->{'_GAUGE'}->{'FH'}->close();
868 0           delete($self->{'_GAUGE'}->{'FH'});
869 0           delete($self->{'_GAUGE'}->{'ARGS'});
870 0           delete($self->{'_GAUGE'}->{'PERCENT'});
871 0           delete($self->{'_GAUGE'});
872 0           $self->rv('null');
873 0           $self->rs('null');
874 0           $self->ra('null');
875 0           $self->_post($args);
876 0           return(1);
877             }
878              
879              
880             1;
881