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