in reply to Re^3: Arrow Keys
in thread Arrow Keys

Ok...

getc() is getting each 'character' at a time... when you do control keys and function keys, they appear to be made up of more than one character.

So the script has to keep track of the sequence of characters to figure out what key was actually pressed.

(Note, this works for xterm-color on OS X)

Below is the new code:
#!/usr/bin/perl -w

use strict;
use warnings;

use IO::Handle;

eval {
    my $stdin = new IO::Handle;
       $stdin->fdopen( fileno( STDIN ), "r" ) || die "Cannot open STDIN";

    system "stty -icanon -isig -echo min 1 time 0";
    my $escape;
    my $ctrl;
    my $function;

    while ( my $char = $stdin->getc() ) {

        if ( ord( $char ) == 27 ) {             # Escape character
            $escape = 1;
            print "ESC + ";
            next;
        }
        if ( $escape && ord( $char ) == 91 ) {  # Control character
            $ctrl = 1;
            print "CTRL + ";
            next;
        }

        if ( $escape && $ctrl && $function && ord( $char ) == 126 ) {
            undef $escape;                      # Clean up after Fnctn key
            undef $ctrl;
            undef $function;
            next;
        }

        if ( $escape && $ctrl && !$function ) {
            print "Up\n"     if ( ord( $char ) == 65 );  # up
            print "Down\n"   if ( ord( $char ) == 66 );  # down
            print "Right\n"  if ( ord( $char ) == 67 );  # right arrow
            print "Left\n"   if ( ord( $char ) == 68 );  # left arrow
            if ( ord( $char ) == 49 ) {                  # Function character
                $function = 1;
                print "FCN + ";
            } else {                                     # Clean up for arrow keys
                undef $escape;
                undef $ctrl;
            }
            next;
        }

        if ( $escape && $ctrl && $function ) {
            print "F5\n"     if ( ord( $char ) == 53 ); # F5 key
            print "F6\n"     if ( ord( $char ) == 55 ); # F6 key
            print "F7\n"     if ( ord( $char ) == 56 ); # F7 key
            print "F8\n"     if ( ord( $char ) == 57 ); # F8 key
                                                        # wait for clean up char
            next;
        }

        if ( $escape && !$ctrl && !$function ) {
            print "F1\n" if ( ord( $char ) == 80 );  # F1 key
            print "F2\n" if ( ord( $char ) == 81 );  # F2 key
            print "F3\n" if ( ord( $char ) == 82 );  # F3 key
            print "F4\n" if ( ord( $char ) == 83 );  # F4 key
            undef $escape;                           # Clean up
            next;
        }

        print "Return\n" if ( ord( $char ) == 10 );  # return key
        print "Delete\n" if ( ord( $char ) == 127 ); # delete key
        print "Tab\n"    if ( ord( $char ) == 9 );   # tab key
        next             if ( ord( $char ) == 32 );  # skip on space key
        last             if ( $char =~ /q/ );        # break on q
        last             if ( $char =~ /\003/ );     # break on Ctrl-C
        last             if ( $char =~ /\032/ );     # break on Ctrl-Z
        print "ord: " . ord($char) . "\n";
    }
    system "stty icanon echo isig";
    exit(0);
};

if ( $@ ) {
    print "$@\n";
    system "stty icanon echo isig";
    exit(1);
}