Search code examples
pascal

Pascal readkey command issue


I use readkey command twice. It works fine on the first time but refuses to work in the second one. I'd like that program waits for my key press but the program ends itself.

code:

program window1;

uses crt;

var x,y:integer;

begin

clrscr;
window(1,1,80,25);
readkey;

//writting just window borders
for x:=1 to 80 do
 for y:=1 to 25 do
 begin
   if (x >= 2) and (x <= 79) and
      (y >= 2) and (y <= 24) then
     continue
   else
     begin
       gotoxy(x,y);
       write('*');
     end;
 end;

gotoxy(2,23);
write('inside window press any key to exit...');
readkey;
//readln;

end.

I've pressed the up arrow key.


Solution

  • I've pressed the up arrow key

    Some keys on a keyboard generates what is called extended keys. The arrow keys (among others) are such keys. They return two characters, not one. The first character is ASCII 0 and the second is the scan code of the pressed key.

    For ReadKey it is documented:

    ReadKey reads 1 key from the keyboard buffer, and returns this. If an extended or function key has been pressed, then the zero ASCII code is returned. You can then read the scan code of the key with a second ReadKey call.

    I could add to that, that ReadKey waits for input if the keyboard buffer is empty (but only if it is empty).

    Therefore, when your program calls ReadKey for the first time, and you hit the "up arrow key", two bytes are put into the buffer, $00 and $48. The first one ($00) is returned to your code, and the scan code for the up arrow remains in the input buffer. When you then later call ReadKey a second time it receives the scan code from the buffer and continues immediately without stopping for input.

    You can deal with this in one of two ways:

    1.Write a procedure, say WaitForAnyKey that deals with the extended keys:

    procedure WaitForAnyKey;
    var
      c: char;
    begin
      c:=ReadKey;
      if c=#0 then
        c:=ReadKey;
    end;
    

    and you call it instead of calling ReadKey directly.

    2.Write a procedure that waits for, and accepts a specific key only:

    procedure WaitForCR; // wait for CR, Carriage Return (Enter)
    const
      CR=#13;
    var
      c: Char;
    begin
      repeat
        c:=ReadKey;
      until c=CR;
    end
    

    and you call it instead of calling ReadKey directly.