1#!/usr/bin/perl -w
2
3#use strict vars;
4
5#use Term::ReadKey qw( ReadMode ReadKey );
6#my $x;
7#ReadMode 3;
8#print "Read 1\n";
9#$x = ReadKey(0);
10#print "X=$x\n";
11#print "Read 2\n";
12#$x = ReadKey(0);
13#print "X=$x\n";
14#ReadMode 0;
15#__END__;
16
17my $interactive = ( @ARGV && $ARGV[0] =~ /interactive/ );
18
19BEGIN { print "1..8\n"; }
20END { print "not ok 1\n" unless $loaded }
21use Term::ReadKey;
22
23$loaded = 1;
24print "ok 1\n";
25
26use Fcntl;
27
28if ( not exists $ENV{COLUMNS} )
29{
30    $ENV{COLUMNS} = 80;
31    $ENV{LINES}   = 24;
32}
33
34if ( $^O =~ /Win32/i )
35{
36    sysopen( IN,  'CONIN$',  O_RDWR ) or die "Unable to open console input:$!";
37    sysopen( OUT, 'CONOUT$', O_RDWR ) or die "Unable to open console output:$!";
38}
39else
40{
41
42    if ( open( IN, "</dev/tty" ) )
43    {
44        *OUT = *IN;
45        die "Foo" unless -t OUT;
46    }
47    else
48    {
49
50        # Okay we are going to cheat a skip
51        foreach my $skip ( 2 .. 8 )
52        {
53            print "ok $skip  # skip /dev/tty is absent\n";
54        }
55        exit;
56    }
57}
58
59*IN = *IN;    # Make single-use warning go away
60$|  = 1;
61
62# Bad filehandle: IN at ../lib/Term/ReadKey.pm line 377 with \IN and harness
63my $size1 = join( ",", GetTerminalSize( -t \IN ? \IN : "IN" ) );
64my $size2 = join( ",", GetTerminalSize("IN") );
65my $size3 = join( ",", GetTerminalSize(*IN) );
66my $size4 = join( ",", GetTerminalSize( \*IN ) );
67
68if ( ( $size1 eq $size2 ) && ( $size2 eq $size3 ) && ( $size3 eq $size4 ) )
69{
70    print "ok 2\n";
71}
72else
73{
74    print "not ok 2\n";
75}
76
77sub makenicelist
78{
79    my (@list) = @_;
80    my ( $i, $result );
81    $result = "";
82    for ( $i = 0 ; $i < @list ; $i++ )
83    {
84        $result .= ", " if $i > 0;
85        $result .= "and " if $i == @list - 1 and @list > 1;
86        $result .= $list[$i];
87    }
88    $result;
89}
90
91sub makenice
92{
93    my ($char) = $_[0];
94    if ( ord($char) < 32 ) { $char = "^" . pack( "c", ord($char) + 64 ) }
95    elsif ( ord($char) > 126 ) { $char = ord($char) }
96    $char;
97}
98
99sub makeunnice
100{
101    my ($char) = $_[0];
102    $char =~ s/^\^(.)$/pack("c",ord($1)-64)/eg;
103    $char =~ s/(\d{1,3})/pack("c",$1+0)/eg;
104    $char;
105}
106
107my $response;
108
109eval {
110
111    if ( &Term::ReadKey::termoptions() == 1 )
112    {
113        $response =
114          "Term::ReadKey is using TERMIOS, as opposed to TERMIO or SGTTY.\n";
115    }
116    elsif ( &Term::ReadKey::termoptions() == 2 )
117    {
118        $response =
119          "Term::ReadKey is using TERMIO, as opposed to TERMIOS or SGTTY.\n";
120    }
121    elsif ( &Term::ReadKey::termoptions() == 3 )
122    {
123        $response =
124          "Term::ReadKey is using SGTTY, as opposed to TERMIOS or TERMIO.\n";
125    }
126    elsif ( &Term::ReadKey::termoptions() == 4 )
127    {
128        $response =
129"Term::ReadKey is trying to make do with stty; facilites may be limited.\n";
130    }
131    elsif ( &Term::ReadKey::termoptions() == 5 )
132    {
133        $response = "Term::ReadKey is using Win32 functions.\n";
134    }
135    else
136    {
137        $response =
138          "Term::ReadKey could not find any way to manipulate the terminal.\n";
139    }
140
141    print "ok 3\n";
142};
143
144print "not ok 3\n" if $@;
145
146print $response if $interactive;
147
148eval {
149    push( @modes, "O_NODELAY" ) if &Term::ReadKey::blockoptions() & 1;
150    push( @modes, "poll()" )    if &Term::ReadKey::blockoptions() & 2;
151    push( @modes, "select()" )  if &Term::ReadKey::blockoptions() & 4;
152    push( @modes, "Win32" )     if &Term::ReadKey::blockoptions() & 8;
153
154    print "ok 4\n";
155};
156
157print "not ok 4\n" if $@;
158
159if ($interactive)
160{
161    if ( &Term::ReadKey::blockoptions() == 0 )
162    {
163        print "No methods found to implement non-blocking reads.\n";
164        print
165" (If your computer supports poll(), you might like to read through ReadKey.xs)\n";
166    }
167    else
168    {
169        print "Non-blocking reads possible via ", makenicelist(@modes), ".\n";
170        print $modes[0] . " will be used. " if @modes > 0;
171        print $modes[1] . " will be used for timed reads."
172          if @modes > 1
173          and $modes[0] eq "O_NODELAY";
174        print "\n";
175    }
176}
177
178eval {
179    @size = GetTerminalSize(OUT);
180    print "ok 5\n";
181};
182
183print "not ok 5\n" if $@;
184
185if ($interactive)
186{
187    if ( !@size )
188    {
189        print
190          "GetTerminalSize was incapable of finding the size of your terminal.";
191    }
192    else
193    {
194        print "Using GetTerminalSize, it appears that your terminal is\n";
195        print "$size[0] characters wide by $size[1] high.\n\n";
196    }
197
198}
199
200eval {
201    @speeds = GetSpeed();
202    print "ok 6\n";
203};
204
205print "not ok 6\n" if $@;
206
207if ($interactive)
208{
209    if (@speeds)
210    {
211        print "Apparently, you are connected at ", join( "/", @speeds ),
212          " baud.\n";
213    }
214    else
215    {
216        print "GetSpeed couldn't tell your connection baud rate.\n\n";
217    }
218    print "\n";
219}
220
221eval {
222    %chars = GetControlChars(IN);
223    print "ok 7\n";
224};
225
226print "not ok 7\n" if $@;
227
228%origchars = %chars;
229
230if ($interactive)
231{
232    for $c ( keys %chars ) { $chars{$c} = makenice( $chars{$c} ) }
233
234    print "Control chars = (",
235      join( ', ', map( "$_ => $chars{$_}", keys %chars ) ), ")\n";
236}
237
238eval {
239    SetControlChars( %origchars, IN );
240    print "ok 8\n";
241};
242
243print "not ok 8\n" if $@;
244
245#SetControlChars("FOOFOO"=>"Q");
246#SetControlChars("INTERRUPT"=>"\x5");
247
248END { ReadMode 0, IN; }    # Just if something goes weird
249
250exit(0) unless $interactive;
251
252print "\nAnd now for the interactive tests.\n";
253
254print
255  "\nThis is ReadMode 1. It's guarranteed to give you cooked input. All the\n";
256print "signals and editing characters may be used as usual.\n";
257
258ReadMode 1, IN;
259
260print "\nYou may enter some text here: ";
261
262$t = ReadLine 0, IN;
263
264chop $t;
265
266print "\nYou entered `$t'.\n";
267
268ReadMode 2, IN;
269
270print
271  "\nThis is ReadMode 2. It's just like #1, but echo is turned off. Great\n";
272print "for passwords.\n";
273
274print "\nYou may enter some invisible text here: ";
275
276$t = ReadLine 0, IN;
277
278chop $t;
279
280print "\nYou entered `$t'.\n";
281
282ReadMode 3, IN;
283
284print
285  "\nI won't demonstrate ReadMode 3 here. It's your standard cbreak mode,\n";
286print
287  "with editing characters disabled, single character at a time input, but\n";
288print "with the control characters still enabled.\n";
289
290print "\n";
291
292print
293"I'm now putting the terminal into ReadMode 4 and using non-blocking reads.\n";
294print
295  "All signals should be disabled, including xon-xoff. You should only be\n";
296print "able to exit this loop via 'q'.\n";
297
298ReadMode 4, IN;
299$k = "";
300
301#$in = *STDIN;
302$in = \*IN;    # or *IN or "IN"
303while ( $k ne "q" )
304{
305    print "Press a key, or \"q\" to stop: ";
306    $count = 0;
307
308    #print "IN = $in\n";
309    $count++ while !defined( $k = ReadKey( -1, $in ) );
310
311    #print "IN2 = $in\n";
312    print "\nYou pressed `", makenice($k),
313      "' after the loop rolled over $count times\n";
314}
315ReadMode 0, IN;
316
317print "\nHere is a similar loop which times out after two seconds:\n";
318
319ReadMode 4, IN;
320$k = "";
321
322#$in = *STDIN;
323$in = \*IN;    # or *IN or "IN"
324while ( $k ne "q" )
325{
326    print "Press a key, or \"q\" to stop: ";
327    $count = 0;
328
329    #print "IN = $in\n";
330    print "Timeout! " while !defined( $k = ReadKey( 2, $in ) );
331
332    #print "IN2 = $in\n";
333    print "\nYou pressed `", makenice($k), "'\n";
334}
335
336print
337  "\nLastly, ReadMode 5, which also affects output (except under Win32).\n\n";
338
339ReadMode 5, IN;
340
341print
342"This should be a diagonal line (except under Win32): *\n*\n*\n\*\n*\n*\r\n\r\n";
343print "And this should be a moving spot:\r\n\r\n";
344
345$width = ( GetTerminalSize(OUT) )[0];
346$width /= 2;
347$width--;
348if ( $width < 10 ) { $width = 10; }
349
350for ( $i = 0 ; $i < 20 ; $i += .15 )
351{
352    print "\r";
353    print( " " x ( ( cos($i) + 1 ) * $width ) );
354    print "*";
355    select( undef, undef, undef, 0.01 );
356    print "\r";
357    print( " " x ( ( cos($i) + 1 ) * $width ) );
358    print " ";
359}
360print "\r                                           ";
361
362print "\n\r\n";
363
364ReadMode 0, IN;
365
366print "That's all, folks!\n";
367
368