Get Key Function?

523 views
Skip to first unread message

nuclear...@gmail.com

unread,
May 1, 2009, 10:51:31 AM5/1/09
to
I've been searching around the message board for information on a "Get
Key" function for Fortran - the ability to have a program read input
from a keyboard without having to push enter - and I've found a few
posts that explain the difficulty of this. However, the posts I could
find were at least a decade old, some older than that.

Have there been any recent developments (or tricks) that would allow
for input that doesn't require pressing the return key? If it helps,
I'm using g95.

Thanks!

Jason Blevins

unread,
May 1, 2009, 12:41:11 PM5/1/09
to

Coincidentally, I was reading Clive Page's Fortran page this morning and
it mentions reading single keystrokes. Unfortunately, it says there
isn't a portable way to do this in Fortran, but he offers a C function
with some instructions on how to call it from Fortran:

http://www.star.le.ac.uk/~cgp/fortran.html
http://www.star.le.ac.uk/~cgp/sys_keyin.c

I would imagine there is a way to do this in Fortran 2003 using
stream input from stdin, but I couldn't get anything working.
Maybe someone else knows...

If you don't mind using something non-standard, I know that
GFortran has an FGET extension for this. It's likely that
G95 has a similar extension.

http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gfortran/FGET.html

Jason

glen herrmannsfeldt

unread,
May 1, 2009, 1:09:52 PM5/1/09
to
Jason Blevins <jrbl...@sdf.lonestar.org> wrote:
(snip)


> Coincidentally, I was reading Clive Page's Fortran page this morning and
> it mentions reading single keystrokes. Unfortunately, it says there
> isn't a portable way to do this in Fortran, but he offers a C function
> with some instructions on how to call it from Fortran:

It is not standard C either, but it is a more common extension
in C libraries than Fortran libraries.

-- glen

Jason Blevins

unread,
May 1, 2009, 2:42:25 PM5/1/09
to
On May 1, 2009, at 12:41 PM, Jason Blevins wrote:
> On May 1, 2009, at 10:51 AM, nuclear wingnut wrote:
>> I've been searching around the message board for information on a "Get
>> Key" function for Fortran - the ability to have a program read input
>> from a keyboard without having to push enter - and I've found a few
>> posts that explain the difficulty of this. However, the posts I could
>> find were at least a decade old, some older than that.
>
> (snip)

>
> If you don't mind using something non-standard, I know that
> GFortran has an FGET extension for this. It's likely that
> G95 has a similar extension.

My mistake. I just realized that FGET doesn't quite do what
you want. It just reads in stream mode, it won't get the
input for you immediately after a key press.

Jason

Jason Blevins

unread,
May 1, 2009, 2:55:24 PM5/1/09
to

Now I see that Clive's code only works on "most Unix systems"
as it uses termios.h.

So, if I understand, the problem is that the terminal usually
buffers the input and so you have to specifically ask it to send
the input character-for-character, but you have to do so in a
platform-dependent way.

Jason

me...@skyway.usask.ca

unread,
May 1, 2009, 9:00:47 AM5/1/09
to

What I do in WATCOM FOrtran 77 (www.openwatcom.org)
is have a little "pragma" (short assembler program embedded
in the source) which looks at the keyboard strobe and gets
the keycode if there was a strobe. If it's a key I don't want,
I clear the strobe and return "no key".
But other fortrans don't have this ability. Too bad.
Chris

Clive Page

unread,
May 1, 2009, 6:26:19 PM5/1/09
to
>My mistake. I just realized that FGET doesn't quite do what
>you want. It just reads in stream mode, it won't get the
>input for you immediately after a key press.

Yes, the routine that I link to only works on "some" Unix systems,
mostly the older ones. I haven't got it to work on Windows with g95 or
gfortran, nor do I know of any other way of doing this, unfortunately.


--
Clive Page

Craig Powers

unread,
May 1, 2009, 8:02:34 PM5/1/09
to

On Windows, you ought to be able to use an API function of some sort or
another (though what with the stdcall cf, you probably have to do a
C/C++ wrapper in order to have a cdecl function to bind(C) to in Win32).

Gary Scott

unread,
May 1, 2009, 11:07:24 PM5/1/09
to

No, those declarations are all provided for you, no muss no fuss.

--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library: http://www.fortranlib.com

Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford

Clive Page

unread,
May 3, 2009, 5:52:20 AM5/3/09
to
In message <87zldw6...@roark.xbeta.org>, Jason Blevins
<jrbl...@sdf.lonestar.org> writes

>it mentions reading single keystrokes. Unfortunately, it says there
>isn't a portable way to do this in Fortran, but he offers a C function
>with some instructions on how to call it from Fortran:

>http://www.star.le.ac.uk/~cgp/sys_keyin.c

As noted earlier, this works on some Unix-like systems including Linux,
but not on Windows.

>I would imagine there is a way to do this in Fortran 2003 using
>stream input from stdin, but I couldn't get anything working.
>Maybe someone else knows...
>
>If you don't mind using something non-standard, I know that
>GFortran has an FGET extension for this. It's likely that
>G95 has a similar extension.
>
>http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gfortran/FGET.html

I've tried this too, but can't get it to read single keystrokes - the
keystroke read still needs a RETURN at the end.

On Windows the nearest I've been able to find uses a function in the
GrWin library, which can be downloaded from:
http://spdg1.sci.shizuoka.ac.jp/grwinlib/english/

This contains a function kbgetch(n) which returns the integer code of
the next single keystroke. Normally n=0 but if n=1 then the character
is echoed to stdout.

This can be linked using g95 or gfortran on Windows-XP using a command
like this:
>g95 testkbd.f90 -Wl,--subsystem,console -lGrWin -mwindows -lg2c

I have no idea what the switch "-Wl,--subsystem,console" is doing, it is
just a bit of magic I found in the GrWin files. If anyone understands
it, please post.

It is, as you say, a pity that this cannot be done in a way that is
portable across operating systems.

--
Clive Page

user1

unread,
May 3, 2009, 9:26:07 AM5/3/09
to

I'd wager that "-Wl,--subsystem,console" ensures that a console window
will be created when the executable loads. I think I read somewhere that
whether or not a console window is created when a Windows app loads
boils down to the value of a singe byte somewhere in the exe header.

What is more interesting above is that you are compiling with g95 and
linking with the g77 runtime ( -lg2c ), so it seems that you would need
both compilers (g95 and g77) installed to use GrWin with g95.

Clive Page

unread,
May 4, 2009, 7:59:10 AM5/4/09
to
In message <gtk61k$6au$1...@news.motzarella.org>, user1 <us...@example.net>
writes

>I'd wager that "-Wl,--subsystem,console" ensures that a console window
>will be created when the executable loads. I think I read somewhere
>that whether or not a console window is created when a Windows app
>loads boils down to the value of a singe byte somewhere in the exe header.

That's sounds a good explanation. But I still don't quite know why this
is needed for the single keystroke routine to work.

>What is more interesting above is that you are compiling with g95 and
>linking with the g77 runtime ( -lg2c ), so it seems that you would need
>both compilers (g95 and g77) installed to use GrWin with g95.

I'm doing that deliberately because the GrWin library was built using
g77, so some of its low-level routines need things not in the
g95/gfortran libraries. Adding -lg2c seems to solve this. g77 seems to
come with the MinGW installation, so it needed no extra effort (for me
at least).

I can't claim this is a good way of getting a single keystroke, just
that it works. Presumably somewhere hidden in the GrWin source code is
the C code to do just that, which could be extracted. I haven't had
time to delve deeply enough and do that.

--
Clive Page

dpb

unread,
May 4, 2009, 9:16:52 AM5/4/09
to
Clive Page wrote:
...

> That's sounds a good explanation. But I still don't quite know why this
> is needed for the single keystroke routine to work.
...
Because w/o a console there's not a keyboard input only a Windows
messages queue created.

--

Craig Powers

unread,
May 4, 2009, 1:30:55 PM5/4/09
to
Gary Scott wrote:
> Craig Powers wrote:
>> Clive Page wrote:
>>
>>>> My mistake. I just realized that FGET doesn't quite do what
>>>> you want. It just reads in stream mode, it won't get the
>>>> input for you immediately after a key press.
>>>
>>>
>>> Yes, the routine that I link to only works on "some" Unix systems,
>>> mostly the older ones. I haven't got it to work on Windows with g95
>>> or gfortran, nor do I know of any other way of doing this,
>>> unfortunately.
>>
>>
>> On Windows, you ought to be able to use an API function of some sort
>> or another (though what with the stdcall cf, you probably have to do a
>> C/C++ wrapper in order to have a cdecl function to bind(C) to in Win32).
>
> No, those declarations are all provided for you, no muss no fuss.

In ifort/CVF, sure, but I doubt that's true of either g95 or gfortran.
And gfortran at least (and I suspect g95 as well) has serious issues
dealing with the cdecl/stdcall divide in win32.

Craig Powers

unread,
May 4, 2009, 1:40:28 PM5/4/09
to
Clive Page wrote:
>
> This can be linked using g95 or gfortran on Windows-XP using a command
> like this:
> >g95 testkbd.f90 -Wl,--subsystem,console -lGrWin -mwindows -lg2c
>
> I have no idea what the switch "-Wl,--subsystem,console" is doing, it is
> just a bit of magic I found in the GrWin files. If anyone understands
> it, please post.

The "-Wl," part is telling it to pass an option through to the linker.
The "--subsystem,console" part is the the linker option, it's telling
the linker to build a console application, i.e. one that gets its own
console when the program starts (and, on the C side, starts with "int
main"). The alternative, I believe, is Win32, which does not start out
with a console and also has a different entry point (WinMain).

user1

unread,
May 4, 2009, 2:08:46 PM5/4/09
to

In which case you would check for a WM_CHAR message in your message
processing loop ...

dpb

unread,
May 4, 2009, 2:49:19 PM5/4/09
to

But a console app doesn't have a message processing loop (in the Windows
sense, the app may be written to be input driven, but that's not the
same thing, of course)--and the keystrokes would be sent to the active
window, not a console.

The result would be that a "standard" Fortran app using stdio and
READ(*,... wouldn't ever "see" the keystroke unless processing the
console connected to the app. The making of which console is the point
of the system linker switch.

I've never tried to see if could hack around it, but a quick perusal
doesn't indicate any (at least straightforward) way for the Win32 user
input keyboard APIs to connect to an open console handle.

--


David Duffy

unread,
May 4, 2009, 6:15:13 PM5/4/09
to

Not recent, but the curses library reads the terminfo database to find
out how to do this for your terminal and OS. There is an old shareware
library (Fortran 77) fcurses, which among other things includes a
demonstration popup calculator (reads function keys, numeric keypad
etc). The curses library has:

getch(3NCURSES)

NAME
getch, wgetch, mvgetch, mvwgetch, ungetch, has_key - get (or push back)
characters from curses terminal

so this could probably be called directly using the Fortran 2003 FFI.

Cheers, David Duffy.

GaryScott

unread,
May 4, 2009, 7:25:37 PM5/4/09
to
On May 4, 1:49 pm, dpb <n...@non.net> wrote:
> user1 wrote:
> > dpb wrote:
> >> Clive Page wrote:
> >> ...
> >>> That's sounds a good explanation.  But I still don't quite know why
> >>> this is needed for the single keystroke routine to work.
> >> ...
> >> Because w/o a console there's not a keyboard input only a Windows
> >> messages queue created.
>
> > In which case you would check for a WM_CHAR message in your message
> > processing loop ...
>
> But a console app doesn't have a message processing loop (in the Windows
> sense, the app may be written to be input driven, but that's not the
> same thing, of course)--and the keystrokes would be sent to the active
> window, not a console.

Actually it does have a normal message processing loop, its just
hidden from you. But you can snoop on it. A console app isn't really
any different, it's just a special "window" (made ugly) with some
"convenience features". You can even have hybrid console/"win32" apps
if you want.

> snip
> --

Jugoslav Dujic

unread,
May 5, 2009, 3:51:09 AM5/5/09
to
GaryScott wrote:
> On May 4, 1:49 pm, dpb <n...@non.net> wrote:
>> user1 wrote:
>>> dpb wrote:
>>>> Clive Page wrote:
>>>> ...
>>>>> That's sounds a good explanation. But I still don't quite know why
>>>>> this is needed for the single keystroke routine to work.
>>>> ...
>>>> Because w/o a console there's not a keyboard input only a Windows
>>>> messages queue created.
>>> In which case you would check for a WM_CHAR message in your message
>>> processing loop ...
>> But a console app doesn't have a message processing loop (in the Windows
>> sense, the app may be written to be input driven, but that's not the
>> same thing, of course)--and the keystrokes would be sent to the active
>> window, not a console.
>
> Actually it does have a normal message processing loop, its just
> hidden from you. But you can snoop on it.

Not that I know of <way of snooping into it>, short of writing a
kernel-mode application. As far as I know (and I claim to be
well-versed on the subject of Windows inner workings), it's buried
somewhere deep into the system innards, to the point of
inaccessibility.

--
Jugoslav
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.

John

unread,
May 5, 2009, 6:37:33 AM5/5/09
to

I have a C routine similar in limitations to some of the ones
mentioned; but it is different enough
to mention; plus I have used it over the years on at least 20 Unix and
GNU/Linux systems, including
CygWin on MSWindows platforms. It used to need tweeked a lot; put I
don't think I've had to change
it since the mid-90s (put except for via CygWin, I have never tried
this on an MSWindows machine -- if anyone
has one and tries the routine, I'd be interested in knowing the
results -- is ioctl(3c) supported? ).

The routine is at
http://home.comcast.net/~urbanjost/CLONE/GETKEY/getkey.html

James

unread,
May 5, 2009, 10:26:48 AM5/5/09
to
On windows, CVF has some built-in functions that work for console mode
applications.
I would guess that IVF has something similar.

Here is code for the INKEY routine. Not sure where I got this exactly,
probably
from the CVF forum or this newgroup:

subroutine inkey(a,ii)
use dflib
character*1 a(2)
logical pressed
pressed = PEEKCHARQQ()
if(pressed) then
ii = 1
a(1) = getcharqq()
kk = ichar(a(1))
if(kk.eq.0 .or. kk.eq.14*16) then
a(1) = char(0)
a(2) = getcharqq()
end if
else
ii = 0
end if

return
end


The subroutine returns ii = 0 if there is no keystroke in the queue, 1
if something is available.
When something is there, a(1) returns the ascii code of the
keystroke, if a(1) is 0, then
the keystroke is a special key (cursor key, end key, home key etc),
and the key code is returned
in a(2).

Here's some sample code where I used this:

C
C-----------
C
C GET A KEYSTROKE FROM THE USER
C
1000 CALL INKEY(KEY,II)
IF(II.EQ.0) GOTO 1000
C
C MAKE A <CR> ACT LIKE <CURSOR DOWN>
C
1500 IF(KEY(1).EQ.CHAR(13)) THEN
KEY(1)=CHAR(0)
KEY(2)=CHAR(80)
END IF
IF(KEY(1).NE.CHAR(0)) GOTO 3000
C
C-----------
C
C THE USER HIT A "SPECIAL" KEY
C
C IF USER HIT <F1> SET ALL ELEVATIONS TO DEFAULT
C
IF(KEY(2).EQ.CHAR(59)) THEN
DO 1050 I=1,19
EL(I)=EGUIDE(I,IW)
1050 CONTINUE
GOTO 5
END IF
C
C IF USER HIT <F2> SET CURRENTLY HIGHLIGHTED ELEVATION TO DEFAULT
C
IF(KEY(2).EQ.CHAR(60)) THEN
IF(IOLD.GT.19) GOTO 1000
EL(IOLD) = EGUIDE(IOLD,IW)
GOTO 2000
END IF
C
C CHECK FOR <END>
C
IF(KEY(2).EQ.CHAR(79)) THEN
WRITE(14,REC=IWEEK) EL,FLOW,PADEL
CLOSE(14)
RETURN
END IF
C
C CHECK FOR <CURSOR UP>
C
IF(KEY(2).EQ.CHAR(72)) THEN
INEW = IOLD - 1
IF(IFLOW.EQ.1) THEN
IF(IOLD.EQ.1) INEW = 10
IF(IOLD.EQ.11) INEW = 19
ELSE
IF(IOLD.EQ.62) INEW = 19
IF(IOLD.EQ.1) INEW = 62
IF(IOLD.EQ.20) INEW = 40
IF(IOLD.EQ.41) INEW = 61
END IF
GOTO 2000
END IF

GaryScott

unread,
May 5, 2009, 12:06:12 PM5/5/09
to

It is quite easy to use the following to get the window handle:

handle = findwindowex(null,null,"ConsoleWindowClass"//char(0),null)

From there, you can inquire and manipulate console windows if you are
knowledgable and careful. If you open a console application, the
handle that it returns will be that of the current application. I
have used peekmessage to query such things as function key values in
the distant past.


>
> --
> Jugoslavwww.xeffort.com


> Please reply to the newsgroup.

> You can find my real e-mail on my home page above.- Hide quoted text -
>
> - Show quoted text -

Jugoslav Dujic

unread,
May 6, 2009, 3:32:00 AM5/6/09
to

Then, please, show me how. This does not work:

program Getch
use ifwin
implicit none

integer(HANDLE):: h
type(T_MSG):: msg
integer:: iret

h = FindWindowEx(null,null,"ConsoleWindowClass"//char(0),null)
iret = GetMessage(msg, h, 0, 0)
if (msg%message.eq.WM_KEYDOWN) &
write(*,*) "You pressed ", char(msg%wParam)

end program Getch

Window handle is returned indeed (as expected), but GetMessage does
not work for any combination of parameters (h or NULL; 0 or WM_KEYDOWN
for messsage filtering); the program only sits in there forever. That
suggests that a /subsystem:console application does not have a regular
message queue, and that you cannot peek into it like for a regular
/subsystem:windows application. I admit I haven't tried a message
hook (SetWindowsHookEx(WH_KEYBOARD or WH_KEYBOARD_LL)).

--
Jugoslav

user1

unread,
May 6, 2009, 6:46:58 AM5/6/09
to
GaryScott wrote:

> It is quite easy to use the following to get the window handle:
>
> handle = findwindowex(null,null,"ConsoleWindowClass"//char(0),null)
>
> From there, you can inquire and manipulate console windows if you are
> knowledgable and careful. If you open a console application, the
> handle that it returns will be that of the current application. I
> have used peekmessage to query such things as function key values in
> the distant past.
>
>

I've been tinkering a little. Google of "hwnd console" and first hit has
example code of how to get the handle to the console window. That part
was easy.

I haven't has much luck yet with PeekMessage. I guess I agree with
Jugoslav - it would be nice to see an example if you can dig one up.

dpb

unread,
May 6, 2009, 10:17:58 AM5/6/09
to
Jugoslav Dujic wrote:
...

> program Getch
> use ifwin
> implicit none
>
> integer(HANDLE):: h
> type(T_MSG):: msg
> integer:: iret
>
> h = FindWindowEx(null,null,"ConsoleWindowClass"//char(0),null)
> iret = GetMessage(msg, h, 0, 0)
> if (msg%message.eq.WM_KEYDOWN) &
> write(*,*) "You pressed ", char(msg%wParam)
>
> end program Getch
>
> Window handle is returned indeed (as expected), but GetMessage does
> not work for any combination of parameters (h or NULL; 0 or WM_KEYDOWN
> for messsage filtering); the program only sits in there forever. That
> suggests that a /subsystem:console application does not have a regular
> message queue, and that you cannot peek into it like for a regular
> /subsystem:windows application. I admit I haven't tried a message
> hook (SetWindowsHookEx(WH_KEYBOARD or WH_KEYBOARD_LL)).
...
That's what I would have expected from my reading of the SDK documentation.

I don't have time right now, as I have a 10AM meeting and aren't ready
but I think the appropriate routines to write a getch() routine for
console are

GetStdHandle()

and the low-level console routines

ReadConsoleInput
Reads and removes input records from an input buffer. The function
does not return until at least one record is available to be read. Then
all available records are transferred to the buffer of the calling
process until either no more records are available or the specified
number of records has been read. Unread records remain in the input
buffer for the next read operation. The function reports the total
number of records that have been read. For an example that uses
ReadConsoleInput, see Reading Input Buffer Events.

PeekConsoleInput
Reads without removing the pending input records in an input buffer.
All available records up to the specified number are copied into the
buffer of the calling process. If no records are available, the function
returns immediately. The function reports the total number of records
that have been read.


There _may_ be a way to get at the windows message queue that handles
the console window default menu functions but afaict it's not in the MS
scheme of things to do so; it's buried so deeply in the bowels that
unless the application is actually built as a Windows app it may as well
be said the windows message pump doesn't exist.

Again, imo, $0.02, etc., etc., ... and I'm willing like you to "be
showed somethin' different..." :)

--

Jugoslav Dujic

unread,
May 6, 2009, 10:41:39 AM5/6/09
to
dpb wrote:
> Jugoslav Dujic wrote: ...

>> Window handle is returned indeed (as expected), but GetMessage does
>> not work for any combination of parameters (h or NULL; 0 or
>> WM_KEYDOWN for messsage filtering); the program only sits in there
>> forever. That suggests that a /subsystem:console application does
>> not have a regular message queue, and that you cannot peek into it
>> like for a regular /subsystem:windows application. I admit I
>> haven't tried a message hook (SetWindowsHookEx(WH_KEYBOARD or
>> WH_KEYBOARD_LL)).
> ... That's what I would have expected from my reading of the SDK
> documentation.
>
> I don't have time right now, as I have a 10AM meeting and aren't
> ready but I think the appropriate routines to write a getch() routine
> for console are
>
> GetStdHandle()
>
> and the low-level console routines
>
> ReadConsoleInput PeekConsoleInput

Amen. Indeed they are, and I betcha that actual getch()/GETCHARQQ
end up calling them. Actually, how did this entire subthread
start, and what's its point, except that Gary and I try to outsmart
each other, and earn "Im-right-and-youre-wrong" scorepoints ? :P

GaryScott

unread,
May 6, 2009, 12:32:16 PM5/6/09
to

:) I do indeed have a very old procedure that used peekmessage. It no
longer works. My more recent EZCONSOLE application uses
readconsoleinput as indicated by dpb. If you only need text
characters, you can do that with READCONSOLE (much easier than
readconsoleinput). setconsolemode(inputhandle,0) to disable return
key requirement if you want to read each keystroke.

>
> --
> Jugoslavwww.xeffort.com


> Please reply to the newsgroup.

user1

unread,
May 6, 2009, 12:42:40 PM5/6/09
to
Jugoslav Dujic wrote:

[snip]

> Amen. Indeed they are, and I betcha that actual getch()/GETCHARQQ
> end up calling them. Actually, how did this entire subthread
> start, and what's its point, except that Gary and I try to outsmart
> each other, and earn "Im-right-and-youre-wrong" scorepoints ? :P


Thread drift ? Yeah, I guess I am partly responsible for that. I don't
think the OP ever actually said that he was using Windows.

Still, how to use the Windows API to get a single keystroke in a console
app, with out requiring user to hit return key, is something I find
potentially useful. The topic has come up here before, along with the
typical there-is-no-portable-way-to-do-it responses.


dpb

unread,
May 6, 2009, 2:52:27 PM5/6/09
to
GaryScott wrote:
...
> ... If you only need text characters, you can do that with

> READCONSOLE (much easier than readconsoleinput).
> setconsolemode(inputhandle,0) to disable return key requirement if
> you want to read each keystroke.

This still stalls if no character, though, right??? Or is there some
other place to set that characteristic or does ReadConsole() return
error if no character waiting? (The latter doesn't seem to be
documented afaict and again I'm dashing between other commitments w/ no
time to play...)

> SetConsoleMode
> ...
> Value
> ENABLE_LINE_INPUT
>
> The ReadFile or ReadConsole function returns only when a carriage
> return character is read. If this mode is disabled, the functions
> return when one or more characters are available.

The last phrase implies it waits???

(So still to wrap it w/ a PeekSomething or other query if want a
non-stalling getch() is my point/question/comment. Of course, maybe C
getch() does, too, I don't recall otomh????)

--

GaryScott

unread,
May 6, 2009, 4:54:44 PM5/6/09
to
Yes readconsole waits for a character. If you're using CVF/IVF, then
the combination of peekcharqq and getcharqq can be used for reading a
character without waiting (peekcharqq just checks to see if a
character is present, then you call getcharqq). To use the API
method, you may need to use peekconsoleinput. There is no peekconsole
that I can find, so I'd recommend writing your own generic one,
isolate the peekconsoleinput part into a compiler-specific module.

dpb

unread,
May 6, 2009, 4:59:46 PM5/6/09
to
GaryScott wrote:
...
> ... If you're using CVF/IVF, then
> the combination of peekcharqq and getcharqq can be used ...

Yes, I'm a CVF devotee which is why I've never had do more than read the
SKD for this particular function... :)

--

David Duffy

unread,
May 7, 2009, 12:29:11 AM5/7/09
to
David Duffy <dav...@orpheus.qimr.edu.au> wrote:
> nuclear...@gmail.com wrote:
>> I've been searching around the message board for information on a "Get
>> Key" function for Fortran - the ability to have a program read input
> Not recent, but the curses library reads the terminfo database to find
> getch(3NCURSES)

> so this could probably be called directly using the Fortran 2003 FFI.

Actually, the PDCurses library seems to work quite nicely with Fortran
(g95 and gfortran) on both Windows (in the console) and X11 (using their
XCurses library). Specifically, wgetch (since getch is implemented as a
macro "to avoid conflict with many DOS compiler's runtime libraries")
can be called to get and/or await a keypress. Writing to standard
output in the Windows console occurs at the location of cursor
after the move() command too.

Cheers, David Duffy.
--
| David Duffy (MBBS PhD) ,-_|\
| email: dav...@qimr.edu.au ph: INT+61+7+3362-0217 fax: -0101 / *
| Epidemiology Unit, Queensland Institute of Medical Research \_,-._/
| 300 Herston Rd, Brisbane, Queensland 4029, Australia GPG 4D0B994A v

nuclear...@gmail.com

unread,
May 7, 2009, 12:45:34 AM5/7/09
to
Thank you all for your comments so far. Just to clarify, I am using
this on Windows XP/Vista, and these are the only platforms that this
get key function has to work for (at least for my purposes), so
portability is not a huge issue.

I've played around with the GETCHARQQ() and PEEKCHARQQ() functions in
CVF that I have at work, and they work perfectly for what I'm doing,
but I'm using G95 at home, where I need to compile this program.

I'm not an expert with Fortran by any means, so I'm sorry if I've
confused some of what's been said here previously, but it seems like
all I need is something like the aforementioned READCONSOLE command.
Is this something I can do using g95?

Terence

unread,
May 7, 2009, 2:35:58 AM5/7/09
to

nuclear.wing...@gmail.com wrote:
> I've been searching around the message board for information on a "Get
> Key" function for Fortran - the ability to have a program read input

> from a keyboard without having to push enter - and I've found a few
> posts that explain the difficulty of this. However, the posts I could
> find were at least a decade old, some older than that.
>
> Have there been any recent developments (or tricks) that would allow
> for input that doesn't require pressing the return key? If it helps,
> I'm using g95.
>

> Thanks!

This is how I do it using DVF. It uses the non-standard PEEK function.
The function waits for a key if IWAIT equals zero, and tests for a key
if IWAIT is not zero.
A zero word return means no key had been pressed.
This is part of the freely-available TUI screen and keyboard controls
function set.

The use of integer*2 is to accomodate the two bytes returned; the high
order byte is the key number; the lower order byte is the value of the
key symbol.
If the low order byte is #00 or #E0, the high order byte indicates a
function or pad key.
All is as per the standard MSDOS key and symbol assigment...

INTEGER*2 FUNCTION SCR_INPUTC(IWAIT)
! tests or waits for any keystroke, returns key code or zero
USE DFWIN
! GETS OR WAITS NEXT INPUT CHARACTER
IMPLICIT NONE
INTEGER*2,INTENT(IN) :: IWAIT
! KERN32 FUNCTIONS ICHAR,PEEKCHARQQ,GETCHARQQ
INTEGER*2 :: ICHAR
LOGICAL*4 :: PEEKCHARQQ
CHARACTER*1 :: GETCHARQQ
IF (IWAIT.NE.0) THEN
! TEST KEY
SCR_INPUTC=0
IF (.NOT.PEEKCHARQQ()) RETURN
END IF
! WAIT ON KEY
SCR_INPUTC=ICHAR(GETCHARQQ())
IF (SCR_INPUTC.EQ.#E0) SCR_INPUTC=0
IF (SCR_INPUTC.EQ.0) SCR_INPUTC=ISHFT(ICHAR(GETCHARQQ()),8)
END FUNCTION SCR_INPUTC

dpb

unread,
May 7, 2009, 8:42:11 AM5/7/09
to

There you're out of my cognizance but I'm sure somebody will chime in...

I've seen notes before that there may be "issues" w/ getting g95 to
generate proper calling sequence for the Win32 API so you'll need a way
around that.

--

Craig Powers

unread,
May 7, 2009, 1:53:54 PM5/7/09
to

In order to be safe, it's probably best to write a cdecl C wrapper
function that calls the Windows API function. You can use bind(c) on
the wrapper function without any issues, and C knows how to handle
stdcall at least semi-consistently.

James Van Buskirk

unread,
May 7, 2009, 2:09:07 PM5/7/09
to
"dpb" <no...@non.net> wrote in message news:gtul3r$rc6$2...@aioe.org...

> I've seen notes before that there may be "issues" w/ getting g95 to
> generate proper calling sequence for the Win32 API so you'll need a way
> around that.

The issue with g95 is that you have to change the calling convention
for the whole application to stdcall just to invoke one procedure
with that convention. The problem with gfortran is more acute in
that it doesn't even let you emit the correctly mangled name of the
procedure you want to call. These problems are only present in 32-
bit Windows but there are other difficulties in 64-bit Windows: g95
doesn't compile to 64-bit Windows and gfortran has difficulty building
a 64-bit Windows compiler. As a consequence there are classes of
bugs that exist on available builds of gfortran for 64-bit Waindows
that are not a problem on other platforms.

Maybe my information above is a little out of date but I haven't
seen any announcements to the contrary.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


dpb

unread,
May 7, 2009, 2:14:38 PM5/7/09
to
Craig Powers wrote:
> dpb wrote:
>> nuclear...@gmail.com wrote:
...

>>> all I need is something like the aforementioned READCONSOLE command.
>>> Is this something I can do using g95?
>>
>> There you're out of my cognizance but I'm sure somebody will chime in...
>>
>> I've seen notes before that there may be "issues" w/ getting g95 to
>> generate proper calling sequence for the Win32 API so you'll need a
>> way around that.
>
> In order to be safe, it's probably best to write a cdecl C wrapper
> function that calls the Windows API function. You can use bind(c) on
> the wrapper function without any issues, and C knows how to handle
> stdcall at least semi-consistently.

Actually, that's closer to what I got to thinking...assuming the
corresponding C runtime has getch(), just write the wrapper function to
link w/ it and let it handle the OS call automagically.

--

David Duffy

unread,
May 12, 2009, 11:24:37 PM5/12/09
to
I have made a module that contains an interface to the PDCurses library
(it should also be compatible with curses/ncurses etc). There are
interfaces to these libraries for some commercial compilers, but this
one works nicely with g95 and gfortran on Linux and Windows, and should
work anywhere else curses has been ported to.

It is not quite finished -- I need to understand how to interface to the
curses equivalents of print and scan, fix up colours and mouse handling
-- but most of the "testcurs" program now works in Fortran.

You can find it at:
http://www.qimr.edu.au/davidD/index.html#misc

Reply all
Reply to author
Forward
0 new messages