File Coverage

blib/lib/Ante/Deluvian/Dialog.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Ante::Deluvian::Dialog;
2              
3 1     1   36086 use strict;
  1         3  
  1         42  
4 1     1   6 use warnings;
  1         2  
  1         32  
5 1     1   423 use Term::ReadKey;
  0            
  0            
6             use Text::Wrap qw($columns wrap);
7             use IO::File;
8              
9             our $VERSION = 0.02;
10             sub FALSE { return 0; }
11             sub TRUE { return 1; }
12             my $_isWin = FALSE;
13             my $_doRec = FALSE;
14             my $_rplay = FALSE;
15             my $_fhInp = undef;
16             my $_fhRec = undef;
17              
18             #------------------------------------------------------------------
19             sub new {
20             #------------------------------------------------------------------
21             my $class = shift;
22             my %param = @_;
23             my $self = {};
24             my ($iCols, $iRows);
25            
26             $self = bless {}, $class;
27             $self->{'rows'} = 25;
28             $self->{'cols'} = 80;
29             $self->{'stat'} = 0;
30             $self->{'from'} = 1;
31             $self->{'eoln'} = "";
32             $self->{'curpid'} = $$,
33             $self->{'getdrv'} = \&_procDfCmd,
34             $self->{'usable'} = 25;
35             $self->{'hcenter'} = 12;
36             $self->{'vcenter'} = 40;
37             $self->{'recary'} = [];
38             $self->{'parind'} = $param{parindent} || 2;
39             $self->{'title'} = $param{title} || undef;
40             $self->{'header'} = $param{header} || " ";
41             $self->{'prompt'} = $param{prompt} || ":";
42             $self->{'platform'} = $param{platform} || "UNIX";
43             $_isWin = $param{platform} eq "MSWIN";
44             $_doRec = $param{record} || FALSE;
45             $_fhInp = $param{inpfile} || undef;
46             if ((exists($param{replay})) && (-s $param{replay})) {
47             my $fi = IO::File->new("< $param{replay}");
48             @{$self->{'recary'}} = <$fi>;
49             $fi->close();
50             $_rplay = TRUE;
51             }
52             $self->_getWinSize();
53             $self->{'usable'} = $self->{'rows'};
54             if (defined($self->{'header'})) {
55             $self->{'usable'}--;
56             $self->{'stat'}++;
57             $self->{'from'}++;
58             }
59             if (defined($self->{'prompt'})) {
60             $self->{'usable'}--;
61             }
62             $self->{'hcenter'} = int ($self->{'cols'} / 2);
63             $self->{'vcenter'} = int (($self->{'usable'} - $self->{'from'}) / 2);
64             $self->{'lines'} = $self->_drawframe();
65             $self->{'usable'} -= 2;
66             return $self;
67             }
68              
69             #------------------------------------------------------------------
70             sub DESTROY {
71             #------------------------------------------------------------------
72             my $self = shift;
73            
74             if ($_doRec) {
75             $self->_createRecFile();
76             print $_fhRec "@{$self->{'recary'}}\n";
77             }
78             }
79              
80             #------------------------------------------------------------------
81             sub _getWinSize {
82             #------------------------------------------------------------------
83             my $self = shift;
84             my ($maxCol, $maxRow);
85            
86             if ($_isWin) {
87             require Win32::Console;
88             my $cns = new Win32::Console();
89             my @info =$cns->Info();
90             ($maxCol, $maxRow) = $cns->MaxWindow();
91             $self->{'gdrv'} = \&_procNetUse;
92             $self->{'eoln'} = "\n";
93             }
94             else {
95             ($maxCol, $maxRow) = GetTerminalSize();
96             }
97             $self->{'cols'} = $maxCol;
98             $self->{'rows'} = $maxRow;
99             }
100              
101             #------------------------------------------------------------------
102             sub _createRecFile {
103             #------------------------------------------------------------------
104             my $self = shift;
105             my $tmpth = $_isWin ? "C:/temp/addialog" : "/tmp/addialog";
106             my $tmpf = sprintf("%s/%s_%d", $tmpth, $_isWin ? $ENV{USERNAME} : $ENV{USER}, $self->{'curpid'});
107            
108             if (! -d $tmpth) {
109             mkdir($tmpth);
110             }
111             $_fhRec = IO::File->new("> $tmpf");
112             print "File $tmpf created to record user input ...\n";
113             }
114              
115             #------------------------------------------------------------------
116             sub _drawframe {
117             #------------------------------------------------------------------
118             my $self = shift;
119             my $rows = $self->{'rows'} - 1;
120             my $cols = $self->{'cols'} - 2;
121             my ($line, @lines, $inp);
122            
123             if (defined($self->{'prompt'})) {
124             $rows--;
125             }
126             for my $i (0 .. $rows) {
127             if (($i == 0) || ($i == $rows)) {
128             push @lines, "+" . "-" x $cols . "+";
129             }
130             else {
131             push @lines, "|" . " " x $cols . "|";
132             }
133             }
134             if (defined($self->{'title'})) {
135             _formatline(\$lines[0], $self->{'title'}, "C");
136             }
137             if (defined($self->{'prompt'})) {
138             push @lines, "$self->{'prompt'} ";
139             }
140             return [ @lines ];
141             }
142              
143             #------------------------------------------------------------------
144             sub _doselection {
145             #
146             # This function is likely to be called recursively ...
147             #------------------------------------------------------------------
148             my $self = shift;
149             my %param = @_;
150            
151             my $rpag = $param{pagary};
152             my $rsel = $param{selary};
153             my $inpt = $param{input};
154             my $mode = $param{selmod};
155            
156             my $j = int($inpt / $self->{'usable'}) + 1;
157             my $k = int($inpt % $self->{'usable'}) + $self->{'from'};
158             print "_doselection (..., $inpt, $mode) j = $j k = $k ...\n";
159             if ($mode eq "single") {
160             if (defined($rsel->[0])) {
161             $self->_doselection(
162             selary => $rsel,
163             pagary => $rpag,
164             input => $rsel->[0],
165             selmod => "discard",
166             );
167             }
168             $self->_doselection(
169             selary => $rsel,
170             pagary => $rpag,
171             input => $inpt,
172             selmod => "select",
173             );
174             $rsel->[0] = $inpt;
175             }
176             elsif ($mode eq "multi") {
177             $self->_doselection(
178             selary => $rsel,
179             pagary => $rpag,
180             input => $inpt,
181             selmod => "toggle",
182             );
183             }
184             elsif ($mode eq "toggle") {
185             if (substr($rpag->[$j][$k], 2, 1) eq " ") {
186             substr($rpag->[$j][$k], 2, 1) = "*";
187             $rsel->[$inpt + 1] = 1;
188             }
189             else {
190             substr($rpag->[$j][$k], 2, 1) = " ";
191             $rsel->[$inpt + 1] = 0;
192             }
193             }
194             elsif ($mode eq "discard") {
195             substr($rpag->[$j][$k], 2, 1) = " ";
196             $rsel->[$inpt + 1] = 0;
197             }
198             elsif ($mode eq "select") {
199             substr($rpag->[$j][$k], 2, 1) = "*";
200             $rsel->[$inpt + 1] = 1;
201             }
202             elsif ($mode eq "all") {
203             foreach my $elm (1 .. $#$rsel) {
204             $self->_doselection(
205             selary => $rsel,
206             pagary => $rpag,
207             input => $elm - 1,
208             selmod => "select",
209             );
210             }
211             }
212             elsif ($mode eq "clear") {
213             foreach my $elm (1 .. $#$rsel) {
214             $self->_doselection(
215             selary => $rsel,
216             pagary => $rpag,
217             input => $elm - 1,
218             selmod => "discard",
219             );
220             $rsel->[0] = undef;
221             }
222             }
223             }
224              
225             #------------------------------------------------------------------
226             sub _getDrives {
227             #------------------------------------------------------------------
228             my $self = shift;
229             my (@drives, @drvlst, $line, $cmd, $pattern, $drv,
230             %windrv,
231             );
232            
233             if ($_isWin) {
234             for $drv ("A" .. "Z") {
235             $windrv{"$drv:"} = 0;
236             }
237             $cmd = "net use";
238             $pattern = "\\A\\w+\\s+([A-Z]:)\\s+(\\\\\\\\\\S+)";
239             }
240             else {
241             $cmd = "df | awk '{ print \$NF }'";
242             $pattern = "%\\s+(\/\\S*)\\z";
243             }
244             open(SYST, "$cmd |");
245             while ($line = ) {
246             if ($line =~ /$pattern/) {
247             push @drives, "$1/";
248             push @drvlst, "$1/ $2";
249             if (exists($windrv{$1})) {
250             delete($windrv{$1});
251             }
252             }
253             }
254             close(SYST);
255             if ($_isWin) {
256             foreach $drv (keys %windrv) {
257             if (-d "$drv/") {
258             push @drives, "$drv/";
259             push @drvlst, "$drv/ Local directory";
260             }
261             }
262             }
263             @drvlst = sort(@drvlst);
264             $drv = $self->listbox(\@drvlst, select => "atonce", prompt => "Please select a drive or partition:");
265             if ($_isWin && ($drv =~ /\A([A-Z]:\/)\s+/)) {
266             $drv = $1;
267             }
268             elsif ($drv =~ /\A(\/\S*)/) {
269             $drv = $1;
270             }
271             else {
272             $drv = undef;
273             }
274             # print "Selected drive: $drv ...\n";
275             return($drv);
276             }
277              
278             #------------------------------------------------------------------
279             sub printscreen {
280             #------------------------------------------------------------------
281             my $self = shift;
282             my $rlines = shift;
283             my (@lines, $prompt);
284            
285             if (defined($rlines)) {
286             @lines = @$rlines;
287             }
288             else {
289             @lines = @{$self->{'lines'}};
290             }
291             if (defined($self->{'prompt'})) {
292             $prompt = pop(@lines);
293             }
294             foreach my $line (@lines) {
295             print "$line" . $self->{'eoln'};
296             }
297             if (defined($prompt)) {
298             print "$prompt ";
299             }
300             }
301              
302             #------------------------------------------------------------------
303             sub _getinput {
304             #------------------------------------------------------------------
305             my $self = shift;
306             my $rLines = shift;
307            
308             $self->printscreen($rLines);
309             if ($_rplay && ($#{$self->{'recary'}} >= 0)) {
310             $self->{'input'} = shift(@{$self->{'recary'}});
311             print "$self->{'input'}";
312             }
313             else {
314             $self->{'input'} = ;
315             }
316             chomp($self->{'input'});
317             if ($_doRec) {
318             # print $self->{'recfile'} "$self->{'input'}";
319             push @{$self->{'recary'}}, $self->{'input'};
320             }
321             }
322              
323             #------------------------------------------------------------------
324             sub _clearselection {
325             #------------------------------------------------------------------
326             my $self = shift;
327             }
328              
329             #------------------------------------------------------------------
330             sub _formatline {
331             #------------------------------------------------------------------
332             # my $self = shift;
333             my $line = shift;
334             my $text = shift;
335             my $frmt = shift;
336             my ($llng, $ltxt, $beg);
337            
338             $llng = length($$line);
339             $ltxt = length($text);
340             if ($llng > $ltxt) {
341             if ($frmt eq "C") {
342             $beg = int(($llng - $ltxt) / 2);
343             }
344             elsif ($frmt eq "R") {
345             $beg = $llng - $ltxt - 1;
346             }
347             elsif ($frmt eq "L") {
348             $beg = 1;
349             }
350             elsif ($frmt =~ /\A(\d+)/) {
351             $beg = $1;
352             }
353             }
354             else {
355             $text = substr($text, 0, $llng - 5) . "...";
356             $ltxt = length($text);
357             $beg = 1;
358             }
359             # print "LINE: $$line\nTEXT: $text\nFRMT: $frmt BEG: $beg LTXT: $ltxt\n";
360             substr($$line, $beg, $ltxt, $text);
361             }
362              
363             #------------------------------------------------------------------
364             sub alert {
365             #------------------------------------------------------------------
366             my $self = shift;
367             my $rAlert = shift;
368             my $rLines = shift || undef;
369             my ($i, $beg, @lines,
370             );
371            
372             if (defined($rLines)) {
373             @lines = @$rLines;
374             }
375             else {
376             @lines = @{$self->{'lines'}};
377             }
378             if (defined($self->{'prompt'})) {
379             $lines[-1] = $rAlert->[0];
380             }
381             $beg = $self->{'vcenter'} - int(($#$rAlert - 1) / 2);
382             for $i (1 .. $#$rAlert) {
383             _formatline(\$lines[$beg + $i - 1], $rAlert->[$i], "C");
384             }
385             $self->_getinput(\@lines);
386             }
387              
388             #------------------------------------------------------------------
389             sub listbox {
390             #------------------------------------------------------------------
391             my $self = shift;
392             my $rList = shift;
393             my %param = @_;
394             my ($i, $j, $k, $nelm, $nopg, @pages, $len, $elm,
395             $entry, $currpg, $inp, @inps, @lines, $rpage, $selmode,
396             @selary, $isTxt, $rLines,
397             );
398            
399             $rLines = $param{lines} || undef;
400             $selmode = $param{select} || "single";
401             if ((defined($param{input})) && ($param{input} eq "text")) {
402             $isTxt = TRUE;
403             }
404             else { $isTxt = FALSE; }
405             $nelm = $#$rList + 1;
406             if (0 == $nelm) { return; }
407             else {
408             $selary[0] = undef;
409             for $i (1 .. $nelm) {
410             $selary[$i] = 0;
411             }
412             }
413             if (defined($rLines)) {
414             @lines = @$rLines;
415             }
416             else {
417             @lines = @{$self->{'lines'}};
418             }
419             if ((exists($param{'prompt'})) && (defined($self->{'prompt'}))) {
420             $lines[-1] = $param{'prompt'};
421             }
422             $len = length($nelm);
423             $nopg = int($nelm / $self->{'usable'});
424             if ($nelm % $self->{'usable'} > 0) { $nopg++; };
425             print "List contains $nelm elements and will result in $nopg pages ...\n";
426             for $i (1 .. $nopg) {
427             $pages[$i] = [ @lines ];
428             _formatline(\$pages[$i]->[$self->{'stat'}], "Page $i from $nopg ...", "R");
429             }
430             $i = 0;
431             foreach $elm (@$rList) {
432             # $i++;
433             $j = int($i / $self->{'usable'}) + 1;
434             $k = int($i % $self->{'usable'});
435             $rpage = $pages[$j];
436             $i++;
437             if ($isTxt) {
438             $entry = $elm;
439             }
440             else {
441             $entry = sprintf(" %*d. %s", $len, $i, $elm);
442             }
443             # print "_formatline(rpage->[$k], $entry)\n";
444             _formatline(\$rpage->[$self->{'from'} + $k], $entry, "3");
445             }
446             $currpg = 1;
447             LISTBOX:
448             while (TRUE) {
449             $self->_getinput($pages[$currpg]);
450             $inp = $self->{'input'};
451             @inps = split(/\s+/, $inp);
452             foreach $inp (@inps) {
453             # if (($inp =~ /\A\d+\z/) && ($inp >= 1) && ($inp <= $#$rList)) {
454             if (($inp =~ /\A\d+\z/) && ($inp >= 1) && ($inp <= $nelm)) {
455             if ($selmode eq "atonce") {
456             return $rList->[$inp - 1];
457             }
458             $self->_doselection(
459             selary => \@selary,
460             pagary => \@pages,
461             input => $inp - 1,
462             selmod => $selmode,
463             );
464             }
465             elsif (($inp =~ /\A(\d+)-(\d+)/)) {
466             my ($from, $to) = ($1, $2);
467             $to = $nelm if ($to > $nelm);
468             for $i ($from .. $to) {
469             $self->_doselection(
470             selary => \@selary,
471             pagary => \@pages,
472             input => $i - 1,
473             selmod => $selmode,
474             );
475             }
476             }
477             elsif (($inp =~ /\A[Aa][Ll][Ll][Ee]?\z/) && ($selmode eq "multi")) {
478             $self->_doselection(
479             selary => \@selary,
480             pagary => \@pages,
481             input => 0,
482             selmod => "all",
483             );
484             }
485             elsif ($inp =~ /\A[Cc][Ll][EeAa]*[Rr]\z/) {
486             $self->_doselection(
487             selary => \@selary,
488             pagary => \@pages,
489             input => 0,
490             selmod => "clear",
491             );
492             }
493             elsif ($inp =~ /\A:?[nNvV]/) {
494             if ($currpg < $nopg) {
495             $currpg++;
496             }
497             }
498             elsif ($inp =~ /\A:?[pPrR]/) {
499             if ($currpg > 1) {
500             $currpg--;
501             }
502             }
503             elsif ($inp =~ /\A:(\d+)\z/) {
504             $inp = $1;
505             if (($inp >= 1) && ($inp <= $nopg)) {
506             $currpg = $inp;
507             }
508             }
509             elsif ($inp =~ /\A:?[Oo][Kk]\z/) {
510             return("OK") if ($selmode ne "multi");
511             last LISTBOX;
512             }
513             elsif ($inp =~ /\A:?[Ee][Ss][Cc]\z/) {
514             return(undef);
515             # last LISTBOX;
516             }
517             }
518             }
519             @lines = ();
520             for $i (1 .. $nelm) {
521             if ($selary[$i] > 0) {
522             push @lines, $rList->[$i - 1];
523             }
524             }
525             return(@lines);
526             }
527              
528             #------------------------------------------------------------------
529             sub radiolist {
530             #------------------------------------------------------------------
531             my $self = shift;
532             my $rRadLst = shift;
533             my %param = @_;
534             my ($i, $inp, $beg, $line, $lng, @radlist, @lines,
535             $selected, $mark, $radio, $rLines,
536             );
537            
538             $rLines = $param{'lines'} || undef;
539             if (defined($rLines)) {
540             @lines = @$rLines;
541             }
542             else {
543             @lines = @{$self->{'lines'}};
544             }
545             RADIO:
546             while (TRUE) {
547             @radlist = ();
548             if (defined($rRadLst->[0]->[0])) {
549             push @radlist, "$rRadLst->[0]->[0]";
550             $lng = length($rRadLst->[0]->[0]);
551             if ($rRadLst->[0]->[1]) {
552             push @radlist, "-" x $lng;
553             }
554             }
555             for $i (1 .. $#$rRadLst) {
556             if ($rRadLst->[$i]->[2] == 1) {
557             $mark = "X";
558             $selected = $i;
559             }
560             else {
561             $mark = " ";
562             }
563             $line = sprintf ("%2d. (%s) %s", $i, $mark, $rRadLst->[$i]->[0]);
564             push @radlist, "$line";
565             }
566             $beg = $self->{'vcenter'} - int(($#radlist - 1) / 2);
567             for $i (0 .. $#radlist) {
568             _formatline(\$lines[$beg + $i], $radlist[$i], "3");
569             }
570             $self->_getinput(\@lines);
571             $inp = $self->{'input'};
572             if ($inp =~ /:?[Oo][Kk]/) {
573             $radio = $rRadLst->[$selected]->[1];
574             last RADIO;
575             }
576             elsif ($inp =~ /:?[Ee][Ss][Cc]/) {
577             $radio = undef;
578             last RADIO;
579             }
580             elsif (($inp >= 1) && ($inp <= $#$rRadLst)) {
581             $rRadLst->[$selected]->[2] = 0;
582             $rRadLst->[$inp]->[2] = 1;
583             }
584             }
585             return $radio;
586             }
587              
588             #------------------------------------------------------------------
589             sub _select {
590             #------------------------------------------------------------------
591             my $self = shift;
592             my $start = shift;
593             my $fmode = shift;
594             my $rLines = shift;
595             my %hmodes = (
596             "FILE" => [ "atonce", "Please select a file:" ],
597             "DIR" => [ "atonce", "Please select a directory:" ],
598             "MULT" => [ "multi", "Please select one or more entities:" ],
599             );
600             my (@files, $file, @flist, $inp, @lines, $stln,
601             );
602            
603             if (defined($rLines)) {
604             @lines = @$rLines;
605             }
606             else {
607             @lines = @{$self->{'lines'}};
608             }
609             if (defined($self->{'prompt'})) {
610             $lines[-1] = $hmodes{$fmode}[1];
611             }
612             if ((!defined($start)) || ($start eq "")) {
613             $start = $self->_getDrives();
614             }
615             elsif ($start !~ /[\\\/]\z/) {
616             $start .= "/";
617             }
618             print "fselect(..., $start, ...)\n";
619             while (TRUE) {
620             @files = ();
621             @flist = ();
622             opendir (DIR, "$start");
623             @files = readdir(DIR);
624             closedir(DIR);
625             foreach $file (sort @files) {
626             if ($file eq ".") {
627             next;
628             }
629             elsif (-d "$start/$file") {
630             push @flist, "$file/";
631             }
632             elsif ((-f "$start/$file") && ($fmode ne "DIR")) {
633             push @flist, $file;
634             }
635             }
636             $stln = sprintf("%-*s", $self->{'cols'} - 2, $start);
637             _formatline(\$lines[$self->{'stat'}], $stln, "L");
638             $inp = $self->listbox(\@flist, lines => \@lines, select => $hmodes{$fmode}[0]);
639             if (defined($inp)) {
640             print "FSEL: $inp\n";
641             if ($inp =~ /\A\.\.[\\\/]*/) {
642             @files = split(/[\\\/]+/, $start);
643             $start = $files[0];
644             pop(@files); shift(@files);
645             $start = join "/", $start, @files, "";
646             }
647             elsif (-d "$start/$inp") {
648             $start .= $inp;
649             }
650             elsif (-f "$start/$inp") {
651             return("$start$inp");
652             }
653             elsif ($inp eq "OK") {
654             return($start);
655             }
656             print "Neues Verzeichnis: $start ...\n";
657             }
658             else {
659             return(undef);
660             }
661             }
662             }
663              
664             #------------------------------------------------------------------
665             sub fselect {
666             #------------------------------------------------------------------
667             my $self = shift;
668             my $start = shift;
669             my $rLines = shift;
670             my $fmode = shift || "FILE";
671            
672             $self->_select($start, $fmode, $rLines);
673             }
674              
675             #------------------------------------------------------------------
676             sub dselect {
677             #------------------------------------------------------------------
678             my $self = shift;
679             my $start = shift;
680             my $rLines = shift;
681             my $fmode = "DIR";
682            
683             my $dir = $self->_select($start, $fmode, $rLines);
684             return($dir);
685             }
686              
687             #------------------------------------------------------------------
688             sub textbox {
689             #------------------------------------------------------------------
690             my $self = shift;
691             my $itxt = shift;
692             my %param = @_;
693             my $text = undef;
694             my $doFmt = $param{keepformat} || TRUE;
695             my @stNames = qw(
696             dev ino mode nlink uid gid rdev size
697             atime mtime ctime blksize blocks
698             );
699             my (@lines, $fmtxt, $pref,
700             @txtlns, @filstat,
701             );
702            
703             if (!defined($itxt)) {
704             return;
705             }
706             $pref = ref($itxt);
707             if ($pref eq "ARRAY") {
708             @txtlns = @$itxt;
709             }
710             elsif ($pref eq "SCALAR") {
711             $text = $$itxt;
712             # @txtlns = split(/\n/, $$itxt);
713             }
714             elsif ($pref eq "IO::File") {
715             @txtlns = <$itxt>;
716             }
717             elsif (($pref eq "") && (-f $itxt)) {
718             my $fi = IO::File->new("< $itxt");
719             if (-T $itxt) {
720             @txtlns = <$fi>;
721             }
722             else {
723             #$/ = "\0";
724             #while (<$fi>) {
725             # while (/([\040-\176\s]{4,})/g) {
726             # push @txtlns, $1;
727             # }
728             #}
729             $doFmt = FALSE;
730             @filstat = stat($itxt);
731             @txtlns = ( "$itxt", "appears to be a binary file ...", "");
732             foreach my $i (0 .. $#filstat) {
733             push @txtlns, sprintf("%-10s -> %s", $stNames[$i], $stNames[$i] =~ /time/ ? scalar localtime($filstat[$i]) : $filstat[$i]);
734             }
735             }
736             $fi->close();
737             }
738             if ($doFmt) {
739             if (!defined($text)) {
740             $text = join "", @txtlns;
741             }
742             $text =~ s/\n\n+/#PAR#/g;
743             $text =~ tr/[\n\t ]/ /s;
744             print "$text\n";
745             $text =~ s/#PAR#/\n\n/g;
746             $text =~ s/#LN#/\n/g;
747             @txtlns = split(/\t/, $text);
748             $columns = $self->{'cols'} - 4;
749             $text = wrap("", "", @txtlns);
750             @lines = split(/\n/, $text);
751             }
752             else {
753             @lines = @txtlns;
754             }
755             print "Maximal $columns Spalten ...\n\n@lines\n";
756             $self->listbox(\@lines, input => "text");
757             }
758              
759             1;
760             __END__