Original date:2020-10-17 11:22:49 Edited by: petelomax Subject: Re: About get_key() alternative

Sure. There should be no real need for this to be part of the core interpreter, or wait for the next release.

I started cobbling the following together from some existing phix innards, reworked to run on Eu, before realising
(a) I was quite, quite stumped as to how Eu might invoke kernel calls on linux, and
(b) there is a far easier way (see below), but I got the windows bit working so here it is:

integer c_init = 0 
atom stdin, knl32, xAllocConsole, xGetStdHandle, xSetConsoleMode, stdin_redirected=0, 
                   xPeekConsoleInputA, xReadConsoleInputA, pBuffer, pBytes 
constant STD_INPUT_HANDLE = -10, 
         P = C_POINTER, 
         I = C_INT 
procedure init_console() 
    c_init = 1 
    if platform()=WINDOWS then 
        knl32 = open_dll("kernel32.dll") 
        xAllocConsole = define_c_proc(knl32,"AllocConsole",{}) 
        xGetStdHandle = define_c_func(knl32,"GetStdHandle",{P},P) 
        xSetConsoleMode = define_c_func(knl32,"SetConsoleMode",{P,I},I) 
        xPeekConsoleInputA = define_c_proc(knl32,"PeekConsoleInputA",{P,P,I,P}) 
        xReadConsoleInputA = define_c_proc(knl32,"ReadConsoleInputA",{P,P,I,P}) 
        pBuffer = allocate(20)  -- sizeof(INPUT_RECORD[/KEY_EVENT_RECORD]) 
        pBytes = allocate(8)    -- 4 or 8? (DWORD/) 
        stdin = c_func(xGetStdHandle,{STD_INPUT_HANDLE}) 
        stdin_redirected = c_func(xSetConsoleMode,{stdin,ENABLE_PROCESSED_INPUT}) 
        pBuffer = allocate(40) -- termios struct (+ 4 bytes padding) 
        stdin = 0 
    end if 
end procedure 
global function getKey() 
-- drop-in replacement for the get_key() builtin 
    integer keyChar = -1 
    if not c_init then init_console() end if 
    if platform()=WINDOWS then 
        while true do 
            if peek4s(pBytes)=0 then exit end if 
            if peek4s(pBuffer)=1            -- KEY_EVENT 
            and peek4s(pBuffer+4)=1 then    -- keyDown(ignore key up events) 
                keyChar = peek(pBuffer+14) 
                if keyChar!=0 then exit end if 
                keyChar = #100+peek(pBuffer+12) -- keyScan 
                if keyChar!=#12A            -- shift key 
                and keyChar!=#11D           -- ctrl key 
                and keyChar!=#138 then      -- alt key 
                end if 
            end if 
        end while 
    else -- LINUX 
        -- sys_ioctl(54/pBuffer/stdin/TCGETS(0x5401))... oh dear 
        -- poke4(pBuffer+12,and_bits(peek4s(pBuffer+12),#FFFFFFF5)) -- not(ICANON or ECHO)  ;turn off echo  
        -- poke(pBuffer+22,0)   -- VMIN                  ;turn off canonical mode  
        -- poke(pBuffer+23,0)   -- VTIME     ;we dont want to wait for keystrokes  
        -- sys_ioctl(54/pBuffer/stdin/TCSETS(0x5402))... oh dear 
        -- keyChar = sys_read(3/stdin/pBuffer/1).. oh dear 
        -- if keyChar=0 then keyChar=-1 end if 
        -- poke4(pBuffer+12,or_bits(peek4s(pBuffer+12),#0000000A)) -- (ICANON or ECHO)  ;turn on echo  
        -- poke(pBuffer+22,1)   -- VMIN                  ;turn on canonical mode  
        --? poke(pBuffer+23,1)  -- VTIME                 ;wait for keystrokes  
        -- sys_ioctl(54/pBuffer/stdin/TCSETS(0x5402))... oh dear 
    end if 
    return keyChar 
end function 

As promised, a far (far) easier way... (DOH)

global function getKey() 
-- drop-in replacement for the get_key() builtin 
    integer ch = get_key() 
    if platform()=WINDOWS then 
        if ch=1015936 then ch=9 end if 
    else -- linux 
--      if ch=??????? then ch=? end if 
    end if 
    return ch 
end function 

test either of the above with say

while true do 
    integer ch = getKey() 
    if ch=#1B then exit end if  -- escape 
end while 
Not Categorized, Please Help


Quick Links

User menu

Not signed in.

Misc Menu