Defining action of CTRL key...

  • Follow


As most of you know, I've been porting UMoria over to BBC BASIC bit by
bit for the last couple of years. I'm now at the point of sorting out
the keyboard input code. The game uses the ESCape key and various CTRL
combinations to perform actions. I've got the ESCape key to behave
using OS_Byte &E5 (229). Is there any way of neutering the CTRL key in
a similar fashion so that it sets a bit, rather than performing any
other action defined by the VDU drivers?

I need to be able to distinguish between uppercase & lowercase as both
are used as CTRL combos.

I seem to remember a way of doing this on the Beeb, though I can't for
the life of me remember what it was.

Your help would be much appreciated.
0
Reply usenet9920 (358) 5/22/2012 3:42:28 PM

In message <4802cf78-e210-4afa-acf0-a751668b03bb@hq4g2000vbb.googlegro 
ups.com>
          Gazza <usenet@garethlock.com> wrote:

> As most of you know, I've been porting UMoria over to BBC BASIC bit by
> bit for the last couple of years. I'm now at the point of sorting out
> the keyboard input code. The game uses the ESCape key and various CTRL
> combinations to perform actions. I've got the ESCape key to behave
> using OS_Byte &E5 (229). Is there any way of neutering the CTRL key in
> a similar fashion so that it sets a bit, rather than performing any
> other action defined by the VDU drivers?

In contrast to Esc, the Ctrl key does not have any associated action, 
so there is no need to suppress it. You can enquire about the state of 
the Ctrl key at any time using OS_Byte 121. Whatever code you use to 
accept keyboard input might do specific things when it sees Ctrl 
keypresses, so in order to answer your question you need to tell us 
how you accept and interpret keyboard input in your program. 
OS_ReadLine, for instance, interprets certain Ctrl keypresses.

-- 
Martin
---------------------------------------------------------------------
Martin Wuerthner         MW Software      http://www.mw-software.com/
        RISC OS Software for Design, Printing and Publishing
---------------------------------------------------------------------
0
Reply spamtrap3075 (2284) 5/22/2012 4:09:48 PM


On May 22, 5:09=A0pm, Martin Wuerthner <spamt...@mw-software.com> wrote:
> In message <4802cf78-e210-4afa-acf0-a751668b0...@hq4g2000vbb.googlegro
> ups.com>
> =A0 =A0 =A0 =A0 =A0 Gazza <use...@garethlock.com> wrote:
>
> > As most of you know, I've been porting UMoria over to BBC BASIC bit by
> > bit for the last couple of years. I'm now at the point of sorting out
> > the keyboard input code. The game uses the ESCape key and various CTRL
> > combinations to perform actions. I've got the ESCape key to behave
> > using OS_Byte &E5 (229). Is there any way of neutering the CTRL key in
> > a similar fashion so that it sets a bit, rather than performing any
> > other action defined by the VDU drivers?
>
> In contrast to Esc, the Ctrl key does not have any associated action,
> so there is no need to suppress it. You can enquire about the state of
> the Ctrl key at any time using OS_Byte 121. Whatever code you use to
> accept keyboard input might do specific things when it sees Ctrl
> keypresses, so in order to answer your question you need to tell us
> how you accept and interpret keyboard input in your program.
> OS_ReadLine, for instance, interprets certain Ctrl keypresses.
>
> --
> Martin
> ---------------------------------------------------------------------
> Martin Wuerthner =A0 =A0 =A0 =A0 MW Software =A0 =A0 =A0http://www.mw-sof=
tware.com/
> =A0 =A0 =A0 =A0 RISC OS Software for Design, Printing and Publishing
> ---------------------------------------------------------------------

Well... I was running a test program that just read from the keyboard
and displayed both the ASCII codes and the character/string
representation on the screen. The idea being I could trap CTRL+<key>
and display the character on the screen, manually prefixed with "^" if
it was part of a CTRL combo. However, I was stumbling across special
cases such as CTRL+U and others which of course do funny things with
the VDU drivers. What I want to do is to intercept this set a flag if
CTRL was pressed and return the ASCII code of just the character
pressed. I'm using GET to return ASCII codes with OS_Byte 229 set to a
non-zero value to supress Escape.

0
Reply usenet9920 (358) 5/22/2012 6:33:59 PM

In message <125e67a9-7565-4a7b-8439-53c951ff140b@l17g2000vbj.googlegro 
ups.com>
          Gazza <usenet@garethlock.com> wrote:

> On May 22, 5:09�pm, Martin Wuerthner <spamt...@mw-software.com> wrote:
>> In message <4802cf78-e210-4afa-acf0-a751668b0...@hq4g2000vbb.googlegro
>> ups.com>
>> � � � � � Gazza <use...@garethlock.com> wrote:
>>
>>> [...] Is there any way of neutering the CTRL key in
>>> a similar fashion so that it sets a bit, rather than performing any
>>> other action defined by the VDU drivers?
>>
>> In contrast to Esc, the Ctrl key does not have any associated action,
>> so there is no need to suppress it. You can enquire about the state of
>> the Ctrl key at any time using OS_Byte 121. Whatever code you use to
>> accept keyboard input might do specific things when it sees Ctrl
>> keypresses, so in order to answer your question you need to tell us
>> how you accept and interpret keyboard input in your program.
>> OS_ReadLine, for instance, interprets certain Ctrl keypresses.

> Well... I was running a test program that just read from the keyboard
> and displayed both the ASCII codes and the character/string
> representation on the screen. The idea being I could trap CTRL+<key>
> and display the character on the screen, manually prefixed with "^" if
> it was part of a CTRL combo. However, I was stumbling across special
> cases such as CTRL+U and others which of course do funny things with
> the VDU drivers.

Of course. Simply do not display characters with a code < 32 to the 
screen.

> What I want to do is to intercept this set a flag if
> CTRL was pressed and return the ASCII code of just the character
> pressed. I'm using GET to return ASCII codes with OS_Byte 229 set to a
> non-zero value to supress Escape.

There is no need to do anything special. This is just a question of 
interpreting the values you get. If you look at the returned codes it 
should not be difficult to work out that Ctrl+A is 1, Ctrl+B is 2, 
etc. If you want Ctrl+Shift as well, you need to test the shift key 
explicitly.

-- 
Martin
---------------------------------------------------------------------
Martin Wuerthner         MW Software      http://www.mw-software.com/
        RISC OS Software for Design, Printing and Publishing
---------------------------------------------------------------------
0
Reply spamtrap3075 (2284) 5/22/2012 8:45:32 PM

On May 22, 9:45=A0pm, Martin Wuerthner <spamt...@mw-software.com> wrote:
> In message <125e67a9-7565-4a7b-8439-53c951ff1...@l17g2000vbj.googlegro
> ups.com>
> =A0 =A0 =A0 =A0 =A0 Gazza <use...@garethlock.com> wrote:
>
>
>
>
>
> > On May 22, 5:09=A0pm, Martin Wuerthner <spamt...@mw-software.com> wrote=
:
> >> In message <4802cf78-e210-4afa-acf0-a751668b0...@hq4g2000vbb.googlegro
> >> ups.com>
> >> =A0 =A0 =A0 =A0 =A0 Gazza <use...@garethlock.com> wrote:
>
> >>> [...] Is there any way of neutering the CTRL key in
> >>> a similar fashion so that it sets a bit, rather than performing any
> >>> other action defined by the VDU drivers?
>
> >> In contrast to Esc, the Ctrl key does not have any associated action,
> >> so there is no need to suppress it. You can enquire about the state of
> >> the Ctrl key at any time using OS_Byte 121. Whatever code you use to
> >> accept keyboard input might do specific things when it sees Ctrl
> >> keypresses, so in order to answer your question you need to tell us
> >> how you accept and interpret keyboard input in your program.
> >> OS_ReadLine, for instance, interprets certain Ctrl keypresses.
> > Well... I was running a test program that just read from the keyboard
> > and displayed both the ASCII codes and the character/string
> > representation on the screen. The idea being I could trap CTRL+<key>
> > and display the character on the screen, manually prefixed with "^" if
> > it was part of a CTRL combo. However, I was stumbling across special
> > cases such as CTRL+U and others which of course do funny things with
> > the VDU drivers.
>
> Of course. Simply do not display characters with a code < 32 to the
> screen.
>
> > What I want to do is to intercept this set a flag if
> > CTRL was pressed and return the ASCII code of just the character
> > pressed. I'm using GET to return ASCII codes with OS_Byte 229 set to a
> > non-zero value to supress Escape.
>
> There is no need to do anything special. This is just a question of
> interpreting the values you get. If you look at the returned codes it
> should not be difficult to work out that Ctrl+A is 1, Ctrl+B is 2,
> etc. If you want Ctrl+Shift as well, you need to test the shift key
> explicitly.
>
> --
> Martin
> ---------------------------------------------------------------------
> Martin Wuerthner =A0 =A0 =A0 =A0 MW Software =A0 =A0 =A0http://www.mw-sof=
tware.com/
> =A0 =A0 =A0 =A0 RISC OS Software for Design, Printing and Publishing
> ---------------------------------------------------------------------- Hi=
de quoted text -
>
> - Show quoted text -

So as long as I don't try to PRINT it until I figure out what I've
got, then all should be OK... Yes?
0
Reply usenet9920 (358) 5/22/2012 11:03:09 PM

OK... As I suspected... I was doing dopey things. I was PRINTing CHR$
(<key>) before I'd worked out whether CTRL was pressed, therefore
PRINTing control codes. DUH!! Well... My excuse, it was gone midnight
last night when I was trying to figure this out!

Anyhow... Got the ESCape part of it nailed and the CTRL part half
nailed. In his last post, Martin hinted at having to test the SHIFT
key explicitly. Whilst I don't have CTRL+SHIFT+<key> combinations, I
do need to differentiate between CTRL+u & CTRL+U for example. This
could be achieved by using CTRL+SHIFT+u or having CapsLock on when CTRL
+u is pressed, whichever of these it doesn't matter, it's just the
character's case that's important.

Thanks again in advance...
0
Reply usenet9920 (358) 5/23/2012 6:42:11 AM

Well... After another little play, I've got no further than I had when
I'd made the last post, probably lost a little ground if the truth be
known. I'm starting to think about tossing GET altogether and scanning
for a keypress with OS_Byte 121 and then reading the keyboard status
byte using OS_Byte 202 and interpreting the CTRL, SHIFT & CAPS status
from that. Will need to take a long look at this.

Any help or advice would be appreciated here.
0
Reply usenet9920 (358) 5/23/2012 11:20:02 PM

In message <1f7f4803-c3ca-4c50-b063-d07b7f61a0f3@b1g2000vbb.googlegrou 
ps.com>
          Gazza <usenet@garethlock.com> wrote:

> OK... As I suspected... I was doing dopey things. I was PRINTing CHR$
> (<key>) before I'd worked out whether CTRL was pressed, therefore
> PRINTing control codes. DUH!! Well... My excuse, it was gone midnight
> last night when I was trying to figure this out!

> Anyhow... Got the ESCape part of it nailed and the CTRL part half
> nailed. In his last post, Martin hinted at having to test the SHIFT
> key explicitly. Whilst I don't have CTRL+SHIFT+<key> combinations, I
> do need to differentiate between CTRL+u & CTRL+U for example. This
> could be achieved by using CTRL+SHIFT+u or having CapsLock on when CTRL
> +u is pressed, whichever of these it doesn't matter, it's just the
> character's case that's important.

Taking CapsLock into account when interpreting Ctrl keypresses sounds 
unusual to me. I think CapsLock should only be relevant when entering 
real characters. However, if you really want to take CapsLock into 
account, then that would be easy enough. Simply read both the Shift 
and the CapsLock status.

-- 
Martin
---------------------------------------------------------------------
Martin Wuerthner         MW Software      http://www.mw-software.com/
        RISC OS Software for Design, Printing and Publishing
---------------------------------------------------------------------
0
Reply spamtrap3075 (2284) 5/24/2012 9:07:07 AM

Gazza wrote:
> Any help or advice would be appreciated here.

      REPEAT
        K%=GET:S%=INKEY-1:C%=INKEY-2
        IF S%:PRINT" Shift:";
        IF C%:PRINT" Ctrl:";
        IF K%<32 OR K%=127 PRINT "^";CHR$(K% EOR 64); ELSE PRINT CHR$K
%;
      UNTIL FALSE

JGH
0
Reply jgh2 (974) 5/24/2012 8:59:51 PM

In message <f85b54c4-eccd-4b57-9a8e-6bdd30435c9b@w24g2000vby.googlegroups.com>
 on 24 May 2012 jgharston  wrote:

> Gazza wrote:
> > Any help or advice would be appreciated here.
> 
>       REPEAT
>         K%=GET:S%=INKEY-1:C%=INKEY-2
>         IF S%:PRINT" Shift:";
>         IF C%:PRINT" Ctrl:";
>         IF K%<32 OR K%=127 PRINT "^";CHR$(K% EOR 64); ELSE PRINT CHR$K
> %;
>       UNTIL FALSE

That will work nicely if the processing you do on the key presses is swift. 
If a keypress results in some long-winded processing, the user can press
further keys which will be buffered (remembered).  While the character that
the key would generate is remembered and buffered properly, the above code is
reading the state of the shift and ctrl keys *now*, not what they were when
the character you have just read with GET was actually generated by the
keyboard.

If the user changes the state of the shift or ctrl key while your program is
caught up in some heavy task and is not responding, then when it catches up
with the buffered input you might end up thinking the user pressed the "a"
key at the same time as shift, when actually the "a" had been buffered and
the shift key was pressed later.

If all that could cause a problem you have various options.  One is to run
through all the keys using negative INKEY values and read the keyboard state
as it is at that instant.  You can then detect any combination of keys the
ham-fisted user might be pressing all at once.  But it's not a good method
for handling ordinary typing, as you would have to deal with keyboard
auto-repeat and all that malarky yourself.

The other option is something like the DeepKeys module, which I think only
applies with the Wimp's key pressed messages.  That manages (I think) to
store the state of various modifier keys as they were at the time of the
actual keypress.

-- 
Matthew Phillips
Durham
0
Reply spam2011m (148) 5/24/2012 9:51:40 PM

Turns out that character case isn't important. Funny... I could have
sworn it was... Anyway... This is what I currently have...

REM
*******************************************************************************************************
REM Debug code...
REM
*******************************************************************************************************

REM Return "TRUE" if value is boolean TRUE, or "FALSE" otherwise...
DEFFNbool2txt(flag%)
 IF flag% THEN ="TRUE"
="FALSE"

REM Parse an 8 bit mask and return a text representation of bit
status...
DEFFNbits2txt(mask%)
 LOCAL i%,byte$:byte$=""
 FOR i%=0 TO 7
  IF FNbbc_tstbit(i%,mask%) THEN byte$+="1" ELSE byte$+="0"
 NEXT
=byte$

REM
*******************************************************************************************************
REM Exported code...
REM
*******************************************************************************************************

REM Get keyboard input...
REM This behaves just like GET in basic usage. When taken advantage of
it will return the character in
REM char$ and the state of the CTRL key in flag%. Bit 6 of keyboard
status byte is CTRL key state
REM according to OS3 PRM. Bit set, CTRL key down. Bit clear, CTRL key
up. Var. debug% is here for use
REM in test prog. only...
DEFFNbbc_getkey(RETURN char$,RETURN flag%,debug%)
 LOCAL code%,kbflags%:kbflags%=0
 flag%=FALSE                             :REM Clear CTRL key flag on
entry...
 code%=GET:SYS"OS_Byte",&CA,kbflags%,&FF :REM OS_Byte (R0=&CA (202)),
(R2=&FF (255)). Read kbd status byte.
 flag%=FNbbc_tstbit(6,kbflags%)          :REM If CTRL key down then
set flag% TRUE...

 REM Debug code. Why OS_Byte is returning zero here ?!?!?
 IF debug% THEN
  PRINT"Bit position         : 01234567"              :REM Create a
meaningful table for next line...
  PRINT"Keyboard status byte : "+FNbits2txt(kbflags%) :REM Debug...
Display kbd status byte...
  PRINT
  PRINT"CTRL key status      : "+FNbool2txt(flag%)    :REM Debug... Is
CTRL key down...
 ENDIF

 REM Deal with special cases, such as NULL, TAB, ENTER, ESCAPE &
SPACE. There may be more...
 REM Otherwise, if code% < 65, add 64 to take it out of CTRL character
range before getting it's character
 REM representation, then RETURN that on exit.
 CASE code% OF
  WHEN  0   : char$="NULL"
  WHEN  9   : char$="TAB"
  WHEN 13   : char$="ENTER"
  WHEN 27   : char$="ESCAPE"
  WHEN 32   : char$="SPACE"
  OTHERWISE : IF code%<65 THEN code%+=64:char$=CHR$(code%)
 ENDCASE

 REM Finally return ASCII code read. This will be offset to uppercase
if regular CTRL character.
=code%

REM Test a bit at pos% in bitmask mask%. Return TRUE if set.
DEFFNbbc_tstbit(pos%,mask%)
=((mask% AND 1<<pos%)=(1<<pos%))

REM
*******************************************************************************************************


View code with fixed width font. Sorry if it wraps... Calling program
disables ESCape key with OS_Byte 229 (&E5) before this is called.
Can't get anything meaningful back from OS_Byte 202 (&CA). Always
returns zero even if CTRL key held down. My debug routines are
included here for completeness, but finished code will not have debug%
passed to it, or call any of the debug routines bool2txt() or
bits2txt().

Any help would be appreciated...
0
Reply usenet9920 (358) 5/25/2012 2:04:42 PM

Gazza wrote:
> REM Parse an 8 bit mask and return a text representation of bit
> status...
> DEFFNbits2txt(mask%)
> =A0LOCAL i%,byte$:byte$=3D""
> =A0FOR i%=3D0 TO 7
> =A0 IF FNbbc_tstbit(i%,mask%) THEN byte$+=3D"1" ELSE byte$+=3D"0"
> =A0NEXT
> =3Dbyte$

errr..? Return the binary string value of a number?

   REM Binary padded with zeros (mdfs.net/blib/Number)
   DEFFNb0(A%,N%):LOCAL A$,B$,L%:B$=3D"0":IFA%<0:B$=3D"1":A%=3DA
%AND&7FFFFFFF
   REPEATA$=3DSTR$(A%AND1)+A$:A%=3DA%DIV2:L%=3DL%+1:UNTILL%>30:=3DRIGHT$(B$=
+A
$,N%)

Ok, that's a bit dense, because it's a library function, but the
first rule of programming is "find and reuse pre-existing code".

> =A0code%=3DGET:SYS"OS_Byte",&CA,kbflags%,&FF
> =A0flag%=3DFNbbc_tstbit(6,kbflags%)
> =A0REM Why OS_Byte is returning zero here ?!?!?

You haven't returned *anything* from the osbyte call. All you've
done is pass values *top* the osbyte call.

SYS "OS_Byte",&CA,0,&FF TO ,kbflags%

And, as you've looking at the state of the Ctrl key 'now', you
may as well just use INKEY-2.

> =A0CASE code% OF
> =A0 WHEN =A00 =A0 : char$=3D"NULL"
> =A0 WHEN =A09 =A0 : char$=3D"TAB"
> =A0 WHEN 13 =A0 : char$=3D"ENTER"
> =A0 WHEN 27 =A0 : char$=3D"ESCAPE"
> =A0 WHEN 32 =A0 : char$=3D"SPACE"
> =A0 OTHERWISE : IF code%<65 THEN code%+=3D64:char$=3DCHR$(code%)
> =A0ENDCASE

Ctrl-I returns "TAB", Ctrl-M returns "ENTER". Is that what you want?
Don't you want to distinguish between Ctrl-M and Enter, between
Ctrl-I and TAB?

> Any help would be appreciated...

  REM Return a string with the keypress, and returns Shift and Ctrl
status
  :
  DEFFNbbc_getkey(RETURN shift%, RETURN ctrl%)
  LOCAL key%, char$
  key%=3DGET:shift%=3DINKEY-1:ctrl%=3DINKEY-2 :REM Read keypress, shift and
ctrl keys
  char$=3DCHR$key%                        :REM Prepare to return
keypress as a character
  IF key%<32 OR key%=3D127 THEN char$=3D"^"+CHR$(key% EOR 64)
  :                                     :REM If a Ctrl+key, prepare to
return "^X"
  IF ctrl%=3D0 THEN
   :                                    :REM If Ctrl was /not/
pressed...
   CASE key% OF
       :                                :REM Translate to key names
      WHEN   8 : char$=3D"BACKSPACE"
      WHEN   9 : char$=3D"TAB"
      WHEN  13 : char$=3D"ENTER"
      WHEN  27 : char$=3D"ESCAPE"
      WHEN  30 : char$=3D"HOME"
      WHEN  32 : char$=3D"SPACE"
      WHEN 127 : char$=3D"DELETE"
    ENDCASE
  ENDIF
  =3Dchar$                                :REM Return keypress string

Can be optimised quite a bit.

JGH
0
Reply jgh2 (974) 5/25/2012 2:48:09 PM

jgharston wrote:
> Gazza wrote:
>> REM Parse an 8 bit mask and return a text representation of bit
>> status...
>> DEFFNbits2txt(mask%)
>>   LOCAL i%,byte$:byte$=""
>>   FOR i%=0 TO 7
>>    IF FNbbc_tstbit(i%,mask%) THEN byte$+="1" ELSE byte$+="0"
>>   NEXT
>> =byte$
>
> errr..? Return the binary string value of a number?
>
>     REM Binary padded with zeros (mdfs.net/blib/Number)
>     DEFFNb0(A%,N%):LOCAL A$,B$,L%:B$="0":IFA%<0:B$="1":A%=A
> %AND&7FFFFFFF
>     REPEATA$=STR$(A%AND1)+A$:A%=A%DIV2:L%=L%+1:UNTILL%>30:=RIGHT$(B$+A
> $,N%)
>
> Ok, that's a bit dense, because it's a library function, but the
> first rule of programming is "find and reuse pre-existing code".

errr..?

   SYS"OS_ConvertBinary1",mask%,END+255,255 TO byte$

or, with Basalt:

   byte$=NUM$(mask%,4,1)
0
Reply steve3677 (307) 5/25/2012 3:30:09 PM

On Fri, 25 May 2012 07:48:09 -0700 (PDT), jgharston 
<jgh@arcade.demon.co.uk> wrote:

>> � IF FNbbc_tstbit(i%,mask%) THEN byte$+="1" ELSE byte$+="0"
> errr..? Return the binary string value of a number?

Isn't there an OS_ConvertBlahBlah SWI that can do this?


Best wishes,

Rick.
0
Reply heyrickmail-usenet (853) 5/26/2012 2:08:51 PM

On Thu, 24 May 2012 22:51:40 +0100, Matthew Phillips 
<spam2011m@yahoo.co.uk> wrote:

> That will work nicely if the processing you do on the key presses 
is swift. 
> If a keypress results in some long-winded processing, the user can 
press
[...]
> reading the state of the shift and ctrl keys *now*, not what they 
were when

I guess the important factor is how long something *actually* takes. 
Keypress entry is remarkably slow, a computer can build a display 
from data in less time than between keydown and keyup (with triangles 
on an older machine, damn near raytraced in realtime on a newer one). 
Remember Chocks Away! and the like? Not only was the game logic 
running, but the world was being redrawn in realtime (that's why it 
is kinda basic, there's only so much an 8MHz processor can do).


Alternatives - write a small bit of code to hang on key events to 
record the state of keys and modifiers to a circular buffer. Or flush 
the keyboard buffer before reading so we know we'll only get fresh 
data. The latter is easy but nasty, the former is hard but the most 
useful.


Best wishes,

Rick.
0
Reply heyrickmail-usenet (853) 5/26/2012 2:16:19 PM

On Thu, 24 May 2012 11:07:07 +0200, Martin Wuerthner 
<spamtrap@mw-software.com> wrote:

> account, then that would be easy enough. Simply read both the Shift 
> and the CapsLock status.

Be aware, however, the the configurations Caps, NoCaps, and ShCaps 
subtly alter how Caps Lock behaves.


Best wishes,

Rick.
0
Reply heyrickmail-usenet (853) 5/26/2012 2:18:55 PM

Thanks JGH... I've grafted parts of what you had into my latest
routine and have something sort of working. Still however, can't tell
the difference between CTRL+ESC & CTRL+[ for example. This is just the
one I tried, there were others you mentioned previously.

What I have now looks like this. In it's most basic form, I need it to
return an ASCII code as a result, like GET, with one, or both of the
other values RETURNed, so I've messed it about a bit to return the
values in the correct places. Again, you'll need to use a fixed width
font and sorry if code wraps...

REM Get keyboard input...
REM This behaves just like GET in basic usage. When taken advantage of
it will return the character in
REM char$ and the state of the CTRL key in flag%. Bit 6 of keyboard
status byte is CTRL key state
REM according to OS3 PRM. Bit set, CTRL key down. Bit clear, CTRL key
up.
DEFFNbbc_getkey(RETURN char$,RETURN flag%)
 LOCAL code%,shift%,ctrl%,caps%,kbflags%
 char$="":flag%=0                                    :REM Clear all
values on entry...
 shift%=3:caps%=4:ctrl%=6
 code%=GET:SYS"OS_Byte",&CA,0,&FF TO void%,kbflags%  :REM OS_Byte
(R0=&CA (202)), (R2=&FF (255)). Read status.
 flag%=FNbbc_tstbit(ctrl%,kbflags%)
 IF (code%<32 OR code%=127) AND flag% THEN char$=CHR$(code% EOR 64)

 REM Deal with special cases, such as NULL, TAB, ENTER, ESCAPE &
SPACE. There may be more...
 IF (NOT flag%) THEN
  CASE code% OF
   WHEN   0  : char$="NULL"
   WHEN   8  : char$="BACKSPACE"
   WHEN   9  : char$="TAB"
   WHEN  13  : char$="ENTER"
   WHEN  27  : char$="ESCAPE"
   WHEN  30  : char$="HOME"
   WHEN  32  : char$="SPACE"
   WHEN 127  : char$="DELETE"
   OTHERWISE : char$=CHR$(code%)
  ENDCASE
 ENDIF
=code%

REM Test a bit at pos% in bitmask mask%. Return TRUE if set.
DEFFNbbc_tstbit(pos%,mask%)
=((mask% AND 1<<pos%)=(1<<pos%))
0
Reply usenet9920 (358) 5/27/2012 9:25:17 AM

Steve Drain wrote:
> > errr..? Return the binary string value of a number?
>
> =A0 =A0SYS"OS_ConvertBinary1",mask%,END+255,255 TO byte$

Doh! Of course. Zero'th law of programming: can the underlying
system do it?

JGH
0
Reply jgh2 (974) 5/27/2012 12:43:01 PM

Gazza wrote:
> Thanks JGH... I've grafted parts of what you had into my latest
> routine and have something sort of working. Still however, can't tell
> the difference between CTRL+ESC & CTRL+[ for example.

Do you /need/ to be able to tell between Ctrl-Esc and Ctrl-[ ?
The more raw information you need the more detatched you are
becoming from using the keyboard as an input stream and more
towards reading it as a raw device. You it looks like you want
is a non-Wimp DeepKeys, which returns a keypress identifier
and the state of the modifier keys.

JGH
0
Reply jgh2 (974) 5/27/2012 5:00:48 PM

Gazza wrote:
> Still however, can't tell the difference between
> CTRL+ESC & CTRL+[ for example.

Ok, how about this.

 REM FNkey_get - waits for and returns a "deep" keypress
 REM ---------------------------------------------------
 REM Returns: b0-b8:  keypress character
 REM          b12-b23: modifier key pressed:
 REM              b12: Left mouse button
 REM              b13: Middle mouse button
 REM              b14: Right mouse button
 REM              b15: Right ALT key
 REM              b16: Right CTRL key
 REM              b17: Right SHIFT key
 REM              b18: Left ALT key
 REM              b19: Left CTRL key
 REM              b20: Left SHIFT key
 REM              b21: Either ALT key
 REM              b22: Either CTRL key
 REM              b23: Either SHIFT key
 REM          b24-b31: physical key pressed
 REM
 REM 33222222 222211111111 11
 REM 10987654 321098765432 109 876543210
 REM physical modifierkeys --- character
 :
 DEFFNkey_get
 LOCAL char%, key%, shift%
 char%=3DGET                              :REM Keypress character
 shift%=3D0
 FOR key%=3D1 TO 12
   shift%=3D(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier keys
 NEXT
 SYS"OS_Byte",122 TO ,key%              :REM Read physical keypress
 =3Dchar% OR (key%<<24) OR (shift%<<13)

This returns a combination of the character returned by the
keypress, the physical key pressed, and the modifier keys
pressed. This lets you tell apart, for instance, Ctrl-M and
Ctrl-Enter and Ctrl-Return:

Ctrl-M       &6590000D
Ctrl-Enter:  &3C90000D
Ctrl-Return: &4990000D

The top byte is the physical key pressed, the bottom byte
is the character returned by that key. Actually, the bottom
*nine* bits are the character returned by the key, as that
will allow me to add in the code that distinguishes between
top-bit-set keys (eg '=A3', &0A3) and function/editing keys
(eg Ctrl-f3, &1A3) as in my 'C' console library, and the
RISC OS Wimp.

Demo code:
REPEAT
  A%=3DFNkey_get
  PRINT "Character: ";~A% AND 511
  PRINT "Modifiers: ";~A% AND &00FFF000
  PRINT "Keypress:  ";~A% >>> 24
UNTIL FALSE

JGH
0
Reply jgh2 (974) 5/27/2012 5:55:23 PM

On May 27, 6:55=A0pm, jgharston <j...@arcade.demon.co.uk> wrote:
> Ok, how about this.
>
>
> JGH

Got it sort of working... I mean the code works OK, I just ran out of
time towards the end to completely develop the wrapper code and modify
the test program to use it... I've added a return parameter which
returns TRUE if caps-lock is active, this I've implemented by calling
OS_Byte 202 as before, otherwise it's exactly as you posted. Call is
now

FNkey_get(*<caps>)

I don't know whether OS_Byte 202 might be a more convenient way of
returning all the modifier keys in the long run. Anyhow... It seems to
work as far as I've pushed it so far. I'm planning on releasing it,
along with the wrapper code and a couple of other keyboard related
routines I've developed as a library, if you approve, I'll post it on
the Moria progress page (http://www.garethlock.com/acorn/umoria/
index.html) where you can download a copy once it's complete.

Thanks

0
Reply usenet9920 (358) 5/29/2012 5:30:44 PM

Gazza wrote:
> Call is now
> FNkey_get(*<caps>)

Might be more useful to return the CapLock status as part of the
return value, giving one return value.

 DEFFNkey_get
 LOCAL char%, key%, shift%
 char%=GET                              :REM Keypress character
 shift%=0
 FOR key%=1 TO 12
   shift%=(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier keys
 NEXT
 SYS "OS_Byte",202,0,255 TO ,key%
 shift%=(shift%<<1) OR ((key% AND 16)>>4)
 SYS"OS_Byte",122 TO ,key%
 =char% OR (key%<<24) OR (shift%<<12)
 REM b11=CapLock status (if I've counted correctly)

There's a programming convention that doesn't like multiple
return values. As with many conventions, it's a convention,
how useful it is depends on the situations it's used in.

> I don't know whether OS_Byte 202 might be a more convenient way
> of returning all the modifier keys in the long run.

Depends if knowing /which/ Shift key, /which/ Ctrl key, etc. is
useful or not. Having a function that returns the state of left
and right modifier keys gives information that can be ignored
which can't be unignored the other way around.

 DEFFNkey_get
 LOCAL char%, key%, shift%
 char%=GET                              :REM Keypress character
 SYS "OS_Byte",202,0,255 TO ,shift%
 SYS "OS_Byte",122 TO ,key%
 =char% OR (key%<<24) OR ((shift%EOR&14)<<16)
 REM  b0-b8 =char value
 REM   b16  =Pending Alt
 REM   b17  =ScrollLock
 REM   b18  =NumLock
 REM   b19  =Shift
 REM   b20  =CapsLock
 REM   b21  =reserved
 REM   b22  =Ctrl
 REM   b23  =ShiftLock
 REM b24-b31=keypress

JGH
0
Reply jgh2 (974) 5/29/2012 9:14:40 PM

On May 29, 10:14=A0pm, jgharston <j...@arcade.demon.co.uk> wrote:
> Gazza wrote:
> > Call is now
> > FNkey_get(*<caps>)
>
> Might be more useful to return the CapLock status as part of the
> return value, giving one return value.
>
> =A0DEFFNkey_get
> =A0LOCAL char%, key%, shift%
> =A0char%=3DGET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0:REM Keypress character
> =A0shift%=3D0
> =A0FOR key%=3D1 TO 12
> =A0 =A0shift%=3D(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier ke=
ys
> =A0NEXT
> =A0SYS "OS_Byte",202,0,255 TO ,key%
> =A0shift%=3D(shift%<<1) OR ((key% AND 16)>>4)
> =A0SYS"OS_Byte",122 TO ,key%
> =A0=3Dchar% OR (key%<<24) OR (shift%<<12)
> =A0REM b11=3DCapLock status (if I've counted correctly)
>
> There's a programming convention that doesn't like multiple
> return values. As with many conventions, it's a convention,
> how useful it is depends on the situations it's used in.
>
> > I don't know whether OS_Byte 202 might be a more convenient way
> > of returning all the modifier keys in the long run.
>
> Depends if knowing /which/ Shift key, /which/ Ctrl key, etc. is
> useful or not. Having a function that returns the state of left
> and right modifier keys gives information that can be ignored
> which can't be unignored the other way around.
>
> =A0DEFFNkey_get
> =A0LOCAL char%, key%, shift%
> =A0char%=3DGET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0:REM Keypress character
> =A0SYS "OS_Byte",202,0,255 TO ,shift%
> =A0SYS "OS_Byte",122 TO ,key%
> =A0=3Dchar% OR (key%<<24) OR ((shift%EOR&14)<<16)
> =A0REM =A0b0-b8 =3Dchar value
> =A0REM =A0 b16 =A0=3DPending Alt
> =A0REM =A0 b17 =A0=3DScrollLock
> =A0REM =A0 b18 =A0=3DNumLock
> =A0REM =A0 b19 =A0=3DShift
> =A0REM =A0 b20 =A0=3DCapsLock
> =A0REM =A0 b21 =A0=3Dreserved
> =A0REM =A0 b22 =A0=3DCtrl
> =A0REM =A0 b23 =A0=3DShiftLock
> =A0REM b24-b31=3Dkeypress
>
> JGH

OK... I couldn't remember whether OS_Byte 202 distinguished between
left and right modifiers, obviously not. That is a better way of
working in the caps-lock status though... Will integrate that change
when I get in front of the machine tomorrow...
0
Reply usenet9920 (358) 5/29/2012 11:32:52 PM

> > =A0DEFFNkey_get
> > =A0LOCAL char%, key%, shift%
> > =A0char%=3DGET
> > =A0SYS "OS_Byte",202,0,255 TO ,shift%
> > =A0SYS "OS_Byte",122 TO ,key%
> > =A0=3Dchar% OR (key%<<24) OR ((shift%EOR&14)<<16)

Hmmm. Every time I add more functionality to this subroutine,
it gets shorter! ;)

JGH
0
Reply jgh2 (974) 5/30/2012 12:34:35 AM

On May 29, 10:14=A0pm, jgharston <j...@arcade.demon.co.uk> wrote:
> Gazza wrote:
> > Call is now
> > FNkey_get(*<caps>)
>
> Might be more useful to return the CapLock status as part of the
> return value, giving one return value.
>
> =A0DEFFNkey_get
> =A0LOCAL char%, key%, shift%
> =A0char%=3DGET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0:REM Keypress character
> =A0shift%=3D0
> =A0FOR key%=3D1 TO 12
> =A0 =A0shift%=3D(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier ke=
ys
> =A0NEXT
> =A0SYS "OS_Byte",202,0,255 TO ,key%
> =A0shift%=3D(shift%<<1) OR ((key% AND 16)>>4)
> =A0SYS"OS_Byte",122 TO ,key%
> =A0=3Dchar% OR (key%<<24) OR (shift%<<12)
> =A0REM b11=3DCapLock status (if I've counted correctly)
> JGH

If it's not to much trouble, could you provide me with the updated
demo code that returns b11 as part of the modifiers...

PRINT "Modifiers: ";~A% AND &00FFF000


0
Reply usenet9920 (358) 5/30/2012 11:06:16 AM

Gazza wrote:
> If it's not to much trouble, could you provide me with the updated
> demo code that returns b11 as part of the modifiers...

PRINT "Modifiers: ";~A% AND &00FFFC00
REM . . . . . . . . . . . . . . . ^

Or, for the OSBYTE 202 version:
  REPEAT
    A%=FNkey_get
    PRINT "Character:  ";~A% AND 511
    PRINT "Keypress:   ";~A% >>> 24
    PRINT "Alt:        ";~A% AND (1<<16)
    PRINT "ScrollLock: ";~A% AND (1<<17)
    PRINT "NumLock:    ";~A% AND (1<<18)
    PRINT "Shift:      ";~A% AND (1<<19)
    PRINT "CapsLock:   ";~A% AND (1<<20)
    PRINT "Ctrl:       ";~A% AND (1<<22)
    PRINT "ShiftLock:  ";~A% AND (1<<23)
  UNTIL FALSE

  DEFFNkey_get
  LOCAL char%, key%, shift%
  char%=GET
  SYS "OS_Byte",202,0,255 TO ,shift%
  SYS "OS_Byte",122 TO ,key%
  =char% OR (key%<<24) OR ((shift%EOR&14)<<16)
  REM  b0-b8 =char value
  REM   b16  =Pending Alt
  REM   b17  =ScrollLock
  REM   b18  =NumLock
  REM   b19  =Shift
  REM   b20  =CapsLock
  REM   b21  =reserved
  REM   b22  =Ctrl
  REM   b23  =ShiftLock
  REM b24-b31=keypress

JGH
0
Reply jgh2 (974) 5/30/2012 11:35:18 AM

On May 30, 12:35=A0pm, jgharston <j...@arcade.demon.co.uk> wrote:
> Gazza wrote:
> > If it's not to much trouble, could you provide me with the updated
> > demo code that returns b11 as part of the modifiers...
>
> PRINT "Modifiers: ";~A% AND &00FFFC00
> REM . . . . . . . . . . . . . . . ^
>

So...

modifier%=3DA% AND &00FFFC00

.... Would return Caps-Lock in b0? If so, then I'll use this, as I've
already virtually completed most of the library with this assumption.
Whilst the ability to detect which SHIFT/CTRL/ALT key is depressed is
not particularly relevant in my Moria port, having this capability as
part of a generic library makes sense in the long run, to me anyway.

Thanks for your help, with your permission, I'll post the library on
my Moria progress page (linked in a previous post) when completed...
0
Reply usenet9920 (358) 5/30/2012 12:40:14 PM

Since my last post this afternoon, I've been playing around a little
more and integrated GET & INKEY (timeout) functionality into the core
deepscan code, and this is what I've come up with. <timeout> is in
secs. INKEY() takes it's values as secs/100 IIRC, if not, then this
needs adjusting accordingly. I wasn't sure how a negative number was
going to be handled with all that shifting, so if the timeout period
expires (INKEY(<timeout>) returns -1) then I make char% zero and
ultimately set b9 before we exit. I haven't tested this yet, but this
should still return the modifier key status even if a regular key
hasn't been pressed within the timeout period.

DEFFNkeyb_deepscan(timeout%)
 LOCAL char%, key%, shift%, mask%, flag%
 IF timeout%=0 THEN
  char%=GET                              :REM Keypress character
 ELSE
  char%=INKEY(timeout%*100)
  IF char%=-1 THEN char%=0:flag%=TRUE
 ENDIF
 shift%=0
 FOR key%=1 TO 12
   shift%=(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier keys
 NEXT
 SYS "OS_Byte",202,0,255 TO ,key%
 shift%=(shift%<<1) OR ((key% AND 16)>>4)
 SYS"OS_Byte",122 TO ,key%
 mask%=(char% OR (key%<<24) OR (shift%<<12))
 IF flag% THEN PROCkeyb_setbit(9,mask%)
=mask%

keyb_scan() : Which in effect calls the above code and returns raw
data, as required by the Demo Code.
keyb_get(*<char>,*<modifier>,*<scan>) : This is the one I'll be using
most in the Moria port. Just calls the above code and performs some
post-processing. The ASCII code is returned by the function.
keyb_inkey(<timeout>,*<char>,*<modifier>,*<scan>) : This is exactly
the same as keyb_get(), except it takes an extra parameter that
specifies a timeout period in seconds. Like the above, the function
returns the ASCII code of the key pressed, or -1 if the timeout has
expired.
keyb_querycase(<modifier>) : Implements CAPS & SHIFT behaviour...

I've also added some extra stuff including a full scan -> ASCII code
LUT which returns the correct ASCII code depending on CAPS & SHIFT key
status and defined behaviour (See Below...)

keyb_querycase(<modifier>) Examines modifier flags. If CAPS & SHIFT
active then we return FALSE (lowercase). If CAPS or SHIFT active then
return TRUE (uppercase). If neither active then return FALSE.

Just got the LUT to fully implement now, this is based on the old
Archimedes type keyboard scan-codes as found in the RISC OS 3 PRMs, as
that is all I have access to. If anyone has access to a keyboard
layout with scan-codes for a modern PC type keyboard, and other common
derivatives and a method to detect the different hardware types on the
fly, then I'll try to implement the differences.

For each keyboard type, I need the physical keyboard layout with both
key-top symbols and the scan-codes, a la the Diagram showing the
Archimedes type keyboard in the OS 3 PRMs.

With your permission, I'll post a link to this library on the progress
page when finalised...
0
Reply usenet9920 (358) 5/30/2012 5:26:35 PM

Been developing a bit more last night. Couldn't post at the time,
because the net went down. I think I've interpreted this correctly, to
use b9 as a timeout flag for INKEY functionality and b10 for Num-Lock
state. I'm including the modified code below. Can JGH please verify
that I've interpreted his code correctly...

Thanks

REM FNkeyb_deepscan(<100th secs>) - waits for and returns a "deep"
keypress
REM
-----------------------------------------------------------------------
REM Returns: b00-b08 : Keypress character
REM              b09 : Timeout flag (Set if timeout expired in INKEY
variant.)
REM          b10-b11 : Toggle state modifier keys:
REM              b10 : Num-Lock state
REM              b11 : Caps-Lock state
REM          b12-b23 : Momentary state modifier keys:
REM              b12 : Left mouse button
REM              b13 : Middle mouse button
REM              b14 : Right mouse button
REM              b15 : Right ALT key
REM              b16 : Right CTRL key
REM              b17 : Right SHIFT key
REM              b18 : Left ALT key
REM              b19 : Left CTRL key
REM              b20 : Left SHIFT key
REM              b21 : Either ALT key
REM              b22 : Either CTRL key
REM              b23 : Either SHIFT key
REM          b24-b31 : Physical key pressed

REM 00000000 11100000000000   000000000
REM 76543210 32109876543210   876543210
REM physical modifier__keys   character
REM 33222222 22221111111111 0 000000000
REM 10987654 32109876543210 9 876543210

REM Need to check this with -JGH-. Have I interpreted what he's doing
correctly when shifting Num-Lock status
REM into b10?
DEFFNkeyb_deepscan(timeout%)
 LOCAL char%,key%,shift%,void%,fl%,mask%
 IF timeout%=0 THEN
  char%=GET                              :REM Keypress character. (No
timeout)
 ELSE
  char%=INKEY(timeout%)                  :REM Keypress character.
(With timeout)
  IF char%<0 THEN char%=0:fl%=TRUE       :REM Make char% 0 if negative
and set flag for later.
 ENDIF
 shift%=0
 FOR key%=1 TO 12
  shift%=(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier keys
 NEXT
 SYS"OS_Byte",&CA,0,&FF TO void%,key%    :REM OS_Byte (R0=&CA (202),
R1=0, R2=&FF (255)). Read keybd status.
 shift%=(shift%<<1)OR((key%AND16)>>4)    :REM Extract Caps-Lock state
from key% shift into b11.
 shift%=(shift%<<1)OR((key%AND16)>>2)    :REM Extract Num-Lock state
from key% shift into b10. Is this correct?
 SYS"OS_Byte",&7A TO void%,key%          :REM OS_Byte (R0=&7A (122)).
Read physical keypress.
 mask%=(char% OR (key%<<24) OR (shift%<<11)) :REM Was mask%=(char% OR
(key%<<24) OR (shift%<<12)). See top.
 IF fl% THEN PROCkeyb_setbit(9,mask%)
=mask%


Needs to be viewed in a fixed-width font, sorry if the code wraps...
0
Reply usenet9920 (358) 5/31/2012 1:56:16 PM

Messed around with it a little more and got it to work and return Caps
in b11 and Num in b10. I'm using b9 for timeout expired when using
INKEY rather than GET is an input method. I've had to hack in Caps and
Num-Lock status for the time being using an extra variable and
manually setting bits after the 32bit mask has been assembled. Both
Caps & Num-Lock state are actually the INVERSE of the bit values
returned after the call to OS_Byte 202 (Bit Clear = ON) for some
reason, so I'm checking the inverse and setting bits accordingly.

The other minor change was that JGH got the left and right mouse
buttons swapped. Starting at b12, it's Adjust, Menu, Select, not
Select, Menu, Adjust. I've included a verbose and hacky version of the
demo code that expands all 32 bits of the returned datastream into a
text string along with significance.

I've not bothered to use OS calls to convert the mask to a string,
just a variation of the debug code I posted the other day. The code
follows. It needs to be view in a fixed width font and as always,
sorry if the code wraps...

REM Demo code:
REPEAT
 PRINT
 A%=FNkeyb_scan
 PRINT "Character:  ";A% AND 511
 PRINT "Modifiers: &";~A% AND &00FFFC00 :REM This mask is doesn't take
into account Num-Lock state in b10
 PRINT "         T C   RRRLLL   "
 PRINT "         ONaAMSACSACSACS"
 PRINT "         uupdneltfltfltf"
 PRINT "<-char-->tmsjultlttlttlt<-scan->"
 PRINT "--------------------------------"
 PRINT FNkeyb_bits2txt(A%,31)
 PRINT "Keypress:   ";A% >>> 24
 PRINT
UNTIL FALSE

REM FNkeyb_deepscan(<100th secs>) - waits for and returns a "deep"
keypress
REM
-----------------------------------------------------------------------
REM Returns: b00-b08 : Keypress character
REM              b09 : Timeout flag (Set if timeout expired in INKEY
variant.)
REM          b10-b11 : Toggle state modifier keys:
REM              b10 : Num-Lock state
REM              b11 : Caps-Lock state
REM          b12-b23 : Momentary state modifier keys:
REM              b12 : Right mouse button
REM              b13 : Middle mouse button
REM              b14 : Left mouse button
REM              b15 : Right ALT key
REM              b16 : Right CTRL key
REM              b17 : Right SHIFT key
REM              b18 : Left ALT key
REM              b19 : Left CTRL key
REM              b20 : Left SHIFT key
REM              b21 : Either ALT key
REM              b22 : Either CTRL key
REM              b23 : Either SHIFT key
REM          b24-b31 : Physical key pressed

REM 00000000 11100000000000   000000000
REM 76543210 32109876543210   876543210
REM physical modifier__keys   character
REM 33222222 22221111111111 0 000000000
REM 10987654 32109876543210 9 876543210
DEFFNkeyb_deepscan(timeout%)
 LOCAL char%,key%,shift%,void%,fl%,mask%
 IF timeout%=0 THEN
  char%=GET                              :REM Keypress character. (No
timeout)
 ELSE
  char%=INKEY(timeout%)                  :REM Keypress character.
(With timeout)
  IF char%<0 THEN
   char%=0:PROCkeyb_setbit(0,fl%)        :REM Make char% 0 if negative
and set flag for later.
  ENDIF
 ENDIF
 shift%=0
 FOR key%=1 TO 12
  shift%=(shift%<<1)OR(INKEY-key% AND 1) :REM Read all modifier keys
 NEXT
 SYS"OS_Byte",&CA,0,&FF TO void%,key%    :REM OS_Byte (R0=&CA (202),
R1=0, R2=&FF (255)). Read keybd status.
 shift%=(shift%<<1)
 IF NOT FNkeyb_tstbit(2,key%) THEN PROCkeyb_setbit(1,fl%) :REM b2
Clear = Num-Lock ON.
 IF NOT FNkeyb_tstbit(4,key%) THEN PROCkeyb_setbit(2,fl%) :REM b4
Clear = Caps-Lock ON.

 SYS"OS_Byte",&7A TO void%,key%          :REM OS_Byte (R0=&7A (122)).
Read physical keypress.
 mask%=(char% OR (key%<<24) OR (shift%<<11))
 IF FNkeyb_tstbit(0,fl%) THEN PROCkeyb_setbit(9,mask%)    :REM If b0
set, INKEY timeout...
 IF FNkeyb_tstbit(1,fl%) THEN PROCkeyb_setbit(10,mask%)   :REM If b1
set, Num-Lock ON...
 IF FNkeyb_tstbit(2,fl%) THEN PROCkeyb_setbit(11,mask%)   :REM If b2
set, Caps-Lock ON...
=mask%

REM Calls keyb_deepscan() with no timeout and returns raw data...
DEFFNkeyb_scan
=FNkeyb_deepscan(0)

REM Returns TRUE if given bit is set in mask...
DEFFNkeyb_tstbit(p%,m%)
=((m% AND 1<<p%)=(1<<p%))

REM Sets a given bit in a bitmask...
DEFPROCkeyb_setbit(p%,RETURN m%)
 m%=m% OR (1<<p%)
ENDPROC

REM Build a text representation of a binary number... (Debug only.)
DEFFNkeyb_bits2txt(mask%,len%)
 LOCAL i%,bits$
 FOR i%=0 TO len%
  IF FNkeyb_tstbit(i%,mask%) THEN bits$+="1" ELSE bits$+="0"
 NEXT
=bits$

Yes... I know it's not the most elegant solution, but it does the job.
If someone would like the challenge of tidying it up a bit then go
ahead, and post it on here afterwards... lol

Many thanks for all your help
0
Reply usenet9920 (358) 6/1/2012 12:02:41 PM

Think I've finally got it sorted. Another hack to Demo Code got the
modifiers returning correctly...

modifier%=A%AND&00FFFC00
modifier%=modifier%>>10

FIXED...

Am posting another copy of the Demo Code with both keyb_deepscan() RAW
data expanded along with Caps-Lock & Num-Lock test stings and the
modifier flags expanded in the same way as the RAW data from
keyb_deepscan()

As before, you'll need a fixed-width font to make sense of it,
especially the expanded stuff...

      10 : REM Demo code:
      20 : REPEAT
      30 :  PRINT
      40 :  mask%=FNkeyb_getraw:modmask%=&00FFFC00
      50 :  char%=mask% AND 511
      60 :  modifier%=mask% AND modmask%:modifier%=modifier%>>10
      70 :  scan%=mask% >>> 24
      80 :
      90 :  PRINT"Character:  ";char%
     100 :  PRINT"Modifiers: &";~modifier%
     110 :  PRINT"Keypress:   ";scan%
     120 :  PRINT
     130 :  PRINT"         T C   RRRLLL   "
     140 :  PRINT"         ONaAMSACSACSACS"
     150 :  PRINT"         uupdneltfltfltf"
     160 :  PRINT"<-char-->tmsjultlttlttlt<-scan->"
     170 :  PRINT"--------------------------------"
     180 :  PRINTFNkeyb_bits2txt(mask%,31)
     190 :  PRINTFNkeyb_bits2txt(modmask%,31)
     200 :  PRINT
     210 :  PRINT"Reading from Modifiers... (mask% AND &";~modmask
%;" )"
     220 :  PRINT"Num-Lock  : "+FNkeyb_iifs(FNkeyb_tstbit(0,modifier
%),"ON","OFF")
     230 :  PRINT"Caps-Lock : "+FNkeyb_iifs(FNkeyb_tstbit(1,modifier
%),"ON","OFF")
     240 :  PRINT
     250 :  PRINT" C   RRRLLL"
     260 :  PRINT"NaAMSACSACSACS"
     270 :  PRINT"updneltfltfltf"
     280 :  PRINT"msjultlttlttlt"
     290 :  PRINT"--------------"
     300 :  PRINTFNkeyb_bits2txt(modifier%,13)
     310 :  PRINT
     320 : UNTIL FALSE

Refer to previous post for most of the DEFs, the only new one is...

DEFFNkeyb_iifs(cond%,true$,false$)
 IF cond% THEN =true$
=false$
0
Reply usenet9920 (358) 6/1/2012 2:01:54 PM

Already changed...

60 :  modifier%=mask% AND modmask%:modifier%=modifier%>>10

to...

60 :  modifier%=(mask% AND modmask%)>>10

.... Was doing it this way until I was sure I was doing the right
thing... Easier to REM out.
0
Reply usenet9920 (358) 6/1/2012 2:54:12 PM

Gazza wrote:
> ... Was doing it this way until I was sure I was doing the right
> thing... Easier to REM out.

Sorry, I've been busy with a funeral, I'll have a play with the code
tomorrow.

JGH
0
Reply jgh2 (974) 6/3/2012 1:18:31 AM

On Jun 3, 2:18=A0am, jgharston <j...@arcade.demon.co.uk> wrote:
> Gazza wrote:
> > ... Was doing it this way until I was sure I was doing the right
> > thing... Easier to REM out.
>
> Sorry, I've been busy with a funeral, I'll have a play with the code
> tomorrow.
>
> JGH

My condolences to you and the family.

I can provide the whole lot as a ZIPped file with the rest of the
library to the e-mail address you use to log in to csap if you think
it would help
0
Reply usenet9920 (358) 6/3/2012 8:02:11 AM

Some points on your code.

>  IF FNkeyb_tstbit(0,fl%) THEN ...
just do: IF (fl% AND (1<<0)) THEN ...

> PROCkeyb_setbit(9,mask%)
just do: mask%=3Dmask% OR (1<<9)

>  SYS "OS_Byte",&7A TO void%,key%
just do: SYS "OS_Byte",&7A TO ,key%

Any returned values you want to ignore can be just ignored
by skipping the variable to deposit it into after the TO,
just as any parameters you want to ignore when calling can
also be skipped by skipping the variable before the TO, and
zero will be used instead.

I've tidied up the code and draft documentation into a library
at mdfs.net/blib#deepkey

Here is an uncrunched version with demo code. The demo code also
defines the function and editing keys to return their keycodes
so they can be distinguished from top-bit-set characters such as
'=A3' in a similar manner to the Wimp. (Using *FX221-228,2 sets
function and editing keys to return CHR$00,CHR$keynumber.)

REM > BLib.Develop.DeepKeys
:
MODE 40:PROCdemo:END
:
:
REM FNdeep_inkey(time%) and FNdeep_get
REM ----------------------------------
REM Returns -1 if no key pressed within time% in centiseconds
REM  or b0-b8  : character code (b8=3D1 if function/editing key)
REM     b9     : reserved
REM     b10    : RightAlt
REM     b11    : RightCtrl
REM     b12    : RightShift
REM     b13    : LeftAlt
REM     b14    : LeftCtrl
REM     b15    : LeftShift
REM     b16    : Alt pending
REM     b17    : Scroll Lock
REM     b18    : NumLock
REM     b19    : Shift
REM     b20    : Caps Lock
REM     b21    : reserved
REM     b22    : Ctrl
REM     b23    : Shift Lock
REM     b24-b31: physical key pressed
:
DEFFNdeep_inkey(time%)
LOCAL char%,mod%,key%,shift%
char%=3DINKEY(time%):IFchar%=3D-1:=3D-1
IF char%=3D0:char%=3DGET:IF char%:char%=3D(char% OR &100) EOR ((char
%AND15)>9 AND &40)
shift%=3D0
FOR key%=3D4 TO 9
  shift%=3D(shift%<<1)OR(INKEY-key% AND 1)
NEXT
SYS "OS_Byte",&CA,,&FF TO ,mod%
SYS "OS_Byte",&7A TO ,key%
=3Dchar% OR (shift%<<10) OR ((mod%EOR&14)<<16) OR (key%<<24)
:
DEFFNdeep_get
LOCAL A%
REPEAT
  A%=3DFNdeep_inkey(10)
UNTIL A%<>-1
=3DA%
:
:
:
DEFPROCdemo
FOR A%=3D221 TO 228:SYS "OS_Byte",A%,2:NEXT:*FX4,2
PRINT "physicalmodifier.......character  char key ";
PRINT "ShLk Ctrl Caps Shift NumLk Scroll Alt ";
PRINT "LeftSg LeftCt RightSh RightCt"
REPEAT
  A%=3DFNdeep_inkey(100)
  :
  PRINT FNb0(A%,32);
  PRINT " ";FNh0(A% AND &1FF,3);" ";FNc(A% AND &FF);
  PRINT " ";FNh0((A%>>24),2);
  :
  PRINT " ";FNonf(A% AND (1<<23),"ShLk");
  PRINT " ";FNonf(A% AND (1<<22),"Ctrl");
  PRINT " ";FNonf(A% AND (1<<20),"Caps");
  PRINT " ";FNonf(A% AND (1<<19),"Shift");
  PRINT " ";FNonf(A% AND (1<<18),"NumLk");
  PRINT " ";FNonf(A% AND (1<<17),"Scroll");
  PRINT " ";FNonf(A% AND (1<<16),"Alt");
  :
  PRINT " ";FNonf(A% AND (1<<15),"LeftSh");
  PRINT " ";FNonf(A% AND (1<<14),"LeftCt");
  PRINT " ";FNonf(A% AND (1<<12),"RightSh");
  PRINT " ";FNonf(A% AND (1<<11),"RightCt");
  :
  PRINT
UNTIL0
:
:
DEFFNb0(A%,N%):LOCAL A$,B$,L%:B$=3D"0":IFA%<0:B$=3D"1":A%=3DA%AND&7FFFFFFF
REPEATA$=3DSTR$(A%AND1)+A$:A%=3DA%DIV2:L%=3DL%+1:UNTILL%>30:=3DRIGHT$(B$+A$=
,N
%)
:
DEFFNh0(A%,N%)=3DRIGHT$("00000000"+STR$~A%,N%)
:
DEFFNc(A%):IF A%<32 OR A%=3D127:=3D"^"+CHR$(A%EOR64) ELSE =3DCHR$A%+" "
:
DEFFNonf(A%,A$):IFA%:=3DA$ ELSE =3DSTRING$(LENA$,"-")
:

JGH
0
Reply jgh2 (974) 6/7/2012 12:29:37 AM

>>  SYS "OS_Byte",&7A TO void%,key%


>just do: SYS "OS_Byte",&7A TO ,key%

>Any returned values you want to ignore can be just ignored
>by skipping the variable to deposit it into after the TO,
>just as any parameters you want to ignore when calling can
>also be skipped by skipping the variable before the TO, and
>zero will be used instead.

That's OK when you've only got a single comma like that I suppose, but
counting commas with tired eyes causes mistakes to be made in my
experience, so I always use something like void%, especially when I'm
still coding stuff... Once development is complete, I may well remove
stuff like that on production code so to speak, but I just find
actually specifying something makes it easier to understand what's
going on. Maybe that's just me!

Again... The setbit() / clrbit() & tstbit() routines are just there to
aid development. I originally encapsulated them like that, as my first
use for them was part of a tutorial I was planning, but never actually
materialised. The idea being that they, themselves, were a library
that could be loaded by the pupil's code and be referenced by names
that actually meant something to them. I had planned to explain what
their purpose was as part of the particular lesson, but, like I said,
nothing ever came of it. Once I have a set of building blocks like
that I tend to be a bit lazy, and just re-use code. So it was
something that just got re-used.
0
Reply usenet9920 (358) 6/7/2012 11:37:11 PM

On 25 May 2012 as I do recall,
          Gazza  wrote:

> Turns out that character case isn't important. Funny... I could have
> sworn it was...
[snip]

*I* could have sworn that character case was important in Moria... how
else do you tell the difference between a bat and a Balrog?

In a turn-based dungeon crawl, on the other hand, I shouldn't have
thought that keyboard scanning speed was terribly significant.

-- 
Harriet Bazley                     ==  Loyaulte me lie ==

One man tells a falsehood, a hundred repeat it as true.
0
Reply bazley (1301) 6/8/2012 7:55:12 AM

On Jun 8, 8:55=A0am, Harriet Bazley <baz...@feathermail.co.uk> wrote:
> On 25 May 2012 as I do recall,
> =A0 =A0 =A0 =A0 =A0 Gazza =A0wrote:
>
> > Turns out that character case isn't important. Funny... I could have
> > sworn it was...
>
> [snip]
>
> *I* could have sworn that character case was important in Moria... how
> else do you tell the difference between a bat and a Balrog?
>
> In a turn-based dungeon crawl, on the other hand, I shouldn't have
> thought that keyboard scanning speed was terribly significant.
>
> --
> Harriet Bazley =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D=3D =A0Loyaulte=
 me lie =3D=3D
>
> One man tells a falsehood, a hundred repeat it as true.

What I meant when I said character case didn't matter was that there
were no lowercase CTRL combos used, so from a keyboard scanning
perspective scanning for lowercase CTRL combos wasn't req'd
0
Reply usenet9920 (358) 6/8/2012 8:16:16 AM

On 07/06/2012 01:29, jgharston wrote:
> REM FNdeep_inkey(time%) and FNdeep_get
> REM ----------------------------------
> REM Returns -1 if no key pressed within time% in centiseconds
> REM  or b0-b8  : character code (b8=1 if function/editing key)
> REM     b9     : reserved
> REM     b10    : RightAlt
> REM     b11    : RightCtrl
> REM     b12    : RightShift
> REM     b13    : LeftAlt
> REM     b14    : LeftCtrl
> REM     b15    : LeftShift
> REM     b16    : Alt pending
> REM     b17    : Scroll Lock
> REM     b18    : NumLock
> REM     b19    : Shift
> REM     b20    : Caps Lock
> REM     b21    : reserved
> REM     b22    : Ctrl
> REM     b23    : Shift Lock
> REM     b24-b31: physical key pressed

I was stimulated by the earlier discussion to look into this as a 
possible extension to Basalt, and I wrote an INKEYS keyword that as a 
statement does:

   INKEYS delay TO charcode%,status%,modifiers%,internalkey%

or as a function does:

   deepkey%=INKEYS(delay)

The format of deepkey% is almost exactly the same as your specification 
above. ;-)

Because it takes little code to do in assembler, these also activate the 
function/cursor keys and restore the previous state on completion, as 
well as disabling Esc and Break so that these can return values. I 
looked at doing this in BASIC alone, but it would be horribly extended.

0
Reply steve3677 (307) 6/8/2012 11:00:45 AM

Finally got something working. I'm now using the <code>=<code>EOR64
method as a catch all, but still using scan-codes where ASCII codes
cause conflicts. E.g ^TAB and ^I or ^ENTER and ^M. I'm sure there are
others, I'll add these as I test what I've coded today.
0
Reply usenet9920 (358) 6/8/2012 4:00:24 PM

If JGH is reading this, can I have permission to publish his code
please? Then I can post the finished library.
0
Reply usenet9920 (358) 6/11/2012 11:14:07 PM

Gazza <usenet@garethlock.com> wrote:

> SYS"OS_Byte",&CA,0,&FF TO void%,key% 
> shift%=(shift%<<1)OR((key%AND16)>>4)  
> shift%=(shift%<<1)OR((key%AND16)>>2)   
> SYS"OS_Byte",&7A TO void%,key%         
> mask%=(char% OR (key%<<24) OR (shift%<<11)) 

Just a brief comment here; I don't know how this routine copes if someone is
typing as it runs, but I would have thought it would be better practice to
keep the time-delay between the two SYS"OS_Byte" calls as brief as possible.
 
Also I'd have used SYS calls with SWI numbers rather than names, so as to
avoid wasting time looking those up on every call, ie have something like

 SYS os_byte% ...                (having set the swi numbers earlier)

and I'd have coded:

 SYSos_byte%,&CA,0,&FF TO void%,ky1%
 SYSos_byte%,&7A TO void%,ky2%
 shift%=(shift%<<1)OR((ky1%AND16)>>4)  
 shift%=(shift%<<1)OR((ky1%AND16)>>2)           
 mask%=(char% OR (ky2%<<24) OR (shift%<<11)) 


-- 
Jeremy C B Nicoll - my opinions are my own.

Email sent to my from-address will be deleted. Instead, please reply
to newsreplyaaa@wingsandbeaks.org.uk replacing "aaa" by "284".  
0
Reply jn.nntp.scrap007 (392) 6/16/2012 7:18:15 PM

On 16 June, 20:18, Jeremy Nicoll - news posts
<jn.nntp.scrap...@wingsandbeaks.org.uk> wrote:
> Just a brief comment here; I don't know how this routine copes if someone=
 is
> typing as it runs, but I would have thought it would be better practice t=
o
> keep the time-delay between the two SYS"OS_Byte" calls as brief as possib=
le.
>
> Also I'd have used SYS calls with SWI numbers rather than names, so as to
> avoid wasting time looking those up on every call, ie have something like
>
> =A0SYS os_byte% ... =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(having set the swi nu=
mbers earlier)
>
> and I'd have coded:
>
> =A0SYSos_byte%,&CA,0,&FF TO void%,ky1%
> =A0SYSos_byte%,&7A TO void%,ky2%
> =A0shift%=3D(shift%<<1)OR((ky1%AND16)>>4)
> =A0shift%=3D(shift%<<1)OR((ky1%AND16)>>2)
> =A0mask%=3D(char% OR (ky2%<<24) OR (shift%<<11))
>
> --
> Jeremy C B Nicoll - my opinions are my own.
>
> Email sent to my from-address will be deleted. Instead, please reply
> to newsreply...@wingsandbeaks.org.uk replacing "aaa" by "284".

I understand where you're coming from... The reason that it was coded
this way, was that it was going in a library. By doing it this way,
you reduce the number of variables required, and therefore defined.
Lowering the memory footprint. As far as coping with typing is
concerned, we're dealing with INKEY< or GET. Both return one value at
a time. In theory, crude typing can be achieved by looping with the
GET variation of the call and processing the resulting bitmask for
each iteration of the loop. This routine however, is only part of the
story.

I hope to be able to make the library available from the UMoria
progress page (http://www.garethlock.com/acorn/umoria ) in time...
0
Reply usenet9920 (358) 6/17/2012 11:08:24 PM

Gazza wrote:
> If JGH is reading this, can I have permission to publish his code
> please? Then I can post the finished library.

Yes, go ahead. Library version available at mdfs.net/blib/DeepKey and
mdfs.net/blib/DeepKey.txt

JGH
0
Reply jgh2 (974) 6/18/2012 12:12:30 AM

Gazza <usenet@garethlock.com> wrote:

> I understand where you're coming from... The reason that it was coded this
> way, was that it was going in a library. By doing it this way, you reduce
> the number of variables required, and therefore defined. Lowering the
> memory footprint.

You must mean something different from what I'd expect by "memory footprint"
then.  The local vars in a FN or PROC are allocated from the stack for the
duration of the FN/PROC's execution and freed when it returns, so it makes
no difference.  

Of course allocating an extra variable will take fractionally longer, but
there are lots of other things in your code which will be slow, eg the time
taken by the interpreter to locate long-named variables, rather than ones
with shorter names.  Using the built in vars like A% B% C% etc might make
more sense (though not aid understanding).  

(Maybe you're going to crunch the code which would help speed it up.) 


> As far as coping with typing is concerned, we're dealing with INKEY< or
> GET. Both return one value at a time. In theory, crude typing can be
> achieved by looping with the GET variation of the call and processing the
> resulting bitmask for each iteration of the loop. This routine however, is
> only part of the story.

I think you misunderstand my point.  I'm not asking how your code would work
if it was intended to read multiple characters, but pointing out that a user
making unwanted keypresses (pressing or releasing Caps-Lock or Num-Lock)
while the code is between OS-Byte calls will (I think) cause a problem.  It
just seemed to me that shortening the time interval between the OS_Byte
calls would be sensible. 


-- 
Jeremy C B Nicoll - my opinions are my own.

Email sent to my from-address will be deleted. Instead, please reply
to newsreplyaaa@wingsandbeaks.org.uk replacing "aaa" by "284".  
0
Reply jn.nntp.scrap007 (392) 6/18/2012 3:45:47 AM

On 18/06/2012 00:08, Gazza wrote:
> I understand where you're coming from... The reason that it was coded
> this way, was that it was going in a library. By doing it this way,
> you reduce the number of variables required, and therefore defined.
> Lowering the memory footprint.

Always get the functionality right before optimising, whether it's for 
speed or memory use.

---druck
0
Reply news5802 (523) 6/18/2012 5:41:18 PM

jgharston wrote:
> Yes, go ahead. Library version available at mdfs.net/blib/DeepKey and
> mdfs.net/blib/DeepKey.txt

Grr. That should be mdfs.net/blib/DeepKey and mdfs.net/blib/Docs/
DeepKey.txt

JGH
0
Reply jgh2 (974) 6/18/2012 8:24:14 PM

druck wrote:
> Always get the functionality right before optimising, whether it's for
> speed or memory use.

Rules of optimisation:
i) Don't.
ii) Don't yet.

JGH
0
Reply jgh2 (974) 6/18/2012 8:26:36 PM

On Jun 18, 4:45=A0am, Jeremy Nicoll - news posts
<jn.nntp.scrap...@wingsandbeaks.org.uk> wrote:
>
> I think you misunderstand my point. =A0I'm not asking how your code would=
 work
> if it was intended to read multiple characters, but pointing out that a u=
ser
> making unwanted keypresses (pressing or releasing Caps-Lock or Num-Lock)
> while the code is between OS-Byte calls will (I think) cause a problem. =
=A0It
> just seemed to me that shortening the time interval between the OS_Byte
> calls would be sensible.
>
> --
> Jeremy C B Nicoll - my opinions are my own.
>
> Email sent to my from-address will be deleted. Instead, please reply
> to newsreply...@wingsandbeaks.org.uk replacing "aaa" by "284".

Made a few minor changes based on your suggestions, shortened variable
names, added an extra variable and moved the two OS_Byte calls next to
each other. I'd actually manually shortened variable names in other
parts of the library already. I think I left that routine as it was,
as I was posting it, or parts of it here. So... In order for it to be
easily followed, I maintained the longer, more descriptive names.
Doing it this way, I've also managed to reduce the manual bit zapping
towards the end of the routine a bit too.

The completed library can be found here...

http://www.garethlock.com/acorn/umoria/libkeyb.zip

0
Reply usenet9920 (358) 6/18/2012 9:49:55 PM

48 Replies
44 Views

(page loaded in 0.671 seconds)

12/13/2012 12:31:09 PM


Reply: