home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol1 / input / amykeymaps next >
Text File  |  1990-01-26  |  8KB  |  275 lines

  1. (c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice, and 
  3. is provided "as is" without warranty of any kind, either expressed or implied.  
  4. The entire risk as to the use of this information is assumed by the user.
  5.  
  6.  
  7.  
  8.                  Amiga Keyboard Input and Keymaps
  9.  
  10.                       by Bryce Nesbitt
  11.  
  12.  
  13. There are at least 15 different keyboard configurations for the Amiga.
  14. If you want your application to be internationally compatible, it will
  15. have to work properly with all of these.  Supporting the various keyboards 
  16. is not difficult - here are the main points to keep in mind.
  17.  
  18.  
  19.  
  20. RAWKEY
  21.     
  22. If your program processes Intuition RAWKEY messages, it is written 
  23. incorrectly.  Raw key codes give physical positions, they do not tell you
  24. anything about what is marked on the top of the key.  With 15 different 
  25. keyboard configurations available for the Amiga, the chances are good 
  26. that your program will not be accepting the input you thought when it
  27. processes raw key codes.
  28.  
  29. It is okay to use RAWKEY messages directly for positional control like the 
  30. up, down, left, and right controls for a game.  But do not use RAWKEYs
  31. for entering any sort of text.  RAWKEY messages can be converted to the 
  32. proper codes with the DeadKeyConvert() function.  See the program listed 
  33. below for more on this.
  34.  
  35.  
  36.  
  37. VANILLAKEY
  38.  
  39. If you don't want the problems of RAWKEYS, just change RAWKEY to VANILLAKEY
  40. in your program.  The keys will be converted to the values in the current 
  41. keymap.  The disadvantage is that you will only get the keys that map to a 
  42. single character.  This eliminates the function, help, and cursor keys.
  43.  
  44.  
  45. CONSOLE DEVICE, CON:, RAW:, CLI, String Gadgets
  46.  
  47. The console device, CON:, RAW:, CLI, and String Gadgets all provide
  48. automatic keymap conversion.  Nothing else is needed.
  49.  
  50.  
  51. DEAD KEYS
  52.  
  53. Dead keys are a feature of V 1.2 Kickstart.  They are used to add accents
  54. to letters.  To try this out, click into a CLI.  Press and release "ALT-K".  
  55. Now press a letter key such as "a".  The video display should show an "a"
  56. with an umlaut.  This is an automatic feature of the keymap conversion
  57. process.  Be sure to test to see if accented characters work in your 
  58. application.
  59.  
  60.  
  61. CUSTOM KEYMAPS
  62.  
  63. Custom keymaps must be placed in the "devs:keymaps" drawer, and activated 
  64. with the SetMap command.  If your program needs to change a keymap during 
  65. execution, it must copy the current map, modifiy it, then use the modification.
  66.  
  67.  
  68. THE NEW MACHINES
  69.     
  70. The A500 and A2000 computers add 5 new keys to the keyboard, all on the 
  71. numeric keypad.  The symbols on these 5 keys will vary depending on what 
  72. country the machine is sold in.  For the United States, the "usa1" keymap 
  73. supports all the extra keys.  The "usa2" keymap provides the same features 
  74. with a Dvorak layout.  As of V1.2, Kickstart itself had not been updated 
  75. to support the extra keys, or to return the "NUMERICPAD" quailifer when 
  76. the extra keys are pressed.
  77.  
  78.  
  79. DISTRIBUTION DISKS
  80.  
  81. If you distribute your program on a Workbench disk, it should contain the
  82. SetMap program and the devs:keymaps drawer.  This allows a person to 
  83. set up the keymaps to match their keyboard.  Better yet, allow the user to 
  84. boot up with their normal Workbench, and click on your icon to start.
  85.  
  86. Some of the old international A1000 keyboards do not have the same symbols 
  87. on the tops of keycaps as the new international A500/A2000 keyboards.  Owners 
  88. of these machines will need to copy their keymap over to your application
  89. disk.
  90.  
  91.  
  92.  
  93.  
  94. -------Setup needed to use DeadKeyConvert--------
  95. /* Manx users must remove the "ConsoleDevice" line from functions.h */
  96. struct Device    *ConsoleDevice;
  97. struct IOStdReq console_IO;    /* empty, zeroed IOStdReq */
  98. ....
  99.     if ( OpenDevice("console.device",-1L,(struct IORequest *)&console_IO,0L) )
  100.     cleanexit(21);
  101.     ConsoleDevice=(struct Device *)console_IO.io_Device;
  102. ....
  103.     if (ConsoleDevice)  CloseDevice  ((struct IORequest *)&console_IO);
  104. ....
  105.  
  106. ----------------DeadKeyConvert.c----------------
  107. #include "exec/types.h"
  108. #include "devices/inputevent.h"
  109. #include "intuition/intuition.h"
  110.  
  111. /*
  112.  * DeadKeyConvert().  Adapted from the Amiga Enhancer Manual
  113.  * by Bryce Nesbitt.
  114.  *
  115.  * Takes an Intuition RAWKEY message and processes it.
  116.  * The result will be "cooked" keys and key conversions in
  117.  * your buffer.
  118.  *
  119.  * The console.device must be open to use this function.
  120.  *
  121.  * The message passed to this must be of Class RAWKEY.
  122.  * Returns -1 if the buffer overflowed, or the
  123.  * number of characters converted if all was ok.
  124.  *
  125.  */
  126. long DeadKeyConvert(msg,kbuffer,kbsize,kmap)
  127. struct IntuiMessage *msg;    /* Message to be converted  */
  128. UBYTE            *kbuffer;    /* Pointer to your buffer   */
  129. long            kbsize;    /* Size of your buffer        */
  130. struct KeyMap        *kmap;    /* Custom keymap, or Zero   */
  131. {
  132. struct InputEvent ievent;
  133.  
  134.     /* if (msg->Class != RAWKEY) return(-2); */
  135.     if (msg->Code & IECODE_UP_PREFIX)
  136.     return(0);  /* Nothing to do for key up messages */
  137.  
  138.     /* pack message into an input event */
  139.     ievent.ie_NextEvent =0;
  140.     ievent.ie_SubClass    =0;
  141.     ievent.ie_Class    =IECLASS_RAWKEY;
  142.     ievent.ie_Code    =msg->Code;
  143.     ievent.ie_Qualifier =msg->Qualifier;
  144.  
  145.     /* get previous codes from location pointed to by IAddress
  146.      * this "magic" pointer is valid intil the IntuiMessage is
  147.      * replied */
  148.     ievent.ie_position.ie_addr =*((APTR*)msg->IAddress);
  149.  
  150.     return(RawKeyConvert(&ievent,kbuffer,kbsize,kmap));
  151. }
  152.  
  153.  
  154. ----------------Complete example-----------------
  155.  
  156. /*
  157.  * 29-Jan-88 Bryce Nesbitt
  158.  *
  159.  * WARNING: In order to compile this program, Manx Aztec C needs to have the
  160.  * line in functions.h that declares "ConsoleDevice();" removed.
  161.  *
  162.  */
  163. #undef LATTICE_4   /* Change to #undef for Manx */
  164. #ifdef LATTICE_4
  165. #include "proto/exec.h"
  166. #include "proto/intuition.h"
  167. #else
  168. #include "functions.h"
  169. extern int Enable_Abort;
  170. #endif
  171. #include "exec/types.h"
  172. #include "intuition/intuition.h"
  173.  
  174.  
  175. struct IntuitionBase *IntuitionBase;
  176. struct GfxBase         *GfxBase;
  177. struct Device         *ConsoleDevice;
  178.  
  179. static char buffer[16];         /* buffer to convert into */
  180. struct IOStdReq     console_IO;     /* empty, zeroed IOStdReq */
  181. struct NewWindow    MyNewWindow=
  182.     {
  183.     0,11,200,32,
  184.     1,3,
  185.     RAWKEY|CLOSEWINDOW,
  186.     WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG|
  187.     SIMPLE_REFRESH|NOCAREREFRESH|ACTIVATE,
  188.     0,0,
  189.     (UBYTE *)"Keymapper",
  190.     0,0,
  191.     64,64,
  192.     -1,-1,  /* No need to limit window growth */
  193.     WBENCHSCREEN,
  194.     };
  195. struct Window        *MyWindow;
  196. struct IntuiMessage *message;
  197.  
  198.  
  199.  
  200. #ifdef LATTICE_4
  201. CXBREAK()       /* Disable break for Lattice C */
  202. {
  203.     return(0);
  204. }
  205. #endif
  206.  
  207.  
  208.  
  209. void cleanexit(value)
  210. int value;
  211. {
  212.     if (MyWindow)       CloseWindow  (MyWindow);
  213.     if (IntuitionBase)  CloseLibrary ((struct Library *)IntuitionBase);
  214.     if (GfxBase)        CloseLibrary ((struct Library *)GfxBase);
  215.     if (ConsoleDevice)  CloseDevice  ((struct IORequest *)&console_IO);
  216.  
  217.     exit(value);
  218. }
  219.  
  220.  
  221.  
  222. void main()
  223. {
  224. long temp;
  225.  
  226. #ifndef LATTICE_4
  227.     Enable_Abort=0;
  228. #endif
  229.  
  230.     if (!( IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33L) ))
  231.     cleanexit(20);
  232.     if (!( GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",33L) ))
  233.     cleanexit(20);
  234.     if (!( MyWindow=OpenWindow(&MyNewWindow) ))
  235.     cleanexit(20);
  236.  
  237.     /*
  238.      *
  239.      * It is not mentioned in the manuals, but the console.device may be
  240.      * opened without attaching it to a window.   To do this, open the device
  241.      * with a unit of -1 and zeroed IOStdReq block.  The console.device
  242.      * pointer will be returned in io_Device.
  243.      *
  244.      * The console.device is also a library... the returned pointer will
  245.      * be used to make calls to it.
  246.      *
  247.      */
  248.     if ( OpenDevice("console.device",-1L,(struct IORequest *)&console_IO,0L) )
  249.     cleanexit(21);
  250.     ConsoleDevice=(struct Device *)console_IO.io_Device;
  251.  
  252.     for(;;)
  253.     {
  254.     WaitPort(MyWindow->UserPort);   /* Wait for one or more messages */
  255.     while( message=(struct IntuiMessage *)GetMsg(MyWindow->UserPort) )
  256.         {
  257.         switch (message->Class)
  258.         {
  259.         case RAWKEY:
  260.             strcpy(&buffer,"               "); /* clear out buffer */
  261.             temp=DeadKeyConvert(message,&buffer,15L,0L);
  262.             Move(MyWindow->RPort,66L,22L);
  263.             Text(MyWindow->RPort,&buffer,15L);
  264.             break;
  265.  
  266.         case CLOSEWINDOW:
  267.             cleanexit(0);
  268.         }
  269.         ReplyMsg((struct Message *)message);
  270.         }
  271.     }
  272. }
  273.  
  274.  
  275.