lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n HotKey.pm 1 # HotKey.pm 2 package HotKey; 3 use strict; 4 5 our @ISA = qw(Exporter); 6 our @EXPORT = qw(cbreak cooked readkey); 7 8 use strict; 9 use POSIX qw(:termios_h); 10 my ($term, $oterm, $echo, $noecho, $fd_stdin); 11 12 $fd_stdin = fileno(STDIN); # fileno retorna el fd de STDIN 13 $term = POSIX::Termios->new(); 14 $term->getattr($fd_stdin); # Rellenamos los campos de $term 15 $oterm = $term->getlflag(); # Obtiene el campo c_lflag 16 # Flags: eco o no; eco kill o no; lectura con buffer o no; 17 $echo = ECHO | ECHOK | ICANON; # posibles valores para c_lflag 18 $noecho = $oterm & ~$echo; # Complento a uno 19 20 sub cbreak { 21 $term->setlflag($noecho); # no se hace echo 22 $term->setcc(VTIME, 1); # marcharse 1 decima de segundo despues del dato 23 $term->setattr($fd_stdin, TCSANOW); 24 } 25 26 sub cooked { 27 $term->setlflag($oterm); 28 $term->setcc(VTIME, 0); 29 $term->setattr($fd_stdin, TCSANOW); 30 } 31 32 sub readkey { 33 my $key = ''; 34 cbreak(); 35 sysread(STDIN, $key, 1); 36 cooked(); 37 return $key; 38 } 39 40 END { cooked() } 41 42 1;Además de los modos raw y cooked los caracteres de entrada son procesados según sean los valores de los campos
c_iflag
y c_lflag
.
El campo c_lflag
se usa para controlar varias
funcionalidades. Se contruye como el OR
de las máscaras que aparecen en la tabla
7.2.
Para entender mejor el programa es necesario tener en cuenta los siguientes hechos:
ECHO
se desactiva no se hará eco de los caracteres de entrada.
ICANON
se permite el procesado canónico.
Si no se pone ICANON
, las lecturas se satisfacen directamente
desde la cola de entrada. Una lectura no se satisface hasta que
se hayan recibido VMIN
bytes o haya
expirado el crono VTIME
entre bytes.
tty
aparecen
temas relacionados con el tiempo. Por ejemplo,
en un teclado ANSI la flecha hacia arriba corresponde a
entre eventos como 'el usuario tecleo ESC
'
frente a 'el usuario tecleo flecha hacia arriba'.
Es por eso que
en un objeto Termios
figuran los campos
VTIME
(líneas 22 y 28)
y VMIN
que gobiernan la forma de lectura.
En la sesión que sigue, después de la línea 2
el proceso queda suspendido a la espera de
un carácter. El usuario a pulsado la tecla x
.
lhp@nereida:~/Lperl/src/perl_networking/ch2$ perl -de 0 DB<1> use HotKey DB<2> $x = readkey() DB<3> x $x 0 'x' DB<4>
Por razones de eficiencia y generalidad,
es mas aconsejable usar el módulo Term::ReadKey
.
lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n noecho.pl 1 use strict; 2 use Term::ReadKey; 3 ReadMode('cbreak'); 4 print "Press keys to see their ASCII values. Use Ctrl-C to quit.\n"; 5 6 while (1) { 7 my $char = ReadKey(0); 8 last unless defined $char; 9 printf(" Decimal: %d\tHex: %x\n", ord($char), ord($char)); 10 } 11 12 ReadMode('normal');
Casiano Rodríguez León