This queue is for tickets about the TermReadKey CPAN distribution.

Report information
The Basics
Id:
16538
Status:
resolved
Priority:
Low/Low
Queue:

People
Owner:
jns [...] gellyfish.co.uk
Requestors:
klemobari [...] gmail.com
Cc:
AdminCc:

BugTracker
Severity:
(no value)
Broken in:
(no value)
Fixed in:
(no value)



From: C Barry <klemobari@gmail.com>
To: jns@gellyfish.com
Subject: ReadKey Win32 contribution
Date: Fri, 16 Dec 2005 10:20:58 +0000
Hi Jonathan,
 
I'd like to solve a portability problem in ReadKey.xs, while using latest ActiveState Perl 5.8.
 
The Win32PeekChar routine makes some basic keys look like the null byte. This is especially true with the arrow keys, and the Home/End/PgUp/PgDn navigation keys. For example the left-arrow key "\e[D" will look like "\0", and the two other characters will never be retrieved by subsequent calls to ReadKey.
 
As a direct consequence, ReadLine packages on Windows deliver a look and feel that is inferior to plain <STDIN>, which ruins the whole idea of using a ReadLine package... Windows users hardly use control keys to move on a command-line, they use arrow keys and will think that "cursor doesn't work".
 
This is also described in this interesting 2001 discussion: http://qs321.pair.com/~monkads/?node_id=125648
 
 
I believe that a solution would be to handle the case when [record.Event.KeyEvent.wVirtualKeyCode] is one of the values in (VK_RIGHT, VK_LEFT, VK_UP, VK_DOWN, VK_HOME, VK_END, VK_PAGE_UP, VK_PAGE_DOWN),
- return the escape character,
- store the subsequent characters in a static array,
- multiply "keyCount" by 3 or 4 according to the key pressed,
- and return the subsequent characters next time function is called.
 
 
Something like that:
 
int Win32PeekChar(PerlIO *file,double delay,char *key)
{
 
[...]
+      static int keySequence = 0;
+      static char[5] lastKeySequence;
[...]
 
again:
     if (keyCount > 0) {
+        if (keySequence>0) {
+             lastKey = lastKeySequence[keySequence];
+             keySequence--;
+             if (keySequence == 0) { keySequence = (int) lastKeySequence[0]; }
+       }
             keyCount--;
             *key = lastKey;
      return TRUE;
}

[...]
 
    case KEY_EVENT:
[...]
+         if (record.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) {
+                keySequence = 3;
+                lastKeySequence = {  3,     'D', '[', '\e'};       /* '\e[D' /*
+                keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
+               goto again; 
+          }
 
 
 
I'd love to send you a real patch, if only I had a compiler that makes ActiveState Perl happy... You wouldn't believe how much I need this fix. See, my users won't use my perl killer-app CLI until it has command-completion, and if I use ReadLine instead of <STDIN>, I get completion but lose support for the arrow keys... Kafka perl, so to say :-)
 
 
Regards,
Clement
Subject: Re: [cpan #16538] ReadKey Win32 contribution
From: Jonathan Stowe <jns@gellyfish.com>
To: C Barry <klemobari@gmail.com>
CC: bug-TermReadKey@rt.cpan.org
Date: Fri, 16 Dec 2005 14:02:18 +0000
RT-Send-Cc:
On Fri, 2005-12-16 at 10:06, C Barry wrote:
Show quoted text
> Hi Jonathan, > > I'd like to solve a portability problem in ReadKey.xs, while using > latest ActiveState Perl 5.8. > > The Win32PeekChar routine makes some basic keys look like the null > byte. This is especially true with the arrow keys, and the > Home/End/PgUp/PgDn navigation keys. For example the left-arrow key > "\e[D" will look like "\0", and the two other characters will never be > retrieved by subsequent calls to ReadKey. > > As a direct consequence, ReadLine packages on Windows deliver a look > and feel that is inferior to plain <STDIN>, which ruins the whole idea > of using a ReadLine package... Windows users hardly use control keys > to move on a command-line, they use arrow keys and will think that > "cursor doesn't work". > > This is also described in this interesting 2001 discussion: > http://qs321.pair.com/~monkads/?node_id=125648 > > > I believe that a solution would be to handle the case when > [record.Event.KeyEvent.wVirtualKeyCode] is one of the values in > (VK_RIGHT, VK_LEFT, VK_UP, VK_DOWN, VK_HOME, VK_END, VK_PAGE_UP, > VK_PAGE_DOWN), > - return the escape character, > - store the subsequent characters in a static array, > - multiply "keyCount" by 3 or 4 according to the key pressed, > - and return the subsequent characters next time function is called. > > > Something like that: > > int Win32PeekChar(PerlIO *file,double delay,char *key) > { > > [...] > + static int keySequence = 0; > + static char[5] lastKeySequence; > [...] > > again: > if (keyCount > 0) { > + if (keySequence>0) { > + lastKey = lastKeySequence[keySequence]; > + keySequence--; > + if (keySequence == 0) { keySequence = (int) > lastKeySequence[0]; } > + } > keyCount--; > *key = lastKey; > return TRUE; > } > > [...] > > case KEY_EVENT: > [...] > + if (record.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) { > + keySequence = 3; > + lastKeySequence = { 3, 'D', '[', '\e'}; /* > '\e[D' /* > + keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > + goto again; > + } > > > > I'd love to send you a real patch, if only I had a compiler that makes > ActiveState Perl happy... You wouldn't believe how much I need this > fix. See, my users won't use my perl killer-app CLI until it has > command-completion, and if I use ReadLine instead of <STDIN>, I get > completion but lose support for the arrow keys... Kafka perl, so > to say :-)
Hi, thanks for this. To be honest that part of the ReadKey.xs looks like it might be unfinished in respect of the special key handling, but I had been labouring under the misapprehension that this just worked under windows as it does with other OS The approach seems fine, just a simple matter of programming, however I would be a little concerned that there may be programs out there that are relying on the current behaviour, so I may have to think of a way to get it to be switchable. I don't have the same compiler as was used to build activeperl either - I built my own perl using the VS2003 compiler and that works fine. You can download the standalone compiler from the MS site somewhere - there are full instructions on compiling perl with a MS compiler in the perl source distribution and on using the MS compiler to build modules there are several articles on the perlmonks web site. I don't know when I am going to get round to putting this in, would would speed it up considerably would to get a list of all of the control-keys that currently return null on windows with the virtual key-code and the characters that the should return. I am copying in the RT queue for TermReadKey so I can keep track of the requests, if you could keep it in the CC if you reply it would be useful. Thanks again. /J\ -- This e-mail is sponsored by http://www.integration-house.com/
Date: Fri, 16 Dec 2005 18:45:54 +0200
From: C Barry <klemobari@gmail.com>
To: Jonathan Stowe <jns@gellyfish.com>
Subject: Re: [cpan #16538] ReadKey Win32 contribution
CC: bug-TermReadKey@rt.cpan.org
RT-Send-Cc:
Show quoted text
I don't know when I am going to get round to putting this in, would
would speed it up considerably would to get a list of all of the
control-keys that currently return null on windows with the virtual
key-code and the characters that the should return.
 
 
OK, let's speed it up considerably :-)
 
 
Keys that currently return 0 as AsciiChar:
----------------------------------------------------------------
(VirtualKeyCodes from google search for "VK_LEFT VK_RIGHT")
 
- Arrow keys:
 
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN
 
- Function keys:
VK_HOME, VK_END
VK_PAGE_UP, VK_PAGE_DOWN,
VK_DELETE, VK_INSERT,

VK_F1, ... , VK_F12
 
Characters that they should return
------------------------------------------------------
(based on Term::ReadLine::Zoid::Base.pm +  a capture of my keyboard strokes to a dumb telnet server)
Show quoted text
 "\e[D" => 'left',
 "\e[C" => 'right',
 "\e[A" => 'up',
 "\e[B" => 'down',
 "\e[1~"  => 'home',
 "\e[4~"  => 'end',
 "\e[5~"  => 'page_up',
 "\e[6~"  => 'page_down',
 "\e[2~"  => 'insert',
 "\e[3~"  => 'delete',
(Note: VK_DELETE in cmd.exe/telnet behaves like BS for me (chr(127)))
 "\eOP" => 'f1',
 "\eOQ" => 'f2',
 "\eOR" => 'f3',
 "\eOS" => 'f4',
 "\e[15~" => 'f5',
 "\e[17~" => 'f6',
 "\e[18~" => 'f7',
 "\e[19~" => 'f8',
 "\e[20~" => 'f9',
 "\e[21~" => 'f10',
 "\e[23~" => 'f11',
 "\e[24~" => 'f12'
(Note: I just realized that F5-F12 are 5 characters, this means static char[]  lastkeySequence length in my previous e-mail should be 6 and not 5.)
No idea about VK_SCROLL_LOCK, VK_PRINTSCREEN, VK_PAUSE: they were caught by Windows before the telnet client could sense them, and this ReadLine module doesn't mention them either. I guess ReadKey can afford ignoring them too.
 
 
Snippet to test this:
------------------------------

use Win32::Console::ANSI;
use Term::ReadLine::Zoid;
my $OUT = new Win32::Console(STD_OUTPUT_HANDLE);


        my $term = Term::ReadLine::Zoid->new("my app");
        my $prompt = "Your command# ";
        my $OUT = $term->OUT || \*STDOUT;
        while ( defined ($_ = $term->readline($prompt)) ) {
                # Think while (<STDIN>) {}
                my $res = eval($_);
                warn $@ if $@;
                print $OUT $res, "\n" unless $@;
        }

 
As for the standalone compiler, I never used the Perl/C XS interface nor a compiler in Windows... To be honest, I think I would "slow it down considerably" ;-)
 
Please let me know if you really can't get round to putting this,
 
Regards,
Clement.
CC: bug-TermReadKey@rt.cpan.org
Subject: Re: [cpan #16538] ReadKey Win32 contribution
Date: Fri, 13 Jan 2006 14:08:11 +0200
To: Jonathan Stowe <jns@gellyfish.com>
From: C Barry <klemobari@gmail.com>

Message body is not shown because sender requested not to inline it.

Hi,
 
I got the arrow keys to respond under Windows!
It works like a charm, the readline-zoid snippet handles them as expected.
 
Source code for Win32PeekChar() is reproduced below, as well as in attached ReadKey.xs.
 
Function keys were also covered: they just cause the snippet to print "f1","f5", etc.
 
Regards
Clement Barry
 
 
int Win32PeekChar(PerlIO *file,double delay,char *key)
{
 int handle;
 HANDLE whnd;
 INPUT_RECORD record;
 DWORD readRecords;

 static int keyCount = 0;
 static char lastKey = 0;
static int keySequence = 0;
static char lastKeySequence[6];


 file = STDIN;

 handle = PerlIO_fileno(file);
 whnd = /*GetStdHandle(STD_INPUT_HANDLE)*/(HANDLE)_get_osfhandle(handle);


again:
 if (keyCount > 0) {

  if (keySequence>0) {
   lastKey = lastKeySequence[keySequence];
   keySequence--;
   if (keySequence == 0) {
    keySequence = (int) lastKeySequence[0];
   }
  } 


  keyCount--;
  *key = lastKey;
     return TRUE;
 }

 if (delay > 0) {
  if (WaitForSingleObject(whnd, delay * 1000.0) != WAIT_OBJECT_0)
  {
   return FALSE;
  }
 }

 if (delay != 0) {
  PeekConsoleInput(whnd, &record, 1, &readRecords);
  if (readRecords == 0)
   return(FALSE);
 }

 ReadConsoleInput(whnd, &record, 1, &readRecords);
 switch(record.EventType)
   {
    case KEY_EVENT:
  /*printf("\nkeyDown = %d, repeat = %d, vKey = %d, vScan = %d, ASCII = %d, Control = %d\n",
   record.Event.KeyEvent.bKeyDown,
   record.Event.KeyEvent.wRepeatCount,
   record.Event.KeyEvent.wVirtualKeyCode,
   record.Event.KeyEvent.wVirtualScanCode,
   record.Event.KeyEvent.uChar.AsciiChar,
    record.Event.KeyEvent.dwControlKeyState);*/

         if (record.Event.KeyEvent.bKeyDown == FALSE)
            goto again;                        /* throw away KeyUp events */

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE LEFT-SQUARE-BRACKET D */
  lastKeySequence[1] = 'D';
  lastKeySequence[2] = '[';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE LEFT-SQUARE-BRACKET C */
  lastKeySequence[1] = 'C';
  lastKeySequence[2] = '[';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_UP) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE LEFT-SQUARE-BRACKET A */
  lastKeySequence[1] = 'A';
  lastKeySequence[2] = '[';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE LEFT-SQUARE-BRACKET B */
  lastKeySequence[1] = 'B';
  lastKeySequence[2] = '[';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_HOME) {
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 1 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '1';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_END) {
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 4 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '4';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_PRIOR) { /* PAGE UP */
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 5 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '5';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_NEXT) { /* PAGE DOWN */
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 6 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '6';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_INSERT) {
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 2 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '2';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_DELETE) {
  keySequence = 4;
  lastKeySequence[0] = 4;   /* ESCAPE LEFT-SQUARE-BRACKET 3 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '3';
  lastKeySequence[3] = '[';
  lastKeySequence[4] = 27;
  keyCount = 4*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F1) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE O P */
  lastKeySequence[1] = 'P';
  lastKeySequence[2] = 'O';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F2) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE O Q */
  lastKeySequence[1] = 'Q';
  lastKeySequence[2] = 'O';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F3) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE O R */
  lastKeySequence[1] = 'R';
  lastKeySequence[2] = 'O';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F4) {
  keySequence = 3;
  lastKeySequence[0] = 3;   /* ESCAPE O S */
  lastKeySequence[1] = 'S';
  lastKeySequence[2] = 'O';
  lastKeySequence[3] = 27;
  keyCount = 3*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F5) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 1 5 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '5';
  lastKeySequence[3] = '1';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F6) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 1 7 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '7';
  lastKeySequence[3] = '1';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F7) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 1 8 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '8';
  lastKeySequence[3] = '1';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F8) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 1 9 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '9';
  lastKeySequence[3] = '1';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F9) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 2 0 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '0';
  lastKeySequence[3] = '2';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F10) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 2 1 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '1';
  lastKeySequence[3] = '2';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F11) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 2 3 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '3';
  lastKeySequence[3] = '2';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }
 if (record.Event.KeyEvent.wVirtualKeyCode == VK_F12) {
  keySequence = 5;
  lastKeySequence[0] = 5;   /* ESCAPE LEFT-SQUARE-BRACKET 2 4 TILDA */
  lastKeySequence[1] = '~';
  lastKeySequence[2] = '4';
  lastKeySequence[3] = '2';
  lastKeySequence[4] = '[';
  lastKeySequence[5] = 27;
  keyCount = 5*(record.Event.KeyEvent.wRepeatCount);
  goto again;
 }

         if (record.Event.KeyEvent.wVirtualKeyCode == 16
         ||  record.Event.KeyEvent.wVirtualKeyCode == 17
         ||  record.Event.KeyEvent.wVirtualKeyCode == 18
         ||  record.Event.KeyEvent.wVirtualKeyCode == 20
         ||  record.Event.KeyEvent.wVirtualKeyCode == 144
         ||  record.Event.KeyEvent.wVirtualKeyCode == 145)
            goto again;  /* throw away shift/alt/ctrl key only key events */
         keyCount = record.Event.KeyEvent.wRepeatCount;
   break;
    default:
         keyCount = 0;
         goto again;
         break;
   }

 *key = lastKey = record.Event.KeyEvent.uChar.AsciiChar;
 keyCount--;
 
 return(TRUE);

 /* again:
 return (FALSE);
 */


}

CC: bug-TermReadKey@rt.cpan.org
Subject: Re: [cpan #16538] ReadKey Win32 contribution
Date: Fri, 13 Jan 2006 17:09:15 +0000
To: C Barry <klemobari@gmail.com>
From: Jonathan Stowe <jns@gellyfish.com>
On Fri, 2006-01-13 at 12:08, C Barry wrote:
Show quoted text
> Hi, > > I got the arrow keys to respond under Windows! > It works like a charm, the readline-zoid snippet handles them as > expected. > > Source code for Win32PeekChar() is reproduced below, as well as in > attached ReadKey.xs. > > Function keys were also covered: they just cause the snippet to print > "f1","f5", etc. >
Thanks for this. I have taken the liberty of changing your if statements into a big switch and moving a few things round, but it seems to work, if you get a minute would you mind testing with the attached? If it works for you then I'll do the rest of the changes and make a release some time over the weekend.
Show quoted text
> Regards > Clement Barry > > > int Win32PeekChar(PerlIO *file,double delay,char *key) > { > int handle; > HANDLE whnd; > INPUT_RECORD record; > DWORD readRecords; > > static int keyCount = 0; > static char lastKey = 0; > static int keySequence = 0; > static char lastKeySequence[6]; > > > file = STDIN; > > handle = PerlIO_fileno(file); > whnd = > /*GetStdHandle(STD_INPUT_HANDLE)*/(HANDLE)_get_osfhandle(handle); > > > again: > if (keyCount > 0) { > > if (keySequence>0) { > lastKey = lastKeySequence[keySequence]; > keySequence--; > if (keySequence == 0) { > keySequence = (int) lastKeySequence[0]; > } > } > > > keyCount--; > *key = lastKey; > return TRUE; > } > > if (delay > 0) { > if (WaitForSingleObject(whnd, delay * 1000.0) != WAIT_OBJECT_0) > { > return FALSE; > } > } > > if (delay != 0) { > PeekConsoleInput(whnd, &record, 1, &readRecords); > if (readRecords == 0) > return(FALSE); > } > > ReadConsoleInput(whnd, &record, 1, &readRecords); > switch(record.EventType) > { > case KEY_EVENT: > /*printf("\nkeyDown = %d, repeat = %d, vKey = %d, vScan = %d, ASCII > = %d, Control = %d\n", > record.Event.KeyEvent.bKeyDown, > record.Event.KeyEvent.wRepeatCount, > record.Event.KeyEvent.wVirtualKeyCode, > record.Event.KeyEvent.wVirtualScanCode, > record.Event.KeyEvent.uChar.AsciiChar, > record.Event.KeyEvent.dwControlKeyState);*/ > > if (record.Event.KeyEvent.bKeyDown == FALSE) > goto again; /* throw away KeyUp > events */ > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE LEFT-SQUARE-BRACKET D */ > lastKeySequence[1] = 'D'; > lastKeySequence[2] = '['; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE LEFT-SQUARE-BRACKET C */ > lastKeySequence[1] = 'C'; > lastKeySequence[2] = '['; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_UP) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE LEFT-SQUARE-BRACKET A */ > lastKeySequence[1] = 'A'; > lastKeySequence[2] = '['; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE LEFT-SQUARE-BRACKET B */ > lastKeySequence[1] = 'B'; > lastKeySequence[2] = '['; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_HOME) { > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 1 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '1'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_END) { > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 4 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '4'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_PRIOR) { /* PAGE UP > */ > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 5 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '5'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_NEXT) { /* PAGE DOWN > */ > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 6 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '6'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_INSERT) { > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 2 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '2'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_DELETE) { > keySequence = 4; > lastKeySequence[0] = 4; /* ESCAPE LEFT-SQUARE-BRACKET 3 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '3'; > lastKeySequence[3] = '['; > lastKeySequence[4] = 27; > keyCount = 4*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F1) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE O P */ > lastKeySequence[1] = 'P'; > lastKeySequence[2] = 'O'; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F2) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE O Q */ > lastKeySequence[1] = 'Q'; > lastKeySequence[2] = 'O'; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F3) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE O R */ > lastKeySequence[1] = 'R'; > lastKeySequence[2] = 'O'; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F4) { > keySequence = 3; > lastKeySequence[0] = 3; /* ESCAPE O S */ > lastKeySequence[1] = 'S'; > lastKeySequence[2] = 'O'; > lastKeySequence[3] = 27; > keyCount = 3*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F5) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 1 5 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '5'; > lastKeySequence[3] = '1'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F6) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 1 7 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '7'; > lastKeySequence[3] = '1'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F7) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 1 8 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '8'; > lastKeySequence[3] = '1'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F8) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 1 9 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '9'; > lastKeySequence[3] = '1'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F9) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 2 0 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '0'; > lastKeySequence[3] = '2'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F10) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 2 1 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '1'; > lastKeySequence[3] = '2'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F11) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 2 3 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '3'; > lastKeySequence[3] = '2'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > if (record.Event.KeyEvent.wVirtualKeyCode == VK_F12) { > keySequence = 5; > lastKeySequence[0] = 5; /* ESCAPE LEFT-SQUARE-BRACKET 2 4 TILDA */ > lastKeySequence[1] = '~'; > lastKeySequence[2] = '4'; > lastKeySequence[3] = '2'; > lastKeySequence[4] = '['; > lastKeySequence[5] = 27; > keyCount = 5*(record.Event.KeyEvent.wRepeatCount); > goto again; > } > > if (record.Event.KeyEvent.wVirtualKeyCode == 16 > || record.Event.KeyEvent.wVirtualKeyCode == 17 > || record.Event.KeyEvent.wVirtualKeyCode == 18 > || record.Event.KeyEvent.wVirtualKeyCode == 20 > || record.Event.KeyEvent.wVirtualKeyCode == 144 > || record.Event.KeyEvent.wVirtualKeyCode == 145) > goto again; /* throw away shift/alt/ctrl key only key > events */ > keyCount = record.Event.KeyEvent.wRepeatCount; > break; > default: > keyCount = 0; > goto again; > break; > } > > *key = lastKey = record.Event.KeyEvent.uChar.AsciiChar; > keyCount--; > > return(TRUE); > > /* again: > return (FALSE); > */ > > > }
-- This e-mail is sponsored by http://www.integration-house.com/

Message body is not shown because sender requested not to inline it.

CC: bug-TermReadKey@rt.cpan.org
Subject: Re: [cpan #16538] ReadKey Win32 contribution
Date: Fri, 13 Jan 2006 19:41:36 +0200
To: Jonathan Stowe <jns@gellyfish.com>
From: C Barry <klemobari@gmail.com>
2006/1/13, Jonathan Stowe <jns@gellyfish.com>:
Show quoted text
Thanks for this.  I have taken the liberty of changing your if
statements into a big switch and moving a few things round, but it seems
to work, if you get a minute would you mind testing with the attached?
If it works for you then I'll do the rest of the changes and make a
release some time over the weekend.
 
You have a point here, Perl almost made me forget switch statements...
However I'm a bit concerned about unifying control/shift/alt-keys and arrow-keys under a same switch, especially in the absence of a default label. The following line:

           keyCount = keySequence * (record.Event.KeyEvent.wRepeatCount);

will be non-zero even for a simple pressure on Control. Maybe would it be wiser to set keySequence back to 0 for cases 16, 17, 18, 20, 144, 145 and default. The ''again'' label doesn't reset keySequence to zero, it resets to 3/4/5 because keyCount may be >1.


Also, you may want to replace lines like these:

Show quoted text
<   keySequence = 3;
<   lastKeySequence[0] = 3;   /* ESCAPE LEFT-SQUARE-BRACKET D */

by those equivalent, less hardcoded lines:

Show quoted text
>   keySequence = 3;
>   lastKeySequence[0] = keySequence;   /* ESCAPE LEFT-SQUARE-BRACKET D */

Basically I stored the int keySequence as a first character of lastKeySequence everywhere, and retrieved it in the ''again'' label by a casting to int type. A kind of very raw data structure.


I wait for your comment on that before I go back testing.


Regards,
Clement
Just so you guys know, there's a new Win32 distribution on the way called Vanilla Perl. It's Perl compiled from scratch with (and building in) MinGW. You might find it easier to test against this than you do ActivePerl. To download a copy, see... http://sourceforge.net/project/showfiles.php?group_id=158775 Thanks
From: christopher@pobox.com
I've got nothing to do with this module, but, if you want to send me your best guess at a patch, I can compile and test it and then submit it to Jonathan in a format he can use immediately.
Subject: Re: [perl #59690][cpan #16538] Term::ReadKey's Win32PeekChar doesn't support special keys
Date: Wed, 8 Oct 2008 12:18:39 +0100
To: perl5-porters@perl.org, bug-TermReadKey@rt.cpan.org, jerbraun@microsoft.com
From: "Jonathan Stowe" <jns@integration-house.com>
Hi Jeremy, Term::ReadKey is not maintained as part of the Perl core. The ticket #59690 can be closed. I already have an ancient RT ticket (#16538) against this same feature request with a patch, I've held off releasing this because I haven't had the facilities to compile and test on Windows. If someone could volunteer to help test a new release then I'd be happy to make the fix. 2008/10/7 via RT Jeremy Braun <perlbug-followup@perl.org>:
Show quoted text
> # New Ticket Created by Jeremy Braun > # Please include the string: [perl #59690] > # in the subject line of all future correspondence about this issue. > # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=59690 > > > > This is a bug report for perl from jerbraun@microsoft.com, > generated with the help of perlbug 1.36 running under perl 5.10.0. > > > ----------------------------------------------------------------- > [Please enter your report here] > > In ReadKey.xs, Win32PeekChar only uses > record.Event.KeyEvent.uChar.AsciiChar to figure out the *key return > value. For text this is okay, but special keys (F1-Fx, HOME, PAGEUP, > PAGEDOWN, ARROWS, etc) all set AsciiChar to zero. In these cases, the > wVirtualKeyCode must be used to figure out what key was pressed. > > (Perl's getc seems to have a similiar bug?) > > > [Please do not change anything below this line] > ----------------------------------------------------------------- > --- > Flags: > category=library > severity=medium > --- > Site configuration information for perl 5.10.0: > > Configured by SYSTEM at Tue May 13 16:52:25 2008. > > Summary of my perl5 (revision 5 version 10 subversion 0) configuration: > Platform: > osname=MSWin32, osvers=5.00, archname=MSWin32-x86-multi-thread > uname='' > config_args='undef' > hint=recommended, useposix=true, d_sigaction=undef > useithreads=define, usemultiplicity=define > useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef > use64bitint=undef, use64bitall=undef, uselongdouble=undef > usemymalloc=n, bincompat5005=undef > Compiler: > cc='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -DPRIVLIB_LAST_IN_INC -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX', > optimize='-MD -Zi -DNDEBUG -O1', > cppflags='-DWIN32' > ccversion='14.1.60511', gccversion='', gccosandvers='' > intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 > d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10 > ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksize=8 > alignbytes=8, prototype=define > Linker and Libraries: > ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -libpath:"D:\sd\pyxis\source\40\zune\tools\perl\lib\CORE" -machine:x86' > libpth=\lib > libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib > perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib > libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl510.lib > gnulibc_version='' > Dynamic Linking: > dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' ' > cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -libpath:"D:\sd\pyxis\source\40\zune\tools\perl\lib\CORE" -machine:x86' > > Locally applied patches: > ACTIVEPERL_LOCAL_PATCHES_ENTRY > 33741 avoids segfaults invoking S_raise_signal() (on Linux) > 33763 Win32 process ids can have more than 16 bits > 32809 Load 'loadable object' with non-default file extension > 32728 64-bit fix for Time::Local > > --- > @INC for perl 5.10.0: > D:/sd/pyxis/source/40/zune/tools/perl/site/lib > D:/sd/pyxis/source/40/zune/tools/perl/lib > . > > --- > Environment for perl 5.10.0: > HOME=C:\Users\jerbraun > LANG (unset) > LANGUAGE (unset) > LD_LIBRARY_PATH (unset) > LOGDIR (unset) > PATH=D:\sd\pyxis\source\40\sdk\bin\i386\ARM;D:\sd\pyxis\source\40\sdk\bin\i386;D:\sd\pyxis\source\40\public\common\oak\Bin\i386;D:\sd\pyxis\source\40\private\bin\i386;D:\sd\pyxis\source\40\private\bat;D:\sd\pyxis\source\40\public\common\oak\misc;D:\sd\pyxis\source\40\developr\jerbraun;C:\Python25\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;D:\sd\pyxis\source\40\zune\developer\jerbraun\bin;C:\PROGRA~1\NcFTP;C:\Program Files\Microsoft Application Virtualization Client;C:\Program Files\Microsoft Network Monitor 3\;C:\Windows\system32\WindowsPowerShell\v1.0\;D:\sd\pyxis\source\40\platform\WOOKIE;D:\sd\pyxis\source\40\platform\WOOKIE\tools\bin\i386;D:\sd\pyxis\source\40\platform\WOOKIE\tools\nvflash\bin\i386;D:\sd\pyxis\source\40\platform\WOOKIE\tools\buildbct\bin\i386;D:\sd\pyxis\source\40\zune\tools\bin\i386;D:\sd\pyxis\source\40\zune\tools\bat;D:\sd\pyxis\source\40\zune\tools\perl\bin;D:\sd\pyxis\source\40\zune\tools\perl\site\bin;C:\Program Files\GnuWin32\bin! > ;c:\Python25;F:\sd\xbox\cadence\tools\bin;D:\sd\pyxis\source\40\zune\tools\env;C:\Cadence\SPB_16.01\tools\specctra\bin;C:\Cadence\SPB_16.01\tools\pcb\bin;C:\Cadence\SPB_16.01\tools\bin;C:\Cadence\SPB_16.01\tools\libutil\bin;C:\Cadence\SPB_16.01\tools\fet\bin > PERLDOC_NROFF=groff -E -mtty-char -Tascii -P-c > PERL_BADLANG (unset) > SHELL (unset) >
Subject: RE: [perl #59690][cpan #16538] Term::ReadKey's Win32PeekChar doesn't support special keys
Date: Wed, 8 Oct 2008 09:45:06 -0700
To: Jonathan Stowe <jns@integration-house.com>
From: Jeremy Braun <jerbraun@microsoft.com>
Thanks Jonathan, incredible turn-around time! I compiled/tested this with visualstudio 9, and it worked* well. If you want (for clarity), the key codes are available as VK_* in foo.h. Please find below a modified portion of Win32PeekChar. Also, your email address is out of date in the pod for ReadKey.pm. Thanks again! *- Microsoft added run-time parameter checking to all of the exports from the MS Visual C Runtime. If "invalid" parameters are passed to a c-runtime function (like _get_osfhandle), rather than return an error code, the c-runtime by default causes an AV and you get a "this program has stopped working" dialog box. I modified every API entry to call _set_invalid_parameter_handler, and things worked great. switch(record.EventType) { case KEY_EVENT: /* printf("\nkeyDown = %d, repeat = %d, vKey = %d, vScan = %d, ASCII = %d, Control = %d\n", record.Event.KeyEvent.bKeyDown, record.Event.KeyEvent.wRepeatCount, record.Event.KeyEvent.wVirtualKeyCode, record.Event.KeyEvent.wVirtualScanCode, record.Event.KeyEvent.uChar.AsciiChar, record.Event.KeyEvent.dwControlKeyState); */ if (record.Event.KeyEvent.bKeyDown == FALSE) goto again; /* throw away KeyUp events */ switch(record.Event.KeyEvent.wVirtualKeyCode) { case VK_SHIFT: case VK_LSHIFT: case VK_RSHIFT: case VK_CONTROL: case VK_LCONTROL: case VK_RCONTROL: case VK_MENU: case VK_LMENU: case VK_RMENU: case VK_CAPITAL: case VK_NUMLOCK: case VK_SCROLL: /* throw away shift/alt/ctrl key only key events */ goto again; case VK_UP: KEY_PUSH3(27, 91, 65); case VK_DOWN: KEY_PUSH3(27, 91, 66); case VK_RIGHT: KEY_PUSH3(27, 91, 67); case VK_LEFT: KEY_PUSH3(27, 91, 68); case VK_PRIOR: KEY_PUSH3(27, 79, 121); case VK_NEXT: KEY_PUSH3(27, 79, 115); case VK_HOME: KEY_PUSH4(27, 91, 49, 126); case VK_INSERT: KEY_PUSH4(27, 91, 50, 126); case VK_DELETE: KEY_PUSH4(27, 91, 51, 126); case VK_END: KEY_PUSH4(27, 91, 52, 126); } keyCount = record.Event.KeyEvent.wRepeatCount; break; default: keyCount = 0; goto again; break; }
Show quoted text
-----Original Message----- From: jonathan.stowe@gmail.com [mailto:jonathan.stowe@gmail.com] On Behalf Of Jonathan Stowe Sent: Wednesday, October 08, 2008 4:19 AM To: perl5-porters@perl.org; bug-TermReadKey@rt.cpan.org; Jeremy Braun Subject: Re: [perl #59690][cpan #16538] Term::ReadKey's Win32PeekChar doesn't support special keys Hi Jeremy, Term::ReadKey is not maintained as part of the Perl core. The ticket #59690 can be closed. I already have an ancient RT ticket (#16538) against this same feature request with a patch, I've held off releasing this because I haven't had the facilities to compile and test on Windows. If someone could volunteer to help test a new release then I'd be happy to make the fix. 2008/10/7 via RT Jeremy Braun <perlbug-followup@perl.org>:
> # New Ticket Created by Jeremy Braun > # Please include the string: [perl #59690] > # in the subject line of all future correspondence about this issue. > # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=59690 > > > > This is a bug report for perl from jerbraun@microsoft.com, > generated with the help of perlbug 1.36 running under perl 5.10.0. > > > ----------------------------------------------------------------- > [Please enter your report here] > > In ReadKey.xs, Win32PeekChar only uses > record.Event.KeyEvent.uChar.AsciiChar to figure out the *key return > value. For text this is okay, but special keys (F1-Fx, HOME, PAGEUP, > PAGEDOWN, ARROWS, etc) all set AsciiChar to zero. In these cases, the > wVirtualKeyCode must be used to figure out what key was pressed. > > (Perl's getc seems to have a similiar bug?) > > > [Please do not change anything below this line] > ----------------------------------------------------------------- > --- > Flags: > category=library > severity=medium > --- > Site configuration information for perl 5.10.0: > > Configured by SYSTEM at Tue May 13 16:52:25 2008. > > Summary of my perl5 (revision 5 version 10 subversion 0) configuration: > Platform: > osname=MSWin32, osvers=5.00, archname=MSWin32-x86-multi-thread > uname='' > config_args='undef' > hint=recommended, useposix=true, d_sigaction=undef > useithreads=define, usemultiplicity=define > useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef > use64bitint=undef, use64bitall=undef, uselongdouble=undef > usemymalloc=n, bincompat5005=undef > Compiler: > cc='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -DPRIVLIB_LAST_IN_INC -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX', > optimize='-MD -Zi -DNDEBUG -O1', > cppflags='-DWIN32' > ccversion='14.1.60511', gccversion='', gccosandvers='' > intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 > d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10 > ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksize=8 > alignbytes=8, prototype=define > Linker and Libraries: > ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -libpath:"D:\sd\pyxis\source\40\zune\tools\perl\lib\CORE" -machine:x86' > libpth=\lib > libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib > perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib > libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl510.lib > gnulibc_version='' > Dynamic Linking: > dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' ' > cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -libpath:"D:\sd\pyxis\source\40\zune\tools\perl\lib\CORE" -machine:x86' > > Locally applied patches: > ACTIVEPERL_LOCAL_PATCHES_ENTRY > 33741 avoids segfaults invoking S_raise_signal() (on Linux) > 33763 Win32 process ids can have more than 16 bits > 32809 Load 'loadable object' with non-default file extension > 32728 64-bit fix for Time::Local > > --- > @INC for perl 5.10.0: > D:/sd/pyxis/source/40/zune/tools/perl/site/lib > D:/sd/pyxis/source/40/zune/tools/perl/lib > . > > --- > Environment for perl 5.10.0: > HOME=C:\Users\jerbraun > LANG (unset) > LANGUAGE (unset) > LD_LIBRARY_PATH (unset) > LOGDIR (unset) > PATH=D:\sd\pyxis\source\40\sdk\bin\i386\ARM;D:\sd\pyxis\source\40\sdk\bin\i386;D:\sd\pyxis\source\40\public\common\oak\Bin\i386;D:\sd\pyxis\source\40\private\bin\i386;D:\sd\pyxis\source\40\private\bat;D:\sd\pyxis\source\40\public\common\oak\misc;D:\sd\pyxis\source\40\developr\jerbraun;C:\Python25\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;D:\sd\pyxis\source\40\zune\developer\jerbraun\bin;C:\PROGRA~1\NcFTP;C:\Program Files\Microsoft Application Virtualization Client;C:\Program Files\Microsoft Network Monitor 3\;C:\Windows\system32\WindowsPowerShell\v1.0\;D:\sd\pyxis\source\40\platform\WOOKIE;D:\sd\pyxis\source\40\platform\WOOKIE\tools\bin\i386;D:\sd\pyxis\source\40\platform\WOOKIE\tools\nvflash\bin\i386;D:\sd\pyxis\source\40\platform\WOOKIE\tools\buildbct\bin\i386;D:\sd\pyxis\source\40\zune\tools\bin\i386;D:\sd\pyxis\source\40\zune\tools\bat;D:\sd\pyxis\source\40\zune\tools\perl\bin;D:\sd\pyxis\source\40\zune\tools\perl\site\bin;C:\Program Files\GnuWin32\bin
!
> ;c:\Python25;F:\sd\xbox\cadence\tools\bin;D:\sd\pyxis\source\40\zune\tools\env;C:\Cadence\SPB_16.01\tools\specctra\bin;C:\Cadence\SPB_16.01\tools\pcb\bin;C:\Cadence\SPB_16.01\tools\bin;C:\Cadence\SPB_16.01\tools\libutil\bin;C:\Cadence\SPB_16.01\tools\fet\bin > PERLDOC_NROFF=groff -E -mtty-char -Tascii -P-c > PERL_BADLANG (unset) > SHELL (unset) >
RT-Send-CC: perl5-porters@perl.org
I had a look at the whole history of this ticket, and the current status is not clear to me. The report also lacks some sample code to reproduce the issue, so I don't know hot to reproduce it to help triaging the issue. Besides that, the Changes file in release 2.31 is completely empty. So, it would be helpful if someone could add a summary of the current status: is it fixed? has any of the provided patches been merged? -- Olivier Mengué - http://perlresume.org/DOLMEN
Hi, due to a variety of reason including this module having moved version control several times in the last ten years, I've totally lost track of where this is at. If anyone has anything to add please send a pull request to https://github.com/jonathanstowe/TermReadKey with the appropriate changes. Thanks,


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.