I've been noticing for quite some time that in Linux, input statements and functions are not very complete in graphics mode. Comparing them with what happens in DOS, many key combinations go undetected (for instance, in DOS, HOME and CTRL+HOME return different INKEY values and in Linux, they are the same; F11 and F12 return no INKEY value in Linux, etc.). I've been solving this with MultiKey where necessary and sometimes using #ifdefs. Now, because DOS does not use Unicode, I was assuming that FBGFX simply did not support it and it only worked in console mode.
In console mode, if the UTF-8 string for a certain character is say, A0h, 53h, then InKey will return CHR(&HA0) once and then CHR(&H53). Not together. Forces me to test the high bits of each InKey character, but that's fine. In graphics mode, however, I always get plain ASCII. Key combinations that would generate anything outside ASCII simply go undetected by InKey. Thus, if I type "á" or "Ñ" on my keyboard, I get nothing. Now I tried one thing. I compiled my graphics mode test program for Windows with FBC under Wine and I ran it. It detects all Unicode. No problem.
I would like to (help) fix this, as I understand now this is not supposed to be left like this. By chance, can anybody else confirm the same behaviour on their computer under Linux? Also, does anybody know how can I system-specifically get Unicode input in graphics mode? Thanks!
InKey, Input, etc. in graphics mode with Unicode
Re: InKey, Input, etc. in graphics mode with Unicode
Well, I figured this out myself. In case anybody finds it useful, this:
... is an example of how keys could be read in Linux both as keys being pressed an released (MultiKey) and as Unicode characters being pushed into a buffer (InKey). Of course, the keysyms, which represent the semantic value of individual keys, are entirely different from DOS scan codes and also from their Windows counterpart, called virtual keys, which FreeBasic surely uses to get MultiKey and InKey for that system. I wonder why the same thing was not done for Linux. I'm still scratching my head thinking what could be the fastest way to implement a translation, because there are about 500 keysyms for a standard US international keyboard and I wouldn't like a 500 cycle For to be executed everytime I tap on a key.
In case you are about to say FreeBasic already supports ScreenEvents, the problem with this is that unrecognised key values are lost before they enter FreeBasic EVENT type.
I will keep on working on this, but I would appreciate any thoughts and suggestions, especially from the people who know how this is currently coded in FreeBasic's source (for Linux and Windows, in graphics mode). Thanks.
Code: Select all
#include "fbgfx.bi"
#include "X11/Xlib.bi"
#include "X11/Xutil.bi"
#include "X11/keysymdef.bi"
Dim dis As Display Ptr, w As Window
Dim e As XEvent, sym As KeySym
Dim s As ZString * 26, v As Long
ScreenRes 480, 480
ScreenControl FB.GET_WINDOW_HANDLE, w
dis = XOpenDisplay(0)
XSelectInput (dis, w, KeyPressMask Or KeyReleaseMask)
Do
If XPending(dis) Then
XNextEvent dis, @e
Select Case e.type
Case KeyPress
XLookupString(@e.xkey, @s, 25, @sym, 0)
v = XLookupKeysym(@e.xkey, 0)
If Len(s) Then
If s = Chr(13) Then Print Else Print s;
ElseIf v Then
Print "<" + Hex(v) + ">";
End If
Case KeyRelease
If XLookupKeysym(@e.xkey, 0) = XK_Escape Then Exit Do
End Select
End If
Loop
XCloseDisplay(dis)
In case you are about to say FreeBasic already supports ScreenEvents, the problem with this is that unrecognised key values are lost before they enter FreeBasic EVENT type.
I will keep on working on this, but I would appreciate any thoughts and suggestions, especially from the people who know how this is currently coded in FreeBasic's source (for Linux and Windows, in graphics mode). Thanks.
Re: InKey, Input, etc. in graphics mode with Unicode
Hi,
generally speaking, I don't think Inkey/Getkey/ScreenEvent can support Unicode. For example, Inkey/Getkey are defined to return an ASCII code or FB extended keycode, so they can't suddenly start returning Unicode values. And the main goal of ScreenEvent or MultiKey is to support the FB scancodes, not do perfect Unicode text input as one is used to from GUIs.
UTF8 is for sure the standard on GNU/Linux systems now, but there probably is no guarantee. I wonder about what guarantees XLookupString() makes in this regard. And in your Windows test, are you sure it was Unicode, or just your Windows codepage?
There is some documentation about this stuff here: Keyboard input: inkey(), multikey(), etc.
For X11 specifically, look here: src/gfxlib2/unix/gfx_x11.c(243): X11 KeyPress event handling
src/rtlib/unix/scancodes_x11.c(120): X11 to FB scancode table
For Linux console input, an important detail is that it's based on receiving ANSI escape sequences from the terminal [emulator] via stdin. FB doesn't handle the codes for F11 and F12 (see src/rtlib/unix/io_inkey.c(29)), that's why they are not recognized. (tested in Linux tty, because terminal emulators tend to bind F1 to help, F11 to full screen, etc.) If we can find out what termcap codes should be used to get the escape sequence for F11 and F12, they could be supported. What extended key code will FB-win32 return for F11/F12 (it's not decipherable from the FB rtlib source code as far as I can tell)?
generally speaking, I don't think Inkey/Getkey/ScreenEvent can support Unicode. For example, Inkey/Getkey are defined to return an ASCII code or FB extended keycode, so they can't suddenly start returning Unicode values. And the main goal of ScreenEvent or MultiKey is to support the FB scancodes, not do perfect Unicode text input as one is used to from GUIs.
UTF8 is for sure the standard on GNU/Linux systems now, but there probably is no guarantee. I wonder about what guarantees XLookupString() makes in this regard. And in your Windows test, are you sure it was Unicode, or just your Windows codepage?
There is some documentation about this stuff here: Keyboard input: inkey(), multikey(), etc.
For X11 specifically, look here: src/gfxlib2/unix/gfx_x11.c(243): X11 KeyPress event handling
src/rtlib/unix/scancodes_x11.c(120): X11 to FB scancode table
For Linux console input, an important detail is that it's based on receiving ANSI escape sequences from the terminal [emulator] via stdin. FB doesn't handle the codes for F11 and F12 (see src/rtlib/unix/io_inkey.c(29)), that's why they are not recognized. (tested in Linux tty, because terminal emulators tend to bind F1 to help, F11 to full screen, etc.) If we can find out what termcap codes should be used to get the escape sequence for F11 and F12, they could be supported. What extended key code will FB-win32 return for F11/F12 (it's not decipherable from the FB rtlib source code as far as I can tell)?
Re: InKey, Input, etc. in graphics mode with Unicode
Thanks for your reply, dkl. I'm answering without having checked the links yet. I will. Just want to give you some info. It's a little long, but probably useful.
I'm aware that the Linux console is another story. Even "text mode" output to the console goes through ANSI stdout. I will research there too, but I'm more interested in solving it for GUI first, because in console mode, one usually is less interested in handling special keys and more interested in... well, console stuff.
Honestly, I'm not sure about the extent to which the keys returned by Windows emulation via Wine (through InKey) and by X in pure Linux (using the procedure I posted) stick to Unicode. What I can tell you is this: all the keys I was able to press that produced characters in both cases returned the same byte combinations and I was able to verify that these character combinations coincided with those in Latin-1, which is part of Unicode. My keyboard is set up for US International and for Russian. When I use the Russian layout, also, the key values coincide in both cases and the values are consistent with Unicode in UTF-8. This is about character codepoints.
Now, about scan codes, they are all different. DOS returns scan codes that it receives directly from the BIOS, that gets them directly from the keyboard. If an ASCII value is given, both QB and FB return that ASCII value. If ASCII from BIOS is zero, then QB returns CHR$(0) + CHR(n) where "n" is the "make" scan code. FB returns Chr(255, n), with the same scan codes, plus some additional ones not supported by QB. In Linux and Windows, I realise FB translates virtual keys (from Windows) or keysyms (from Linux X) into scan codes that are used both for MultiKey and InKey. The translation for Windows is very good. The translation for Linux lacks many keys and fails to recognise the shift status (Ctrl, Alt, Shift) when applied to scan code based keys. Keysyms are completely different from virtual keys, and both are completely different from scan codes. I have the tables.
Alright... now I'll go and check the links :)
EDIT: Checked the links. Very, very useful. It seems original scan codes can actually be obtained from within X11. It also looks like, instead of using a 256 cycle For, FB uses a large map to translate the keys. This is a lot faster. In graphics mode, MultiKey works very well. Only problem with it is that is cannot tell a keypad key from an extended key, or left Ctrl from right Ctrl, for example. InKey is the one that is drastically different from its Windows counterpart. I'll research more on how InKey works under X11 and I'll sketch a fully commented potential fix.
I'm aware that the Linux console is another story. Even "text mode" output to the console goes through ANSI stdout. I will research there too, but I'm more interested in solving it for GUI first, because in console mode, one usually is less interested in handling special keys and more interested in... well, console stuff.
Honestly, I'm not sure about the extent to which the keys returned by Windows emulation via Wine (through InKey) and by X in pure Linux (using the procedure I posted) stick to Unicode. What I can tell you is this: all the keys I was able to press that produced characters in both cases returned the same byte combinations and I was able to verify that these character combinations coincided with those in Latin-1, which is part of Unicode. My keyboard is set up for US International and for Russian. When I use the Russian layout, also, the key values coincide in both cases and the values are consistent with Unicode in UTF-8. This is about character codepoints.
Now, about scan codes, they are all different. DOS returns scan codes that it receives directly from the BIOS, that gets them directly from the keyboard. If an ASCII value is given, both QB and FB return that ASCII value. If ASCII from BIOS is zero, then QB returns CHR$(0) + CHR(n) where "n" is the "make" scan code. FB returns Chr(255, n), with the same scan codes, plus some additional ones not supported by QB. In Linux and Windows, I realise FB translates virtual keys (from Windows) or keysyms (from Linux X) into scan codes that are used both for MultiKey and InKey. The translation for Windows is very good. The translation for Linux lacks many keys and fails to recognise the shift status (Ctrl, Alt, Shift) when applied to scan code based keys. Keysyms are completely different from virtual keys, and both are completely different from scan codes. I have the tables.
Alright... now I'll go and check the links :)
EDIT: Checked the links. Very, very useful. It seems original scan codes can actually be obtained from within X11. It also looks like, instead of using a 256 cycle For, FB uses a large map to translate the keys. This is a lot faster. In graphics mode, MultiKey works very well. Only problem with it is that is cannot tell a keypad key from an extended key, or left Ctrl from right Ctrl, for example. InKey is the one that is drastically different from its Windows counterpart. I'll research more on how InKey works under X11 and I'll sketch a fully commented potential fix.