Re: Esc key

Search this archive.

From: Sergio Masci (sergio@titan.demon.co.uk)
Date: Sun 12 Mar 2000 - 17:41:50 IST


> 
> > > Ok, I'm sure I could figure this one out for myself if I put some time
> > > into it, but I'm also thinking someone (like Russell) has maybe already
> > > solved it.
> > > 
> > > So, in a public display of the languor and apathy that I'm feeling today, 
> > > I'll post my question here.  ;-P
> > > 
> > > When using vga_getch() and vga_getkey(), how do you avoid a value of "27"
> > > applying to more than just the "Esc" key? I know the directional arrows
> > > are "escaped", and so pressing the up arrow sends (at first) the same
> > > signal as the Esc key. This is the same problem as you get with ncurses.
> > > 
> > > So, what's the answer? Can this be done without raw keyboard mode?
> [...]
> > Use vga_getkey() to read the keyboard, if you see an ESC read it again
> > immediately (without waiting). If you get 0 then no other key was
> > pressed and you have an ESC key press, if you get anything else then
> > treat it as an escape sequence.
> 
> In the spirit of "show me the code" :-), there's a working (I hope)
> example of how to do this below (after all my verbiage).

I didn't think my explanation needed any futher clarification which is
why I didn't include any code in this case. I do "show you the code"
when I think its usefull or necessary (check the logs for my posting
on the anti aliased line code and pretty picture).

> BTW, the reason this read-without-waiting works is because Linux dumps
> the whole string generated by the key into your input at once (AFAIK),
> something you can't depend on over network or serial connections. So
> this approach is ok to use with svgalib, but you obviously can't do it
> this way for terminals (which is why ncurses has to wait).
> 
> Another thing to note - since vga_getkey() returns zero for `no key',
> it gives you no way of reading ctrl-space. [1] Admittedly this isn't a
> key you're likely to want to read unless you're writing an svgalib
> driver for Emacs, but...
> 
> (Actually, I was adding a sort of pseudo-compatibility feature to
> $PROGRAM_I_END_UP_MENTIONING_IN_EVERY_POST the other day, and I needed
> ctrl-space for that. But then again, I don't use vga_getkey() there
> (for complicated reasons to do with console switching).)
> 
> [1] Rather like CP/M's direct console I/O BDOS function in fact. But,
> er, I didn't say that honest, I'm not that sad. :-)
> 
> > I forget if you need to explicitly tell SVGALIB to use vga_getkey() as
> > non-blocking. If it does, then you'll need to set it to non-blocking.
> 
> I think svgalib runs in CBREAK mode, and vga_getkey() uses select() to
> avoid blocking.
> 
> > I don't know about this ncurses problem, but this method also works with
> > normal terminals connected to a unix box, you just need to be sure to
> 
> Ummm, for terminals you really ought to wait a bit, rather than
> reading the chars after Esc immediately. If it happens to work without
> waiting, it's only luck and/or buffering. :-) (I know you mentioned
> disabling buffering, but that won't affect a UART - using a multi-byte
> buffering UART like a 16550A might be all that's saving you here.)
> ncurses may wait a stupidly long time (IMHO), but you really should
> wait at least a *short* time. (But as I say, there's no need to wait
> when using svgalib, so I'm veering off-topic.)

I didn't want to go completely off topic and explain the exact line
setting etc but basically you set the line disaplin to have a time out
of about 3 char transmition periods and you short circuit this by a
'minimum number of chars to wait for' to 2. You then issue a read()
requesting a short string (minimum of 2 but could be several chars) and
the read will return a single char for normal keys including ESC and
multiple chars in the case where a function key has been pressed.
read() returns the count of chars read into the buffer. In effect the
programmer sees an ESC+ch without a pause between the two but will still
be using non-blocking non-buffered IO.

I do appriciate that its possible to execute several million machine
instructions between two consequtive received chars on a uart - really
I do, honest :-)

> Anyway, in case actual code might help :-), here's what zgv does. I've
> hacked it to use vga_getkey() here and removed some support for (very)
> old broken keymaps, but other than that, and a slight hack added
> recently to handle more Alt-shifted keys, this is basically from zgv
> 5.0. It handles most (all?) of the keys which are readable without
> using raw mode, and handles both Esc-prefixed meta (Alt) keys and
> `real' ones. (It also maps e.g. Alt-A to Alt-a, but it wouldn't be
> hard to remove that if you wanted.) RK_* as used below can be any
> integers not in the 0..255 range; see zgv's src/readnbkey.h.
> 
> (I've not tested it since the hacking, so YMMV :-))

[...]

> In case you're wondering, Shift-F9..F12 are missing because they don't
> seem to generate anything. And most Ctrl/Alt-shifted `special' keys
> are indistinguishable from unshifted ones (or are used for console
> switching and the like). You also risk losing e.g. multiple presses of
> cursor keys if you wait too long between calls. This is actually
> rather useful in zgv, but could be a pain in some contexts.
> 
> If you need more than the above routine can handle, you probably do
> need raw mode.
> 
> -Rus.

Regards
Sergio

http://www.xcprod.com/titan


This archive was generated by hypermail 2.1.4 : Wed 21 Jan 2004 - 22:10:23 IST