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