[comp.sys.amiga] DEADKEYS

ans@well.UUCP (Anne Schweizer) (12/27/87)

******* POSTING THIS FOR A FRIEND OF MINE ***********************************


        FROM: boxdiger@altger.UUCP (Patrick Guelat)
        UUCP: ...mcvax!unido!altger!boxdiger
                                       ^g
        Unix System V don't allow names longer than 8 chars... ACK ! 

/* FLAME MODE ON */

When XY have the idea to write a texteditor or an other program for the
amiga which needs keyboard input, XY have to fight against several
problems. XY use a swiss keymap (ch1) and wants to support it. He also
wants RAW input, (coz of the cursor keys... :-) ). XY isn't an official
developper of amiga software, so he didn't get Amiga Mails..(especially
Amiga Mail July/August 87). XY heard (on the net) about something called
Deadkeys... XY owns a few manuals about AMY .. (RK series..), but the 
stuff in it seems to be very very old... ( 1.1 whot's that ?!?! )......
BUT XY WANNA USE DEADKEYCONVERT() !!!! But XY don't know how !

GETTING RID OF C-A, XY BOUGHT AN UGLY ATARI... which don't support keymaps :-)

/* FLAME MODE OFF */

I'm actually writing a program to design setmap compatible keymaps.
( I had the idea while examining Bryce Nesbitt's sample source
  code for a setmapable keymap. )

The program works fine, hunk generation no longer a problem (solved
yesterday ... >>2 ACK I HATE BCPL <<2 ). You can use all features
of keymapping, that means all KCF_ Types.. (eg. KCF_SHIFT) except of
KCF_DEAD !!!!, you can choose which keys shall be repeatable, which
keys shall be capsable and so on. BUT I DON'T KNOW HOW TO CONSTRUCT
THE DATA FOR A KCF_DEAD Type key.... !!

Why can't C-A mail the Amiga Mail's to usenet or BIX ?!
How can I get them ?! If I want to have them, how long will I have to
wait ?!.

How do I use DeadKeyConvert() ? How can the user take advantage of
Deadkeys ? 

THIS IS HELP CALL TO CATS PEOPLE.. 

Thanks a lot in advance...
                      - Pat

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\  Patrick Guelat, living in Switzerland, using a German system...   /
/  UUCP: ..mcvax!unido!altger!{althh!}boxdiger                       \
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

dillon@CORY.BERKELEY.EDU (Matt Dillon) (12/28/87)

/*
 *  DEADKEYCONVERT()
 *
 *  Using RawKeyConvert() and DeadKeyConvert()
 */

#include <exec/types.h>
#include <exec/io.h>
#include <intuition/intuition.h>

struct Device *ConsoleDevice;

typedef struct IOStdReq CIO;

/*
 *  The global ConsoleDevice must be initialized before
 *  RawKeyConvert() and DeadKeyConvert() can be used.
 */

init()
{
    CIO     cio;

    OpenDevice("console.device", -1, &cio, 0);
    ConsoleDevice = cio.io_Device;
}

/*
 *  NOTE: For some reason DeadKeyConvert()/RawKeyConvert() seem to get
 *  confused about the REPEAT flag, therefore the flag bit should be
 *  cleared from the qualifier set before calling this function.
 *
 *  msg     -intuition RAWKEY message
 *  buf     -buffer to store result
 *  bufsize -size of buffer
 *  keymap  -keymap to use or NULL for default
 *
 *  returns:	-2	illegal message
 *		-1	buffer not large enough
 *		0..N	# bytes placed in buffer
 */

DeadKeyConvert(msg,buf,bufsize,keymap)
struct IntuiMessage *msg;
UBYTE *buf;
int bufsize;
struct KeyMap *keymap;
{
    static struct InputEvent ievent = { NULL, IECLASS_RAWKEY };
    if (msg->Class != RAWKEY)
	return(-2);
    ievent.ie_Code = msg->Code;
    ievent.ie_Qualifier = msg->Qualifier;
    ievent.ie_position.ie_addr = *((APTR *)msg->IAddress);
    return(RawKeyConvert(&ievent,buf,bufsize,keymap));
}

kodiak@amiga.UUCP (Robert R. Burns) (12/29/87)

In article <8712272146.AA27035@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
> *  NOTE: For some reason DeadKeyConvert()/RawKeyConvert() seem to get
> *  confused about the REPEAT flag, therefore the flag bit should be
> *  cleared from the qualifier set before calling this function.

I suggest that the proper way to phrase this is that RawKeyConvert uses the
REPEAT flag of the input event.  If the input event represents a repeat of
a key, and the keymap specifies that the key is not, in fact, repeatable,
then the resulting conversion is (correctly) of zero length.  You may, of
course, know that you want the conversion anyway and force REPEAT to zero.

If RawKeyConvert is, in fact, confused, I'd like to know more about it.

- Bob

dillon@CORY.BERKELEY.EDU (Matt Dillon) (12/29/87)

:> *  NOTE: For some reason DeadKeyConvert()/RawKeyConvert() seem to get
:> *  confused about the REPEAT flag, therefore the flag bit should be
:> *  cleared from the qualifier set before calling this function.
:
:I suggest that the proper way to phrase this is that RawKeyConvert uses the
:REPEAT flag of the input event.  If the input event represents a repeat of
:a key, and the keymap specifies that the key is not, in fact, repeatable,
:then the resulting conversion is (correctly) of zero length.  You may, of
:course, know that you want the conversion anyway and force REPEAT to zero.
:
:If RawKeyConvert is, in fact, confused, I'd like to know more about it.
:
:- Bob

	I sent a note to Jim Mackraz on this after he asked.  Actually, I
made one mistake.... DeadKeyConvert() *does* handle the REPEAT flag 
correctly.  I thought it hadn't when DME stopped repeating the RETURN key
when I switched over to DeadKeyConvert() but as it turns out, the RETURN
key isn't supposed to repeat.  Still, it was something I wanted so I
defeated the flag before calling DeadKeyConvert() in DME.

	The two *real* bugs are:

	-(1) the new additions to the numeric keypad in the A500/A2000
	keyboard are not flagged as being in the numeric keypad.  This
	is an absolute *must* to distinguish the two without resorting
	to making assumptions on the keycodes (the keycodes are different,
	of course).

	-(2) It is difficult to use RawKeyConvert() as an inverse function
	due to it's lack of bounds checking and the duplication of many
	keys.  
	
	That is, rather than write a huge amount of code to decipher the 
	keymap, I simply call RawKeyConvert() with Code values 0 thru 127,
	and with and without the shift/numeric keypad qualifier flags set
	to create an upper/lower case keycode conversion table.  BUT since
	RawKeyConvert() doesn't return an error when I give, say, the keycode
	for the '*' on the NON-numeric keypad, but WITH the numeric keypad flag
	set, I get duplicates and have to make assumptions as to some of
	the keycodes.

	Also the RETURN key is mapped into two different keycodes.... for
	one key. 

					-Matt

carolyn@cbmvax.UUCP (Carolyn Scheppner CATS) (12/30/87)

In article <4863@well.UUCP> ans@well.UUCP (Anne Schweizer) writes:
>
>******* POSTING THIS FOR A FRIEND OF MINE ***********************************
>[lots of ranting and raving]
>
>Why can't C-A mail the Amiga Mail's to usenet or BIX ?!

We post some AmigaMail articles and programs to usenet and BIX.  
Of course, THEN we get complaints from developers that AmigaMail is
"redundant" and contains "no new information".  Can't win, I guess.
I do feel that more AmigaMail articles should be posted, but perhaps
after the issue is delivered.

>How can I get them ?! If I want to have them, how long will I have to
>wait ?!.

AmigaMail subscription (1 year = 6 issues) is $20 US within US, $25 US outside
of US.  Make check out to Commodore Business Machines.

   Mail to:     CATS - AmigaMail
                Lauren Brown
                CBM
                1200 Wilson Drive
                West Chester, PA  19380
                USA



As for back issues, we plan to put together all issues through Dec 87
into a spiral bound book and sell it as a support item.  We'll let
everyone know when that's available.

>How do I use DeadKeyConvert() ? How can the user take advantage of
>Deadkeys ? 
>
>THIS IS HELP CALL TO CATS PEOPLE.. 

DeadKeyConvert() has already been posted.  For more info, here's the
International Keyboard Input article that appeared in AmigaMail.

---------------------------------------------------------------------------


                       INTERNATIONAL KEYBOARD INPUT
                       ============================
                    Eric Cotton and Carolyn Scheppner

        The Amiga computers are sold internationally with a variety of
     local keyboards which match the standards of particular countries.
     The 1.2 Enhancer manual contains diagrams of the keyboards which
     are currently distributed.  If you examine the diagrams, you will
     notice that some letters and special symbols are in different
     physical positions on various keyboards.  For instance, on the
     German and Italian keyboards, the "Y" and "Z" keys are swapped
     when compared to the USA keyboard.  Since the physical position
     of a key determines the raw key code that it generates, straight
     RAWKEY input is not internationally compatible.

        The 1.2 Amiga console device supports national keyboards by 
     providing mapping of raw key codes to the proper acscii characters 
     and strings as specified in a Keymap.  In addition, the console 
     device provides handling of the "deadkeys" used to generate accented 
     characters.  Any keyboard input which is processed by the console
     device will be automatically translated to the installed keymap.
     The new 1.2 Setmap command is used to install the default keymap
     to be used by the console device.  If you wish to experiment with
     the national keymaps, the KeyToy program on Extras 1.2 provides
     a graphic simulation of the current various keyboards.
     
        All of the national Keymaps, including USA, contain "deadkeys". 
     A deadkey is generally an ALT/letter combination which specifies 
     that a particular accent mark is to be placed on the next character 
     typed.  The ASCII values for these characters are all greater than 
     127 and they can be seen in the International Character Codes table 
     in the AmigaDOS manual.  If a deadkey is used to request an invalid 
     accent for a character, the normal unaccented character results.

        If you look at the "usa" keyboard diagram in the Enhancer manual,
     you'll see that the F, G, H, J, and K keys (shadowed) are defined 
     as deadkeys.  In the diagram, various accent marks are printed in 
     the lower half of each of these keys.  Pressing ALT and one of these
     shadowed keys is a request for the illustrated accent to be placed 
     on the next character you type.

       For example, with the default usa keymap (try from CLI):

         ALT/F (') then A  results in an A accented with '
         ALT/H (^) then E  results in an E accented with ^
         ALT/J (~) then C  results in a plain C (invalid accent for C)


        Under 1.2, the console.device, IDCMP VANILLAKEY, and AmigaDOS
     CON: and RAW: all provide automatic handling of deadkeys and
     translation of raw keycodes to ASCII based on the current keymap.
     If your software requires non-VANILLA keys such as the cursor and
     function keys, using console device keyboard input in your Intuition 
     window will allow you to receive the escape sequences generated
     by these keys.  If you are using IDCMP RAWKEY input in international
     software, you must properly use the console devices's RawKeyConvert()
     function to get keymap translation and deadkey handling.  See the
     example DeadKeyConvert() in the 1.2 Enhancer manual (P. 65) or the 
     1.2 Readmes.  Use NULL for the kmap argument to get translation to
     the currently installed Keymap.
 
        Be sure to test your code with ASCII characters > 127 (such as 
     accented characters like ALT/F A) wherever your code accepts keyboard
     input to insure that your logic and data structures work properly 
     with high ASCII values.  In addition, test your code after using 
     SetMap to install various keymaps, using the Enhancer manual keyboard
     diagrams as a guide for what the keycaps would show in that country.
     You won't be able to test all of the keys of some national keyboards,
     but you can test enough keys to be sure you are getting translation.

        The following information is a supplement to the Console Device
     chapter of the Rom Kernel Manual, describing the Keymap format and
     console.device handling of deadkeys.  The page, section, and figure
     numbers in this supplement are correct for the Addison-Wesley ROM
     Kernel Manual: Libraries and Devices. 


Dead-Class Keys

The term "dead-class key" refers to keys that either modify or can themselves
be modified by other dead-class keys.  There are two types of dead-class keys:
dead and deadable.  A dead key is one which can modify the key pressed im-
mediately following.  For example, on the German keyboard there is a dead key
marked '` that when followed by (for instance) the 'A' key will produce the
character 'a' (International Character Code $E0).  A deadable key is one that
can be prefixed by a dead key.  The 'A' key in the previous example is a
deadable key.  Thus, a dead key can only affect the output of a deadable key.

For any key that is to have a dead-class function, whether dead or deadable,
the qualifier KCF_DEAD flag must be included in the entry for the key in the
KeyMapTypes table.  The KCF_DEAD type may also be used in conjunction with
the other qualifiers.  Furthermore, the key's KeyMap table entry must contain
the longword address of the key's dead-key descriptor data area in place of
the usual 4 ASCII character mapping.

Below is an excerpt from the AMIGA 1000 German key map.  It will be referenced
in the following discussion.


			Example 4-2: Dead-Class Keys

	new LoKeyMapTypes:
		DC.B	KCF_DEAD+KCF_SHIFT+KCF_ALT+KCF_CONTROL  ;aA (Key 20)
			    ...			;(more...)
		DC.B	KCF_DEAD+KCF_SHIFT+KCF_ALT+KCF_CONTROL	;hH (Key 25)
			    ...			;(more...)

	new LoKeyMap:
		DC.L	key20			; a, A, ae, AE
                            ...                 ;(more...)
		DC.L	key25			;h, H, dead ^
			    ...			;(more...)

	;------ possible dead keys
	key25:
		DC.B	0,'h',0,'H'		;h, H
		DC.B	DPF_DEAD,3,DPF_DEAD,3	;dead ^
		DC.B	0,$08,0,$08,0,$88,0,$88	;control translation
			    ...			;(more...)

	;------ deadable keys (modified by dead keys)
	key20:
		DC.B	DPF_MOD,key20u-key20	;deadable flag, number of
						;bytes from start of key20
						;descriptor to start of un-
						;shifted data

		DC.B	DPF_MOD,key20s-key20	;deadable flag, number of
						;bytes from start of key20
						;descriptor to start of shift-
						;ed data

		DC.B	0,$E6,0,$C6		;null flags followed by rest
		DC.B	0,$01,0,$01,0,$81,0,$81	;of values (ALT, CTRL...)
	key20u:
		DC.B	'a',$E0,$E1,$E2,$E3,$E4	;'a' alone and characters to
						;output when key alone is
						;prefixed by a dead key
	key20s:
		DC.B	'A',$C0,$C1,$C2,$C3,$C4	;SHIFTed 'a' and characters to
						;output when SHIFTed key is
						;prefixed by a dead key



In the example, key 25 (the 'H' key) is a dead key and key 20 (the 'A' key) is
a deadable key.  Both keys use the addresses of their descriptor data areas as
entries in the LoKeyMap table.  The LoKeyMapTypes table says that there are
four qualifiers for both: the requisite KCF_DEAD, as well as KCF_SHIFT,
KCF_ALT, and KCF_CONTROL.  The number of qualifiers determine length and
arrangement of the descriptor data areas for each key.  Table 4-8 below shows
how to interpret the KeyMapTypes for various combinations of the qualifier
bits.  For each possible position a pair of bytes is needed.  The first byte
in each pair tells how to interpret the second byte (more about this below).


		Table 4-8: Dead Key Qualifier Bits

If type is:	Then the pair of bytes in this position in the dead-class key
		descriptor data is output when the key is pressed along with:

NOQUAL		alone	-	-	-	-	-	-	-
A		alone	A	-	-	-	-	-	-
C		alone	C	-	-	-	-	-	-
S		alone	S	-	-	-	-	-	-
A+C		alone	A	C	A+C	-	-	-	-
A+S		alone	S	A	A+S	-	-	-	-
C+S		alone	S	C	C+S	-	-	-	-
S+A+C (VANILLA)	alone	S	A	S+A	C	C+S	C+A	C+S+A

	NOTE: the abbreviations A, C, S stand for ALT, control, and SHIFT,
	respectively.  Also note that the ordering is reversed from that in
	the normal KeyMap table.


Because keys 20 and 25 each use three qualifier bits (not including KCF_DEAD),
according to the table there must be 8 pairs of data, arranged as shown.
Had only KCF_ALT been set, for instance, (not including KCF_DEAD), just two
pairs would have been needed.

As mentioned earlier, the first byte of data pair in the a descriptor data
area specifies how to interpret the second byte.  There are three possible
values: 0, DPF_DEAD and DPF_MOD.  In Example 4-2 DPF_DEAD appears in the data
for key 25,  while DPF_MOD is used for key 20.  It is the use of these flags
which determines whether a dead-class key has dead or deadable function. A
value of zero causes the unrestricted output of the following byte.

If the flag byte is DPF_DEAD, then that particular key combination (determined
by the placement of the pair of bytes in the data table) is dead and will mod-
ify the output of the next key pressed (if deadable).  How it modifies is
controlled by the second byte of the pair which is used as an index into into
part(s) of the data area for ALL the deadable (DPF_MOD set) keys.

Before going further, an understanding of the structure of a descriptor data
area wherein DPF_MOD is set for one (or more) of its members is necessary.
Referring to the example, we see that DPF_MOD is set for the first and second
pairs of bytes.  According to its LoKeyMapTypes entry, and using Table 4-8 as
a guide, these pairs represent the alone and SHIFTed values for the key.  When
DPF_MOD is set, the byte immediately following the flag must be the offset
from the start of the key's descriptor data area to the start of a table of
bytes describing the characters to output when this key combination is preced-
ed by any dead keys.  This is where the index mentioned above comes in.  The
value of the index from a prefixing dead key is used to determine which of the
bytes from the deadable keys special table to output.  The byte in the index+1
position is sent out.  (The very first byte is the value to output if the key
was not prefixed by a dead key.)  Thus, if ALT'ed H is pressed (dead) and then
SHIFTed A, an 'A' will be output.  This is because: 

	o  The byte pair for the ALT position of the H key (key 25) is
	   DPF_DEAD,3 so the index is 3.
	o  The byte pair for the SHIFT position of the A key (key 20) is
	   DPF_MOD,key20s-key20, so we refer to the table-of-bytes at key20s.
	o  The third+1 byte of the table-of-bytes is $C2, a 'A' character.

Note that the number of bytes in the table-of-bytes for all deadable keys must
be equal to the highest index value of all dead keys plus 1.





        
     

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Carolyn Scheppner -- CATS   >>Commodore Amiga Technical Support<<
                     UUCP  ...{allegra,ihnp4,rutgers}!cbmvax!carolyn 
                     PHONE 215-431-9180
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=