[comp.sys.atari.st.tech] Getting ASCII value from scancode

heavy@zip.eecs.umich.edu (Richard Scott Hall) (04/27/91)

I am having a problem.  It is quite easy to get the scancode
for a key being pressed (by using evnt_keybd/envt_multi), but
it is a little harder if you just want the ASCII value.  For
instance:  

   it is possible to press any ALT+<key> sequence in my program.
   When I get a keyboard event, I get the keyboard state from
   vq_key_s() (i.e. shift/control/alt), but I get the scancode
   from evnt_keybd/multi.  So i guess what I am asking, is there
   anyway to go from scancode to ASCII without having to define
   all the values in my program?

Richard Hall
University of Michigan
-- 

Standard disclaimer:  I am not me, I am who you think you are...
                      so don't blame me.

rcb@netcom.COM (Roy Bixler) (04/27/91)

In article <1991Apr26.232519.12216@zip.eecs.umich.edu> heavy@zip.eecs.umich.edu (Richard Scott Hall) writes:
>I am having a problem.  It is quite easy to get the scancode
>for a key being pressed (by using evnt_keybd/envt_multi), but
>it is a little harder if you just want the ASCII value.  For
>instance:  
>
>   it is possible to press any ALT+<key> sequence in my program.
>   When I get a keyboard event, I get the keyboard state from
>   vq_key_s() (i.e. shift/control/alt), but I get the scancode
>   from evnt_keybd/multi.  So i guess what I am asking, is there
>   anyway to go from scancode to ASCII without having to define
>   all the values in my program?

When you press 'normal' keys (without ALT), the ASCII code is in the
least significant byte of the scan-code.  With ALT, the least
significant byte is 0.  So, it looks like getting the ASCII would
involve a table which maps the most significant byte of the scan-code
to ASCII.  Unfortunately, this scan-code byte is based on the QWERTY
positioning of the keys.

It's true that it would be nice if the non-ASCII code for ALT keys
were, say, the same least significant 7 bits (as the corresponding
ASCII character) with the 8'th bit set, but ...  After all, why make
it hard on the people who write typing tutors?

>
>Richard Hall
>University of Michigan
>-- 
>
>Standard disclaimer:  I am not me, I am who you think you are...
>                      so don't blame me.


-- 
Roy Bixler
rcb@netcom.com -or- (UUCP) uunet!apple!netcom!rcb
"Just when you think you know it all, it changes!"

harryk@bucsf.bu.edu (Harry Karayiannis) (04/27/91)

In article <1991Apr26.232519.12216@zip.eecs.umich.edu> heavy@zip.eecs.umich.edu (Richard Scott Hall) writes:
>I am having a problem.  It is quite easy to get the scancode
>for a key being pressed (by using evnt_keybd/envt_multi), but
>it is a little harder if you just want the ASCII value.  For
>instance:  
>
>   it is possible to press any ALT+<key> sequence in my program.
>   When I get a keyboard event, I get the keyboard state from
>   vq_key_s() (i.e. shift/control/alt), but I get the scancode
>   from evnt_keybd/multi.  So i guess what I am asking, is there
>   anyway to go from scancode to ASCII without having to define
>   all the values in my program?
>
>Richard Hall
>University of Michigan
>-- 
>
>Standard disclaimer:  I am not me, I am who you think you are...
>                      so don't blame me.



	You should use evnt_keybd() which returns an integer.

	Now, the high-order byte contains the scan code of the key pressed,
	and the low-order byte contains the ASCII code.



===============================================================================
			     Harry Karayiannis          Post:
      ||   |#   ||					  15 N.Beacon, #316
     |#|  ||#|  |#|	     Boston University		  Allston, MA 02134
     |#|  ||#|  |#|	     Computer Science Dpt.	  U.S.A.
    |##|  ||#|  |##|				        _______________________
    ||#|  ||#|  ||#|				       |INTERnet:
   ////   ||||   \\\\	     % fortune -o	       |  harryk@bucsf.bu.edu
 /////    ||||    \\\\\	     "Hackers do it with       |BITnet:
///// ATARI ST     \\\\\      fewer instructions"      |  cscrzcc@buacca.bu.edu
=======================================================|_______________________

heavy@zip.eecs.umich.edu (Richard Scott Hall) (04/28/91)

In article <80354@bu.edu.bu.edu> harryk@bucsf.bu.edu (Harry Karayiannis) writes:
>In article <1991Apr26.232519.12216@zip.eecs.umich.edu> heavy@zip.eecs.umich.edu (Richard Scott Hall) writes:
>>
>>   it is possible to press any ALT+<key> sequence in my program.
>>   When I get a keyboard event, I get the keyboard state from
>>   vq_key_s() (i.e. shift/control/alt), but I get the scancode
>>   from evnt_keybd/multi.  So i guess what I am asking, is there
>>   anyway to go from scancode to ASCII without having to define
>>   all the values in my program?
>>
>>Richard Hall
>>University of Michigan
>
>	You should use evnt_keybd() which returns an integer.
>
>	Now, the high-order byte contains the scan code of the key pressed,
>	and the low-order byte contains the ASCII code.
>

Yes, it does, but not if someone presses 'ATL+A'.  The low order
bits in this case are zero.  I want to be able to see that they
pressed 'A' while holding down 'ATL'.  I can get the keyboard
state with vq_key_s() (this tells me if they are holding down
shift/control/alt), but what I need to know now is what ASCII
key they pressed with it.  So if I can get some method to find
this out, I won'd need some big if-then-else-if structure to
key for a specific value...for instance, 'ATL+A' = 0x1e00,
'ATL+B' = 0x3000.  Now the only what I know which ASCII key
they pressed is by having some code like:

     if (key == 0x1e00)
        c = 'A';
     else if (key == 0x3000)
        c = 'B';
     .
     .
     .

     ad infinitum

I don't really want to do this, but it might be necessary.

Richard Hall
University of Michigan

-- 

Standard disclaimer:  I am not me, I am who you think you are...
                      so don't blame me.

dbrooks@osf.osf.org (David Brooks) (04/29/91)

heavy@zip.eecs.umich.edu (Richard Scott Hall) writes:
>>>   is there
>>>   anyway to go from scancode to ASCII without having to define
>>>   all the values in my program?
>>
>>	You should use evnt_keybd() which returns an integer.
>>
>>	Now, the high-order byte contains the scan code of the key pressed,
>>	and the low-order byte contains the ASCII code.
>
>Yes, it does, but not if someone presses 'ATL+A'.  The low order
>bits in this case are zero.

Right.  Unfortunately, the low-order bytes are zero in lots of other cases:
function keys and cursor keys, to name two.

Here's what I do when I see a null byte.  First, kbshift(-1) & 8 tells me
if ALT is depressed.  Now you take the scancode and look it up again in the
key mapping table.  The address of this table is handed to you as the
return value of keytbl(-1L, -1L, -1L), which you need call only once; this
points to a vector of pointers to the unshift, shift and capslock tables
(each 128 bytes indexed by scancode).

Now all you have to do is undo the GSX nonsense -- hello?  Are you still
there? -- best to experiment with values between '1' and '='; I get
terribly confused at this point.

-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
Donnie Wahlberg is brought to you by three billion years of evolution.

dbrooks@osf.osf.org (David Brooks) (04/29/91)

entropy@gnu.ai.mit.edu (entropy) writes:
>Could you maybe give a hunk of code using the methods you described?

Pleasure.  In startup:

  char **keytb;
  char *ktunshift, *ktshift;

  keytp = (char **)Keytbl(-1L, -1L, -1L);
/* Setting [2] to same as [0] forces capslock to be ignored... */
  ktunshift = keytp[2] = keytp[0];
  ktshift = keytp[1];

...

/* Now, if you have the scancode right justified in int scode... */

  shifts = Getshift();		/* i.e. kbshift(-1);

  if (shifts & 8) {		/* ALT */

    if (scode >= 0x78)		/* Allan Pratt explained this once, but... */
/* GSX correction: */
      scode -= 0x76;

/* This code ignores the capslock key.  Use shifts & 0x10 to look at it. */
    ch = ((shifts & 3)?ktshift:ktunshift)[scode];

    if (shifts & 4)		/* CTRL */
      ch &= 0x1f;

    if (using_full_8_bits)
      ch |= 0x80;
    else
      emit('\033');		/* Use esc-char as alias for 8th bit */
  }

  emit(ch);
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
Donnie Wahlberg is brought to you by three billion years of evolution.

csbrod@immd4.informatik.uni-erlangen.de (Claus Brod) (04/29/91)

dbrooks@osf.osf.org (David Brooks) writes:

>entropy@gnu.ai.mit.edu (entropy) writes:
>/* Now, if you have the scancode right justified in int scode... */

>  shifts = Getshift();		/* i.e. kbshift(-1);

You don't have to call kbshift; the keyboard status is returned in one of
the evnt_multi return parameters. Use this value instead of the kbshift
value to be sure to get a consistent view of the things going on at the
keyboard and in the AES keyboard buffer.

----------------------------------------------------------------------
Claus Brod, Am Felsenkeller 2,			Things. Take. Time.
D-8772 Marktheidenfeld, West Germany		(Piet Hein)
csbrod@medusa.informatik.uni-erlangen.de
Claus Brod@wue.maus.de
----------------------------------------------------------------------

klamer@mi.eltn.utwente.nl (Klamer Schutte) (04/29/91)

In <1991Apr27.172516.29313@zip.eecs.umich.edu> heavy@zip.eecs.umich.edu (Richard Scott Hall) writes:

>Yes, it does, but not if someone presses 'ATL+A'.  The low order
>bits in this case are zero.  I want to be able to see that they
>pressed 'A' while holding down 'ATL'.  I can get the keyboard
>state with vq_key_s() (this tells me if they are holding down
>shift/control/alt), but what I need to know now is what ASCII
>key they pressed with it.  So if I can get some method to find
>this out, I won'd need some big if-then-else-if structure to
>key for a specific value...for instance, 'ATL+A' = 0x1e00,
>'ATL+B' = 0x3000.  Now the only what I know which ASCII key
>they pressed is by having some code like:

>     if (key == 0x1e00)
>        c = 'A';
>     else if (key == 0x3000)
>        c = 'B';
>     .
>     .
>     .

>     ad infinitum

>I don't really want to do this, but it might be necessary.

How about this code:

/* correct this table to the correct values.				*
 * From your example it seems that position 0x1e should have 'A'	*/
char	alt_to_ascii[256] = { 'a', 'b', 'c', ... };

	if ((key & 0xff) == 0)		/* is the low byte 0? */
		c = alt_to_ascii[key >> 8];
	else
		c = key && 0xff;

Or otherwise:
	switch (key)
	{case 0x1e00:
		c = 'A';
		break;
	case 0x3000:
		c = 'B';
		break;
	.
	.
	.

	ad infinitum

Just some thoughts

Klamer
-- 
Klamer Schutte
Faculty of electrical engineering -- University of Twente, The Netherlands
klamer@mi.eltn.utwente.nl	{backbone}!mcsun!mi.eltn.utwente.nl!klamer

dbrooks@osf.osf.org (David Brooks) (04/29/91)

csbrod@immd4.informatik.uni-erlangen.de (Claus Brod) writes:
>dbrooks@osf.osf.org (David Brooks) writes:
>
>>entropy@gnu.ai.mit.edu (entropy) writes:
>>/* Now, if you have the scancode right justified in int scode... */
>>
>>  shifts = Getshift();		/* i.e. kbshift(-1);
>
>You don't have to call kbshift; the keyboard status is returned in one of
>the evnt_multi return parameters.

True; my code assumes Bconin(), and I had missed the fact that the original
question had referenced evnt_multi().

> Use this value instead of the kbshift
>value to be sure to get a consistent view of the things going on at the
>keyboard and in the AES keyboard buffer.

Yes, there is a window between Bconin() and Kbshift(), but it's an utterly
unimportant one.  There's also a little overhead in the extra BIOS call.
Incidentally, what does evnt_multi() do; does it call Kbshift(), or does it
know where the BIOS stores the current shift bits?  Just wondering.
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
Donnie Wahlberg is brought to you by three billion years of evolution.

bjoern@drdhh.hanse.de (Bjoern Kriews) (05/01/91)

From article <1991Apr26.232519.12216@zip.eecs.umich.edu>, by heavy@zip.eecs.umich.edu (Richard Scott Hall):
> I am having a problem.  It is quite easy to get the scancode
> for a key being pressed (by using evnt_keybd/envt_multi), but
> it is a little harder if you just want the ASCII value.  For

Try key=evnt_keybd() & 0xff.




---
bjoern@drdhh.hanse.de = Bjoern Kriews / Stormsweg 6 / 2000 Hamburg 76 / FRG
"gaaga mahwe Bjoern urgl ufzae Turbo-C bnub"     (J. Willamowius)

csbrod@immd4.informatik.uni-erlangen.de (Claus Brod) (05/02/91)

dbrooks@osf.osf.org (David Brooks) writes:

>> Use this value instead of the kbshift
>>value to be sure to get a consistent view of the things going on at the
>>keyboard and in the AES keyboard buffer.

>Yes, there is a window between Bconin() and Kbshift(), but it's an utterly
>unimportant one.  There's also a little overhead in the extra BIOS call.
>Incidentally, what does evnt_multi() do; does it call Kbshift(), or does it
>know where the BIOS stores the current shift bits?  Just wondering.

evnt_multi does many things, and it even seems to buffer keyboard
events in some manner. Moreover, it's just the recommended method
for sampling the keyboard when using AES functions. Internally,
the AES calls the VDI, and the VDI probably calls BIOS, but nobody
knows exactly what else goes on.

----------------------------------------------------------------------
Claus Brod, Am Felsenkeller 2,			Things. Take. Time.
D-8772 Marktheidenfeld, West Germany		(Piet Hein)
csbrod@medusa.informatik.uni-erlangen.de
Claus Brod@wue.maus.de
----------------------------------------------------------------------