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
