1*99fd0875Safresh1#! perl 2*99fd0875Safresh1 3*99fd0875Safresh1package Term::ReadKey; 4*99fd0875Safresh1 5*99fd0875Safresh1# This also needs to be adjusted in the generated code below 6*99fd0875Safresh1# and in the Makefile.PL 7*99fd0875Safresh1use vars qw($VERSION); 8*99fd0875Safresh1 9*99fd0875Safresh1$VERSION = '2.38'; 10*99fd0875Safresh1 11*99fd0875Safresh1use Config; 12*99fd0875Safresh1use File::Basename qw(&basename &dirname); 13*99fd0875Safresh1use File::Spec; 14*99fd0875Safresh1use Cwd; 15*99fd0875Safresh1 16*99fd0875Safresh1# List explicitly here the variables you want Configure to 17*99fd0875Safresh1# generate. Metaconfig only looks for shell variables, so you 18*99fd0875Safresh1# have to mention them as if they were shell variables, not 19*99fd0875Safresh1# %Config entries. Thus you write 20*99fd0875Safresh1# $startperl 21*99fd0875Safresh1# to ensure Configure will look for $Config{startperl}. 22*99fd0875Safresh1# Wanted: $archlibexp 23*99fd0875Safresh1 24*99fd0875Safresh1# This forces PL files to create target in same directory as PL file. 25*99fd0875Safresh1# This is so that make depend always knows where to find PL derivatives. 26*99fd0875Safresh1my $origdir = cwd; 27*99fd0875Safresh1my $dir = dirname($0); 28*99fd0875Safresh1chdir $dir; 29*99fd0875Safresh1my $file = 'ReadKey.pm'; 30*99fd0875Safresh1 31*99fd0875Safresh1open OUT, ">", $file or die "Can't create $file: $!"; 32*99fd0875Safresh1 33*99fd0875Safresh1print "Creating $file\n"; 34*99fd0875Safresh1 35*99fd0875Safresh1print OUT <<'!FIRSTPART'; 36*99fd0875Safresh1# -*- buffer-read-only: t -*- 37*99fd0875Safresh1# 38*99fd0875Safresh1# This file is auto-generated. ***ANY*** changes here will be lost 39*99fd0875Safresh1# 40*99fd0875Safresh1package Term::ReadKey; 41*99fd0875Safresh1 42*99fd0875Safresh1use strict; 43*99fd0875Safresh1use warnings; 44*99fd0875Safresh1 45*99fd0875Safresh1=head1 NAME 46*99fd0875Safresh1 47*99fd0875Safresh1Term::ReadKey - A perl module for simple terminal control 48*99fd0875Safresh1 49*99fd0875Safresh1=head1 SYNOPSIS 50*99fd0875Safresh1 51*99fd0875Safresh1 use Term::ReadKey; 52*99fd0875Safresh1 ReadMode 4; # Turn off controls keys 53*99fd0875Safresh1 while (not defined ($key = ReadKey(-1))) { 54*99fd0875Safresh1 # No key yet 55*99fd0875Safresh1 } 56*99fd0875Safresh1 print "Get key $key\n"; 57*99fd0875Safresh1 ReadMode 0; # Reset tty mode before exiting 58*99fd0875Safresh1 59*99fd0875Safresh1=head1 DESCRIPTION 60*99fd0875Safresh1 61*99fd0875Safresh1Term::ReadKey is a compiled perl module dedicated to providing simple 62*99fd0875Safresh1control over terminal driver modes (cbreak, raw, cooked, etc.,) support for 63*99fd0875Safresh1non-blocking reads, if the architecture allows, and some generalized handy 64*99fd0875Safresh1functions for working with terminals. One of the main goals is to have the 65*99fd0875Safresh1functions as portable as possible, so you can just plug in "use 66*99fd0875Safresh1Term::ReadKey" on any architecture and have a good likelihood of it working. 67*99fd0875Safresh1 68*99fd0875Safresh1Version 2.30.01: 69*99fd0875Safresh1Added handling of arrows, page up/down, home/end, insert/delete keys 70*99fd0875Safresh1under Win32. These keys emit xterm-compatible sequences. 71*99fd0875Safresh1Works with Term::ReadLine::Perl. 72*99fd0875Safresh1 73*99fd0875Safresh1=over 4 74*99fd0875Safresh1 75*99fd0875Safresh1=item ReadMode MODE [, Filehandle] 76*99fd0875Safresh1 77*99fd0875Safresh1Takes an integer argument or a string synonym (case insensitive), which 78*99fd0875Safresh1can currently be one of the following values: 79*99fd0875Safresh1 80*99fd0875Safresh1 INT SYNONYM DESCRIPTION 81*99fd0875Safresh1 82*99fd0875Safresh1 0 'restore' Restore original settings. 83*99fd0875Safresh1 84*99fd0875Safresh1 1 'normal' Change to what is commonly the default mode, 85*99fd0875Safresh1 echo on, buffered, signals enabled, Xon/Xoff 86*99fd0875Safresh1 possibly enabled, and 8-bit mode possibly disabled. 87*99fd0875Safresh1 88*99fd0875Safresh1 2 'noecho' Same as 1, just with echo off. Nice for 89*99fd0875Safresh1 reading passwords. 90*99fd0875Safresh1 91*99fd0875Safresh1 3 'cbreak' Echo off, unbuffered, signals enabled, Xon/Xoff 92*99fd0875Safresh1 possibly enabled, and 8-bit mode possibly enabled. 93*99fd0875Safresh1 94*99fd0875Safresh1 4 'raw' Echo off, unbuffered, signals disabled, Xon/Xoff 95*99fd0875Safresh1 disabled, and 8-bit mode possibly disabled. 96*99fd0875Safresh1 97*99fd0875Safresh1 5 'ultra-raw' Echo off, unbuffered, signals disabled, Xon/Xoff 98*99fd0875Safresh1 disabled, 8-bit mode enabled if parity permits, 99*99fd0875Safresh1 and CR to CR/LF translation turned off. 100*99fd0875Safresh1 101*99fd0875Safresh1 102*99fd0875Safresh1These functions are automatically applied to the STDIN handle if no 103*99fd0875Safresh1other handle is supplied. Modes 0 and 5 have some special properties 104*99fd0875Safresh1worth mentioning: not only will mode 0 restore original settings, but it 105*99fd0875Safresh1cause the next ReadMode call to save a new set of default settings. Mode 106*99fd0875Safresh15 is similar to mode 4, except no CR/LF translation is performed, and if 107*99fd0875Safresh1possible, parity will be disabled (only if not being used by the terminal, 108*99fd0875Safresh1however. It is no different from mode 4 under Windows.) 109*99fd0875Safresh1 110*99fd0875Safresh1If you just need to read a key at a time, then modes 3 or 4 are probably 111*99fd0875Safresh1sufficient. Mode 4 is a tad more flexible, but needs a bit more work to 112*99fd0875Safresh1control. If you use ReadMode 3, then you should install a SIGINT or END 113*99fd0875Safresh1handler to reset the terminal (via ReadMode 0) if the user aborts the 114*99fd0875Safresh1program via C<^C>. (For any mode, an END handler consisting of "ReadMode 0" 115*99fd0875Safresh1is actually a good idea.) 116*99fd0875Safresh1 117*99fd0875Safresh1If you are executing another program that may be changing the terminal mode, 118*99fd0875Safresh1you will either want to say 119*99fd0875Safresh1 120*99fd0875Safresh1 ReadMode 1; # same as ReadMode 'normal' 121*99fd0875Safresh1 system('someprogram'); 122*99fd0875Safresh1 ReadMode 1; 123*99fd0875Safresh1 124*99fd0875Safresh1which resets the settings after the program has run, or: 125*99fd0875Safresh1 126*99fd0875Safresh1 $somemode=1; 127*99fd0875Safresh1 ReadMode 0; # same as ReadMode 'restore' 128*99fd0875Safresh1 system('someprogram'); 129*99fd0875Safresh1 ReadMode 1; 130*99fd0875Safresh1 131*99fd0875Safresh1which records any changes the program may have made, before resetting the 132*99fd0875Safresh1mode. 133*99fd0875Safresh1 134*99fd0875Safresh1=item ReadKey MODE [, Filehandle] 135*99fd0875Safresh1 136*99fd0875Safresh1Takes an integer argument, which can currently be one of the following 137*99fd0875Safresh1values: 138*99fd0875Safresh1 139*99fd0875Safresh1 0 Perform a normal read using getc 140*99fd0875Safresh1 -1 Perform a non-blocked read 141*99fd0875Safresh1 >0 Perform a timed read 142*99fd0875Safresh1 143*99fd0875Safresh1If the filehandle is not supplied, it will default to STDIN. If there is 144*99fd0875Safresh1nothing waiting in the buffer during a non-blocked read, then undef will be 145*99fd0875Safresh1returned. In most situations, you will probably want to use C<ReadKey -1>. 146*99fd0875Safresh1 147*99fd0875Safresh1I<NOTE> that if the OS does not provide any known mechanism for non-blocking 148*99fd0875Safresh1reads, then a C<ReadKey -1> can die with a fatal error. This will hopefully 149*99fd0875Safresh1not be common. 150*99fd0875Safresh1 151*99fd0875Safresh1If MODE is greater then zero, then ReadKey will use it as a timeout value in 152*99fd0875Safresh1seconds (fractional seconds are allowed), and won't return C<undef> until 153*99fd0875Safresh1that time expires. 154*99fd0875Safresh1 155*99fd0875Safresh1I<NOTE>, again, that some OS's may not support this timeout behaviour. 156*99fd0875Safresh1 157*99fd0875Safresh1If MODE is less then zero, then this is treated as a timeout 158*99fd0875Safresh1of zero, and thus will return immediately if no character is waiting. A MODE 159*99fd0875Safresh1of zero, however, will act like a normal getc. 160*99fd0875Safresh1 161*99fd0875Safresh1I<NOTE>, there are currently some limitations with this call under Windows. 162*99fd0875Safresh1It may be possible that non-blocking reads will fail when reading repeating 163*99fd0875Safresh1keys from more then one console. 164*99fd0875Safresh1 165*99fd0875Safresh1 166*99fd0875Safresh1=item ReadLine MODE [, Filehandle] 167*99fd0875Safresh1 168*99fd0875Safresh1Takes an integer argument, which can currently be one of the following 169*99fd0875Safresh1values: 170*99fd0875Safresh1 171*99fd0875Safresh1 0 Perform a normal read using scalar(<FileHandle>) 172*99fd0875Safresh1 -1 Perform a non-blocked read 173*99fd0875Safresh1 >0 Perform a timed read 174*99fd0875Safresh1 175*99fd0875Safresh1If there is nothing waiting in the buffer during a non-blocked read, then 176*99fd0875Safresh1undef will be returned. 177*99fd0875Safresh1 178*99fd0875Safresh1I<NOTE>, that if the OS does not provide any known mechanism for 179*99fd0875Safresh1non-blocking reads, then a C<ReadLine 1> can die with a fatal 180*99fd0875Safresh1error. This will hopefully not be common. 181*99fd0875Safresh1 182*99fd0875Safresh1I<NOTE> that a non-blocking test is only performed for the first character 183*99fd0875Safresh1in the line, not the entire line. This call will probably B<not> do what 184*99fd0875Safresh1you assume, especially with C<ReadMode> MODE values higher then 1. For 185*99fd0875Safresh1example, pressing Space and then Backspace would appear to leave you 186*99fd0875Safresh1where you started, but any timeouts would now be suspended. 187*99fd0875Safresh1 188*99fd0875Safresh1B<This call is currently not available under Windows>. 189*99fd0875Safresh1 190*99fd0875Safresh1=item GetTerminalSize [Filehandle] 191*99fd0875Safresh1 192*99fd0875Safresh1Returns either an empty array if this operation is unsupported, or a four 193*99fd0875Safresh1element array containing: the width of the terminal in characters, the 194*99fd0875Safresh1height of the terminal in character, the width in pixels, and the height in 195*99fd0875Safresh1pixels. (The pixel size will only be valid in some environments.) 196*99fd0875Safresh1 197*99fd0875Safresh1I<NOTE>, under Windows, this function must be called with an B<output> 198*99fd0875Safresh1filehandle, such as C<STDOUT>, or a handle opened to C<CONOUT$>. 199*99fd0875Safresh1 200*99fd0875Safresh1=item SetTerminalSize WIDTH,HEIGHT,XPIX,YPIX [, Filehandle] 201*99fd0875Safresh1 202*99fd0875Safresh1Return -1 on failure, 0 otherwise. 203*99fd0875Safresh1 204*99fd0875Safresh1I<NOTE> that this terminal size is only for B<informative> value, and 205*99fd0875Safresh1changing the size via this mechanism will B<not> change the size of 206*99fd0875Safresh1the screen. For example, XTerm uses a call like this when 207*99fd0875Safresh1it resizes the screen. If any of the new measurements vary from the old, the 208*99fd0875Safresh1OS will probably send a SIGWINCH signal to anything reading that tty or pty. 209*99fd0875Safresh1 210*99fd0875Safresh1B<This call does not work under Windows>. 211*99fd0875Safresh1 212*99fd0875Safresh1=item GetSpeed [, Filehandle] 213*99fd0875Safresh1 214*99fd0875Safresh1Returns either an empty array if the operation is unsupported, or a two 215*99fd0875Safresh1value array containing the terminal in and out speeds, in B<decimal>. E.g, 216*99fd0875Safresh1an in speed of 9600 baud and an out speed of 4800 baud would be returned as 217*99fd0875Safresh1(9600,4800). Note that currently the in and out speeds will always be 218*99fd0875Safresh1identical in some OS's. 219*99fd0875Safresh1 220*99fd0875Safresh1B<No speeds are reported under Windows>. 221*99fd0875Safresh1 222*99fd0875Safresh1=item GetControlChars [, Filehandle] 223*99fd0875Safresh1 224*99fd0875Safresh1Returns an array containing key/value pairs suitable for a hash. The pairs 225*99fd0875Safresh1consist of a key, the name of the control character/signal, and the value 226*99fd0875Safresh1of that character, as a single character. 227*99fd0875Safresh1 228*99fd0875Safresh1B<This call does nothing under Windows>. 229*99fd0875Safresh1 230*99fd0875Safresh1Each key will be an entry from the following list: 231*99fd0875Safresh1 232*99fd0875Safresh1 DISCARD 233*99fd0875Safresh1 DSUSPEND 234*99fd0875Safresh1 EOF 235*99fd0875Safresh1 EOL 236*99fd0875Safresh1 EOL2 237*99fd0875Safresh1 ERASE 238*99fd0875Safresh1 ERASEWORD 239*99fd0875Safresh1 INTERRUPT 240*99fd0875Safresh1 KILL 241*99fd0875Safresh1 MIN 242*99fd0875Safresh1 QUIT 243*99fd0875Safresh1 QUOTENEXT 244*99fd0875Safresh1 REPRINT 245*99fd0875Safresh1 START 246*99fd0875Safresh1 STATUS 247*99fd0875Safresh1 STOP 248*99fd0875Safresh1 SUSPEND 249*99fd0875Safresh1 SWITCH 250*99fd0875Safresh1 TIME 251*99fd0875Safresh1 252*99fd0875Safresh1Thus, the following will always return the current interrupt character, 253*99fd0875Safresh1regardless of platform. 254*99fd0875Safresh1 255*99fd0875Safresh1 %keys = GetControlChars; 256*99fd0875Safresh1 $int = $keys{INTERRUPT}; 257*99fd0875Safresh1 258*99fd0875Safresh1=item SetControlChars [, Filehandle] 259*99fd0875Safresh1 260*99fd0875Safresh1Takes an array containing key/value pairs, as a hash will produce. The pairs 261*99fd0875Safresh1should consist of a key that is the name of a legal control 262*99fd0875Safresh1character/signal, and the value should be either a single character, or a 263*99fd0875Safresh1number in the range 0-255. SetControlChars will die with a runtime error if 264*99fd0875Safresh1an invalid character name is passed or there is an error changing the 265*99fd0875Safresh1settings. The list of valid names is easily available via 266*99fd0875Safresh1 267*99fd0875Safresh1 %cchars = GetControlChars(); 268*99fd0875Safresh1 @cnames = keys %cchars; 269*99fd0875Safresh1 270*99fd0875Safresh1B<This call does nothing under Windows>. 271*99fd0875Safresh1 272*99fd0875Safresh1=back 273*99fd0875Safresh1 274*99fd0875Safresh1=head1 AUTHOR 275*99fd0875Safresh1 276*99fd0875Safresh1Kenneth Albanowski <kjahds@kjahds.com> 277*99fd0875Safresh1 278*99fd0875Safresh1Currently maintained by Jonathan Stowe <jns@gellyfish.co.uk> 279*99fd0875Safresh1 280*99fd0875Safresh1=head1 SUPPORT 281*99fd0875Safresh1 282*99fd0875Safresh1The code is maintained at 283*99fd0875Safresh1 284*99fd0875Safresh1 https://github.com/jonathanstowe/TermReadKey 285*99fd0875Safresh1 286*99fd0875Safresh1Please feel free to fork and suggest patches. 287*99fd0875Safresh1 288*99fd0875Safresh1 289*99fd0875Safresh1=head1 LICENSE 290*99fd0875Safresh1 291*99fd0875Safresh1Prior to the 2.31 release the license statement was: 292*99fd0875Safresh1 293*99fd0875Safresh1 Copyright (C) 1994-1999 Kenneth Albanowski. 294*99fd0875Safresh1 2001-2005 Jonathan Stowe and others 295*99fd0875Safresh1 296*99fd0875Safresh1 Unlimited distribution and/or modification is allowed as long as this 297*99fd0875Safresh1 copyright notice remains intact. 298*99fd0875Safresh1 299*99fd0875Safresh1And was only stated in the README file. 300*99fd0875Safresh1 301*99fd0875Safresh1Because I believe the original author's intent was to be more open than the 302*99fd0875Safresh1other commonly used licenses I would like to leave that in place. However if 303*99fd0875Safresh1you or your lawyers require something with some more words you can optionally 304*99fd0875Safresh1choose to license this under the standard Perl license: 305*99fd0875Safresh1 306*99fd0875Safresh1 This module is free software; you can redistribute it and/or modify it 307*99fd0875Safresh1 under the terms of the Artistic License. For details, see the full 308*99fd0875Safresh1 text of the license in the file "Artistic" that should have been provided 309*99fd0875Safresh1 with the version of perl you are using. 310*99fd0875Safresh1 311*99fd0875Safresh1 This program is distributed in the hope that it will be useful, but 312*99fd0875Safresh1 without any warranty; without even the implied warranty of merchantability 313*99fd0875Safresh1 or fitness for a particular purpose. 314*99fd0875Safresh1 315*99fd0875Safresh1 316*99fd0875Safresh1=cut 317*99fd0875Safresh1 318*99fd0875Safresh1use vars qw($VERSION); 319*99fd0875Safresh1 320*99fd0875Safresh1$VERSION = '2.38'; 321*99fd0875Safresh1 322*99fd0875Safresh1require Exporter; 323*99fd0875Safresh1require DynaLoader; 324*99fd0875Safresh1 325*99fd0875Safresh1use vars qw(@ISA @EXPORT_OK @EXPORT); 326*99fd0875Safresh1 327*99fd0875Safresh1@ISA = qw(Exporter DynaLoader); 328*99fd0875Safresh1 329*99fd0875Safresh1# Items to export into callers namespace by default 330*99fd0875Safresh1# (move infrequently used names to @EXPORT_OK below) 331*99fd0875Safresh1 332*99fd0875Safresh1@EXPORT = qw( 333*99fd0875Safresh1 ReadKey 334*99fd0875Safresh1 ReadMode 335*99fd0875Safresh1 ReadLine 336*99fd0875Safresh1 GetTerminalSize 337*99fd0875Safresh1 SetTerminalSize 338*99fd0875Safresh1 GetSpeed 339*99fd0875Safresh1 GetControlChars 340*99fd0875Safresh1 SetControlChars 341*99fd0875Safresh1); 342*99fd0875Safresh1 343*99fd0875Safresh1@EXPORT_OK = qw(); 344*99fd0875Safresh1 345*99fd0875Safresh1bootstrap Term::ReadKey; 346*99fd0875Safresh1 347*99fd0875Safresh1# Should we use LINES and COLUMNS to try and get the terminal size? 348*99fd0875Safresh1# Change this to zero if you have systems where these are commonly 349*99fd0875Safresh1# set to erroneous values. (But if either are near zero, they won't be 350*99fd0875Safresh1# used anyhow.) 351*99fd0875Safresh1 352*99fd0875Safresh1use vars qw($UseEnv $CurrentMode %modes); 353*99fd0875Safresh1 354*99fd0875Safresh1$UseEnv = 1; 355*99fd0875Safresh1 356*99fd0875Safresh1$CurrentMode = 0; 357*99fd0875Safresh1 358*99fd0875Safresh1%modes = ( # lowercase is canonical 359*99fd0875Safresh1 original => 0, 360*99fd0875Safresh1 restore => 0, 361*99fd0875Safresh1 normal => 1, 362*99fd0875Safresh1 noecho => 2, 363*99fd0875Safresh1 cbreak => 3, 364*99fd0875Safresh1 raw => 4, 365*99fd0875Safresh1 'ultra-raw' => 5 366*99fd0875Safresh1); 367*99fd0875Safresh1 368*99fd0875Safresh1# reduce Carp memory footprint, only load when needed 369*99fd0875Safresh1sub croak { require Carp; goto &Carp::croak; } 370*99fd0875Safresh1sub carp { require Carp; goto &Carp::carp; } 371*99fd0875Safresh1 372*99fd0875Safresh1sub ReadMode 373*99fd0875Safresh1{ 374*99fd0875Safresh1 my $mode = $modes{ lc $_[0] }; # lowercase is canonical 375*99fd0875Safresh1 my $fh = normalizehandle( ( @_ > 1 ? $_[1] : \*STDIN ) ); 376*99fd0875Safresh1 377*99fd0875Safresh1 if ( defined($mode) ) { $CurrentMode = $mode } 378*99fd0875Safresh1 elsif ( $_[0] =~ /^\d/ ) { $CurrentMode = $_[0] } 379*99fd0875Safresh1 else { croak("Unknown terminal mode `$_[0]'"); } 380*99fd0875Safresh1 381*99fd0875Safresh1 SetReadMode($CurrentMode, $fh); 382*99fd0875Safresh1} 383*99fd0875Safresh1 384*99fd0875Safresh1sub normalizehandle 385*99fd0875Safresh1{ 386*99fd0875Safresh1 my ($file) = @_; # allows fake signature optimization 387*99fd0875Safresh1 388*99fd0875Safresh1 no strict; 389*99fd0875Safresh1 # print "Handle = $file\n"; 390*99fd0875Safresh1 if ( ref($file) ) { return $file; } # Reference is fine 391*99fd0875Safresh1 392*99fd0875Safresh1 # if ($file =~ /^\*/) { return $file; } # Type glob is good 393*99fd0875Safresh1 if ( ref( \$file ) eq 'GLOB' ) { return $file; } # Glob is good 394*99fd0875Safresh1 395*99fd0875Safresh1 # print "Caller = ",(caller(1))[0],"\n"; 396*99fd0875Safresh1 return \*{ ( ( caller(1) )[0] ) . "::$file" }; 397*99fd0875Safresh1} 398*99fd0875Safresh1 399*99fd0875Safresh1sub GetTerminalSize 400*99fd0875Safresh1{ 401*99fd0875Safresh1 my $file = normalizehandle( ( @_ > 0 ? $_[0] : \*STDOUT ) ); 402*99fd0875Safresh1 403*99fd0875Safresh1 my (@results, @fail); 404*99fd0875Safresh1 405*99fd0875Safresh1 if ( &termsizeoptions() & 1 ) # VIO 406*99fd0875Safresh1 { 407*99fd0875Safresh1 @results = GetTermSizeVIO($file); 408*99fd0875Safresh1 push( @fail, "VIOGetMode call" ); 409*99fd0875Safresh1 } 410*99fd0875Safresh1 elsif ( &termsizeoptions() & 2 ) # GWINSZ 411*99fd0875Safresh1 { 412*99fd0875Safresh1 @results = GetTermSizeGWINSZ($file); 413*99fd0875Safresh1 push( @fail, "TIOCGWINSZ ioctl" ); 414*99fd0875Safresh1 } 415*99fd0875Safresh1 elsif ( &termsizeoptions() & 4 ) # GSIZE 416*99fd0875Safresh1 { 417*99fd0875Safresh1 @results = GetTermSizeGSIZE($file); 418*99fd0875Safresh1 push( @fail, "TIOCGSIZE ioctl" ); 419*99fd0875Safresh1 } 420*99fd0875Safresh1 elsif ( &termsizeoptions() & 8 ) # WIN32 421*99fd0875Safresh1 { 422*99fd0875Safresh1 @results = GetTermSizeWin32($file); 423*99fd0875Safresh1 push( @fail, "Win32 GetConsoleScreenBufferInfo call" ); 424*99fd0875Safresh1 } 425*99fd0875Safresh1 else 426*99fd0875Safresh1 { 427*99fd0875Safresh1 @results = (); 428*99fd0875Safresh1 } 429*99fd0875Safresh1 430*99fd0875Safresh1 if ( @results < 4 and $UseEnv ) 431*99fd0875Safresh1 { 432*99fd0875Safresh1 my ($C) = defined( $ENV{COLUMNS} ) ? $ENV{COLUMNS} : 0; 433*99fd0875Safresh1 my ($L) = defined( $ENV{LINES} ) ? $ENV{LINES} : 0; 434*99fd0875Safresh1 if ( ( $C >= 2 ) and ( $L >= 2 ) ) 435*99fd0875Safresh1 { 436*99fd0875Safresh1 @results = ( $C + 0, $L + 0, 0, 0 ); 437*99fd0875Safresh1 } 438*99fd0875Safresh1 push( @fail, "COLUMNS and LINES environment variables" ); 439*99fd0875Safresh1 } 440*99fd0875Safresh1 441*99fd0875Safresh1 if ( @results < 4 && $^O ne 'MSWin32') 442*99fd0875Safresh1 { 443*99fd0875Safresh1 my ($prog) = "resize"; 444*99fd0875Safresh1 445*99fd0875Safresh1 # Workaround for Solaris path silliness 446*99fd0875Safresh1 if ( -f "/usr/openwin/bin/resize" ) { 447*99fd0875Safresh1 $prog = "/usr/openwin/bin/resize"; 448*99fd0875Safresh1 } 449*99fd0875Safresh1 450*99fd0875Safresh1 my ($resize) = scalar(`$prog 2>/dev/null`); 451*99fd0875Safresh1 if (defined $resize 452*99fd0875Safresh1 and ( $resize =~ /COLUMNS\s*=\s*(\d+)/ 453*99fd0875Safresh1 or $resize =~ /setenv\s+COLUMNS\s+'?(\d+)/ ) 454*99fd0875Safresh1 ) 455*99fd0875Safresh1 { 456*99fd0875Safresh1 $results[0] = $1; 457*99fd0875Safresh1 if ( $resize =~ /LINES\s*=\s*(\d+)/ 458*99fd0875Safresh1 or $resize =~ /setenv\s+LINES\s+'?(\d+)/ ) 459*99fd0875Safresh1 { 460*99fd0875Safresh1 $results[1] = $1; 461*99fd0875Safresh1 @results[ 2, 3 ] = ( 0, 0 ); 462*99fd0875Safresh1 } 463*99fd0875Safresh1 else 464*99fd0875Safresh1 { 465*99fd0875Safresh1 @results = (); 466*99fd0875Safresh1 } 467*99fd0875Safresh1 } 468*99fd0875Safresh1 else 469*99fd0875Safresh1 { 470*99fd0875Safresh1 @results = (); 471*99fd0875Safresh1 } 472*99fd0875Safresh1 push( @fail, "resize program" ); 473*99fd0875Safresh1 } 474*99fd0875Safresh1 475*99fd0875Safresh1 if ( @results < 4 && $^O ne 'MSWin32' ) 476*99fd0875Safresh1 { 477*99fd0875Safresh1 my ($prog) = "stty size"; 478*99fd0875Safresh1 479*99fd0875Safresh1 my ($stty) = scalar(`$prog 2>/dev/null`); 480*99fd0875Safresh1 if (defined $stty 481*99fd0875Safresh1 and ( $stty =~ /(\d+) (\d+)/ ) 482*99fd0875Safresh1 ) 483*99fd0875Safresh1 { 484*99fd0875Safresh1 $results[0] = $2; 485*99fd0875Safresh1 $results[1] = $1; 486*99fd0875Safresh1 @results[ 2, 3 ] = ( 0, 0 ); 487*99fd0875Safresh1 } 488*99fd0875Safresh1 else 489*99fd0875Safresh1 { 490*99fd0875Safresh1 @results = (); 491*99fd0875Safresh1 } 492*99fd0875Safresh1 push( @fail, "stty program" ); 493*99fd0875Safresh1 } 494*99fd0875Safresh1 495*99fd0875Safresh1 if ( @results != 4 ) 496*99fd0875Safresh1 { 497*99fd0875Safresh1 carp("Unable to get Terminal Size." 498*99fd0875Safresh1 . join( "", map( " The $_ didn't work.", @fail ) )); 499*99fd0875Safresh1 return undef; 500*99fd0875Safresh1 } 501*99fd0875Safresh1 502*99fd0875Safresh1 @results; 503*99fd0875Safresh1} 504*99fd0875Safresh1 505*99fd0875Safresh1!FIRSTPART 506*99fd0875Safresh1 507*99fd0875Safresh1close OUT; 508*99fd0875Safresh1# preload the XS module needed for the blockoptions() expansions below 509*99fd0875Safresh1# does not work with miniperl 510*99fd0875Safresh1package Term::ReadKey; 511*99fd0875Safresh1require DynaLoader; 512*99fd0875Safresh1our @ISA = qw(DynaLoader); 513*99fd0875Safresh1 514*99fd0875Safresh1print "Bootstrapping the XS for blockoptions: "; 515*99fd0875Safresh1bootstrap Term::ReadKey or die; 516*99fd0875Safresh1print blockoptions()."\n"; 517*99fd0875Safresh1 518*99fd0875Safresh1open OUT, ">>", $file or die "Can't append to $file: $!"; 519*99fd0875Safresh1print OUT "# blockoptions: \n"; 520*99fd0875Safresh1if ( &blockoptions() & 1 ) # Use nodelay 521*99fd0875Safresh1{ 522*99fd0875Safresh1 print OUT "#nodelay\n"; 523*99fd0875Safresh1 if ( &blockoptions() & 2 ) #poll 524*99fd0875Safresh1 { 525*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 526*99fd0875Safresh1# poll 527*99fd0875Safresh1sub ReadKey { 528*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 529*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 530*99fd0875Safresh1 if ($_[0]) { 531*99fd0875Safresh1 return undef if &pollfile($File,$_[0]) == 0; 532*99fd0875Safresh1 } 533*99fd0875Safresh1 } 534*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1); } 535*99fd0875Safresh1 my $value = getc $File; 536*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0); } 537*99fd0875Safresh1 $value; 538*99fd0875Safresh1} 539*99fd0875Safresh1sub ReadLine { 540*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 541*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 542*99fd0875Safresh1 if ($_[0]) { 543*99fd0875Safresh1 return undef if &pollfile($File,$_[0]) == 0; 544*99fd0875Safresh1 } 545*99fd0875Safresh1 } 546*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1) }; 547*99fd0875Safresh1 my $value = scalar(<$File>); 548*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0) }; 549*99fd0875Safresh1 $value; 550*99fd0875Safresh1} 551*99fd0875Safresh1!NO!SUBS! 552*99fd0875Safresh1 553*99fd0875Safresh1 } 554*99fd0875Safresh1 elsif ( &blockoptions() & 4 ) #select 555*99fd0875Safresh1 { 556*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 557*99fd0875Safresh1#select 558*99fd0875Safresh1sub ReadKey { 559*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 560*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 561*99fd0875Safresh1 if ($_[0]) { return undef if &selectfile($File,$_[0]) == 0 } 562*99fd0875Safresh1 } 563*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1); } 564*99fd0875Safresh1 my $value = getc $File; 565*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0); } 566*99fd0875Safresh1 $value; 567*99fd0875Safresh1} 568*99fd0875Safresh1sub ReadLine { 569*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 570*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 571*99fd0875Safresh1 if ($_[0]) { return undef if &selectfile($File,$_[0]) == 0 } 572*99fd0875Safresh1 } 573*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1) }; 574*99fd0875Safresh1 my $value = scalar(<$File>); 575*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0) }; 576*99fd0875Safresh1 $value; 577*99fd0875Safresh1} 578*99fd0875Safresh1!NO!SUBS! 579*99fd0875Safresh1 580*99fd0875Safresh1 } 581*99fd0875Safresh1 else 582*99fd0875Safresh1 { #nothing 583*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 584*99fd0875Safresh1sub ReadKey { 585*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 586*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 587*99fd0875Safresh1 # Nothing better seems to exist, so I just use time-of-day 588*99fd0875Safresh1 # to timeout the read. This isn't very exact, though. 589*99fd0875Safresh1 $starttime = time; 590*99fd0875Safresh1 $endtime = $starttime + $_[0]; 591*99fd0875Safresh1 &setnodelay($File,1); 592*99fd0875Safresh1 my $value; 593*99fd0875Safresh1 while (time < $endtime) { # This won't catch wraparound! 594*99fd0875Safresh1 $value = getc $File; 595*99fd0875Safresh1 last if defined($value); 596*99fd0875Safresh1 } 597*99fd0875Safresh1 &setnodelay($File,0); 598*99fd0875Safresh1 return $value; 599*99fd0875Safresh1 } 600*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1); } 601*99fd0875Safresh1 my $value = getc $File; 602*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0); } 603*99fd0875Safresh1 $value; 604*99fd0875Safresh1} 605*99fd0875Safresh1sub ReadLine { 606*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 607*99fd0875Safresh1 if (defined $_[0] && $_[0] > 0) { 608*99fd0875Safresh1 # Nothing better seems to exist, so I just use time-of-day 609*99fd0875Safresh1 # to timeout the read. This isn't very exact, though. 610*99fd0875Safresh1 $starttime = time; 611*99fd0875Safresh1 $endtime = $starttime + $_[0]; 612*99fd0875Safresh1 &setnodelay($File,1); 613*99fd0875Safresh1 my $value; 614*99fd0875Safresh1 while (time < $endtime) { # This won't catch wraparound! 615*99fd0875Safresh1 $value = scalar(<$File>); 616*99fd0875Safresh1 last if defined($value); 617*99fd0875Safresh1 } 618*99fd0875Safresh1 &setnodelay($File,0); 619*99fd0875Safresh1 return $value; 620*99fd0875Safresh1 } 621*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,1) }; 622*99fd0875Safresh1 my $value = scalar(<$File>); 623*99fd0875Safresh1 if (defined $_[0] && $_[0] < 0) { &setnodelay($File,0) }; 624*99fd0875Safresh1 $value; 625*99fd0875Safresh1} 626*99fd0875Safresh1!NO!SUBS! 627*99fd0875Safresh1 628*99fd0875Safresh1 } 629*99fd0875Safresh1} 630*99fd0875Safresh1else { 631*99fd0875Safresh1 print OUT "#no nodelay\n"; 632*99fd0875Safresh1 633*99fd0875Safresh1 if ( &blockoptions() & 2 ) # Use poll 634*99fd0875Safresh1 { 635*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 636*99fd0875Safresh1#poll 637*99fd0875Safresh1sub ReadKey { 638*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 639*99fd0875Safresh1 if (defined $_[0] && $_[0] != 0) { 640*99fd0875Safresh1 return undef if &pollfile($File,$_[0]) == 0 641*99fd0875Safresh1 } 642*99fd0875Safresh1 getc $File; 643*99fd0875Safresh1} 644*99fd0875Safresh1sub ReadLine { 645*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 646*99fd0875Safresh1 if (defined $_[0] && $_[0] != 0 ) { 647*99fd0875Safresh1 return undef if &pollfile($File,$_[0]) == 0; 648*99fd0875Safresh1 } 649*99fd0875Safresh1 scalar(<$File>); 650*99fd0875Safresh1} 651*99fd0875Safresh1!NO!SUBS! 652*99fd0875Safresh1 653*99fd0875Safresh1 } 654*99fd0875Safresh1 elsif ( &blockoptions() & 4 ) # Use select 655*99fd0875Safresh1 { 656*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 657*99fd0875Safresh1#select 658*99fd0875Safresh1sub ReadKey { 659*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 660*99fd0875Safresh1 if (defined $_[0] && $_[0] != 0) { 661*99fd0875Safresh1 return undef if &selectfile($File,$_[0]) == 0 662*99fd0875Safresh1 } 663*99fd0875Safresh1 getc $File; 664*99fd0875Safresh1} 665*99fd0875Safresh1sub ReadLine { 666*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 667*99fd0875Safresh1 if (defined $_[0] && $_[0] != 0) { 668*99fd0875Safresh1 return undef if &selectfile($File,$_[0]) == 0; 669*99fd0875Safresh1 } 670*99fd0875Safresh1 scalar(<$File>); 671*99fd0875Safresh1} 672*99fd0875Safresh1!NO!SUBS! 673*99fd0875Safresh1 674*99fd0875Safresh1 } 675*99fd0875Safresh1 elsif ( &blockoptions() & 8 ) # Use Win32 676*99fd0875Safresh1 { 677*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 678*99fd0875Safresh1#Win32 679*99fd0875Safresh1sub ReadKey { 680*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 681*99fd0875Safresh1 if ($_[0] || $CurrentMode >= 3) { 682*99fd0875Safresh1 Win32PeekChar($File, $_[0]); 683*99fd0875Safresh1 } else { 684*99fd0875Safresh1 getc $File; 685*99fd0875Safresh1 } 686*99fd0875Safresh1 #if ($_[0]!=0) {return undef if !Win32PeekChar($File, $_[0])}; 687*99fd0875Safresh1 #getc $File; 688*99fd0875Safresh1} 689*99fd0875Safresh1sub ReadLine { 690*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 691*99fd0875Safresh1 #if ($_[0]!=0) {return undef if !Win32PeekChar($File, $_[0])}; 692*99fd0875Safresh1 #scalar(<$File>); 693*99fd0875Safresh1 if ($_[0]) { 694*99fd0875Safresh1 croak("Non-blocking ReadLine is not supported on this architecture") 695*99fd0875Safresh1 } 696*99fd0875Safresh1 scalar(<$File>); 697*99fd0875Safresh1} 698*99fd0875Safresh1!NO!SUBS! 699*99fd0875Safresh1 700*99fd0875Safresh1 } 701*99fd0875Safresh1 else 702*99fd0875Safresh1 { 703*99fd0875Safresh1 print OUT <<'!NO!SUBS!'; 704*99fd0875Safresh1sub ReadKey { 705*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 706*99fd0875Safresh1 if ($_[0]) { 707*99fd0875Safresh1 croak("Non-blocking ReadKey is not supported on this architecture") 708*99fd0875Safresh1 } 709*99fd0875Safresh1 getc $File; 710*99fd0875Safresh1} 711*99fd0875Safresh1sub ReadLine { 712*99fd0875Safresh1 my $File = normalizehandle((@_>1?$_[1]:\*STDIN)); 713*99fd0875Safresh1 if ($_[0]) { 714*99fd0875Safresh1 croak("Non-blocking ReadLine is not supported on this architecture") 715*99fd0875Safresh1 } 716*99fd0875Safresh1 scalar(<$File>); 717*99fd0875Safresh1} 718*99fd0875Safresh1!NO!SUBS! 719*99fd0875Safresh1 720*99fd0875Safresh1 } 721*99fd0875Safresh1} 722*99fd0875Safresh1 723*99fd0875Safresh1print OUT <<'EOF'; 724*99fd0875Safresh11; 725*99fd0875Safresh1# ex: set ro: 726*99fd0875Safresh1EOF 727*99fd0875Safresh1 728*99fd0875Safresh1close OUT; 729*99fd0875Safresh1if (-s $file < 1000) { 730*99fd0875Safresh1 warn "WARNING: $file probably too small"; 731*99fd0875Safresh1} else { 732*99fd0875Safresh1 print "Done\n"; 733*99fd0875Safresh1} 734