home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / keyboard / a228_1 / !KeyChange / KeyCodes < prev    next >
Text File  |  1992-02-08  |  14KB  |  233 lines

  1.  
  2.                             The Keycode Story
  3.                             =================
  4.                         
  5.                                    or
  6.                               
  7.                    How to get more from your keyboard
  8.                    ==================================
  9.  
  10. The PRM isn't very forthcoming about the way the keyboard is handled, so
  11. this file attempts to explain how things work, as well as giving the
  12. rationale for the way the KeyChange module works. The information was
  13. gleaned from VERY careful reading of the "Character Input" section of the
  14. PRM (among others), plus quite a lot of experimentation, but I don't
  15. guarantee that it's all exactly right. The main problems are that the PRM
  16. fails to distinguish between things done by the keyboard handler and by
  17. OS_ReadC (which are logically quite distinct), and fails to make very clear
  18. what codes are inserted into the keyboard buffer in different conditions.
  19. All page references are to the 1st edition (issue 1) PRM.
  20.  
  21.   To begin with, it's very important to understand the difference between
  22. five concepts:
  23.   
  24. 1) Function keys - these are the physical red (or grey) keys along the top
  25.    of the keyboard, the Print and Insert keys (F0 and F13 in disguise), and
  26.    the cursor, Page Up/Down, copy and tab keys (if you set them up
  27.    appropriately).
  28.  
  29. 2) Function key strings (or expansions) - these are the strings assigned to
  30.    the variables Key$0 to Key$15 with *Key or whatever, that get used when
  31.    you hit a function key outside the desktop. These aren't usually used in
  32.    the desktop environment.
  33.    
  34. 3) Function key (buffer) codes - these are the codes inserted into the
  35.    keyboard buffer when you hit a function key. They are in the range
  36.    &80-&FF.
  37.    
  38. 4) Top-bit-set characters - these are also in the range &80-&FF, but are
  39.    just treated as normal characters. They are distinguished from function
  40.    key codes in the buffer by being preceded by a zero (ASCII NUL), as
  41.    described below.
  42.    
  43. 5) Codes returned by OSReadC - these are what your program will normally
  44.    see. Normal and top-bit-set characters are just returned as they stand,
  45.    but function key codes can be treated in different ways - discarded,
  46.    translated into a function key string, returned as a NUL followed by the
  47.    code (allowing them to be distinguished from top-bit-set characters),
  48.    or returned as a top-bit-set character (although not necessarily the one
  49.    with the same code!).
  50.    
  51. Confused? You will be ...
  52.  
  53.   Things start with a keyboard interrupt whenever you press or release a
  54. key. This can be trapped as event 11 (see p. 122), which gives you a
  55. hardware keycode which is different for every key on the keyboard, and tells
  56. you if the key went down or up. It also gives you a keyboard driver ID, but
  57. no information is given about it, so this isn't very helpful. This means
  58. that the KeyChange module may not work with non-UK keyboards, although there
  59. is a gap for an extra code between left-Shift and "Z", so maybe all is OK.
  60. (Do Acorn make any other keyboards, anyway?) It may also help to know that
  61. the row and column legends on the table are the wrong way around, i.e. the
  62. numbers along the top are the high byte and the ones down the side are the
  63. low byte.
  64.  
  65.   Unfortunately, the event is purely informational, so you can't alter the
  66. keycode at this stage. The BBC micro had a Key Vector which did let you
  67. change the code, but this seems to be the only vector that didn't make it
  68. from the beeb. The PRM does say that you can replace the keyboard handler
  69. completely, but "[i]t is outside the scope of this manual to discuss this
  70. procedure in depth" (p. 468). How can anything be outside the scope of the
  71. PRM?
  72.  
  73.   Anyway, the keyboard handler translates the hardware code into a buffer
  74. code, except for shifting and locking keys, and escape and break if enabled.
  75. Escape is a story in itself; see the table on p. 472. The shift and lock
  76. keys just change an internal flag, which (sometimes) modifies the code
  77. produced by the other keys. You can change the code produced by the tab key
  78. with OS_Byte 219, and (to a very limited extent) those produced by the
  79. keypad with OS_Bytes 238 and 254. Apart from this, the code that enters the
  80. keyboard buffer is that given in the table on p. 520, EXCEPT that ASCII NUL
  81. (Ctrl-@) is entered as two NUL characters in a row. Incidentally, note that
  82. the Page Up/Down keys are effectively just shifted versions of the up/down
  83. cursor keys.
  84.  
  85.   Furthermore, if you have the InternationalKeyboard module enabled, it
  86. allows you to use the Alt keys as shifting keys with various normal keys to
  87. get top-bit-set characters, and to type ASCII codes on the keypad. These
  88. codes are entered into the keyboard buffer as TWO characters, a NUL followed
  89. by the top-bit-set character. Alt with keys that don't give a top-bit-set
  90. character don't give a buffer code at all. If you *Unplug or *RMKill the
  91. InternationalKeyboard module, Alt keys make no difference to the keycode
  92. generated by other keys, and top-bit-set characters can't be typed (as far
  93. as I know). [By this I mean that you can't put them in the buffer; as
  94. described below, OS_ReadC can return function key codes as top-bit-set
  95. characters. You could also put them in by hand with OS_Byte 138.] The fact
  96. that these characters are entered with a preceding NUL means that you can
  97. distinguish top-bit-set characters from function key codes, a vitally
  98. important fact!
  99.  
  100.   Once the code is emitted by the keyboard handler you can start
  101. manipulating it, by grabbing either the buffer insert or buffer remove
  102. vector. KeyChange uses buffer insert, as it needs to know about shifting
  103. keys; codes can be removed from the buffer a long time after they're
  104. inserted, so you might have taken your finger off the shift key by then! The
  105. two vectors are otherwise more-or-less equivalent, as nothing happens to the
  106. codes in between. The main thing to remember is that any code preceded by a
  107. NUL has to be passed unchanged, assuming you only want to mess around with
  108. function key codes. Incidentally, if you pull characters out of the buffer
  109. directly with OS_Byte 145 you'll see the nulls, but OS_ReadC and everything
  110. that calls it deals with translated codes.
  111.  
  112.   The buffer insertion code is called in IRQ mode, and another thing that
  113. the PRM fails to make clear is whether you can call the OS_Bytes which check
  114. the keyboard status (e.g. OS_Byte 121 or 202) in this case. The description
  115. says "interrupt status is not altered", which looks OK, but also says
  116. "re-entrancy not defined". What exactly is the difference between
  117. "undefined" re-entrancy and non-re-entrancy? I suspect that it is OK to call
  118. them, but just to be safe KeyChange traps the key up/down event referred to
  119. earlier, and keeps its own record of the state of keys in which it's
  120. interested. [The more I use the PRM, the more I feel that Acorn have skimped
  121. on defining the entry and exit conditions for SWIs etc.; at first sight it
  122. all looks clear, but the closer you look the less certain it all gets. As a
  123. good example, I believe it to be true that the data block used in Wimp SWIs
  124. remains unchanged except where values are explicitly returned, but I'm
  125. pretty sure it does't say so anywhere. End of whinge.]
  126.  
  127.   Most programs that use the keyboard get characters with OS_ReadC, or with
  128. something like OS_ReadLine that calls it. This passes all normal codes
  129. (below &80) and all top-bit-set characters without interpretation, except
  130. for removing any leading NUL. This includes all control codes;
  131. interpretation of Return, Ctrl-U and Delete is done by OS_ReadLine, and
  132. other codes normally only have an effect once they're echoed to OS_WriteC.
  133. (In the Wimp environment all codes are just passed to tasks to deal with as
  134. they wish).
  135.  
  136.   The cursor and copy keys give buffer codes as shown in the table on page
  137. 520. Depending on the mode selected by OS_Byte 4 they either trigger cursor
  138. editing, return top-bit-set characters (not the same ones as their buffer
  139. codes), or get treated as standard function key codes. These are interpreted
  140. according to the setting of OS_Bytes 221-228; they can be discarded,
  141. expanded, returned as a NUL followed by the code (which is the opposite of
  142. how they're stored in the buffer!), or returned as top-bit-set characters.
  143. Note that any codes above &7F in function key strings are returned as
  144. top-bit-set characters, and not interpreted as function key codes.
  145.  
  146.   The Wimp adds yet another twist to all this. It programs the cursor and
  147. copy keys to be treated as normal function keys, and the tab key to give
  148. code &8A (modified appropriately by Shift and Ctrl), which you can't
  149. otherwise get from the keyboard. Note that this isn't the same as F10 due to
  150. the strange way the codes are set out; F0-F9 are &80-&89, but F10-F13 are
  151. &CA-&CD (F13 is the Insert key). Following this interpretation, F14 and F15
  152. don't really exist. However, this doesn't mean that you can't access the
  153. function key strings for F14 and F15, as only the low nibble of the code is
  154. used to determine the string used. Outside the desktop, if you program the
  155. cursor keys to act as function keys with OS_Byte 4 you can get at the F14
  156. and F15 strings with the up and down cursor keys, just as you can get the
  157. F11 and F12 strings with the left and right cursor keys. (Simple, isn't it?)
  158.  
  159.   Anyway, the Wimp also uses OS_Bytes 221-228 to make all function key codes
  160. be returned preceded by a NUL. It then internally translates this to the 32
  161. bit value passed on the Key_Pressed wimp event, which adds &100 to the code
  162. for function keys. Thus the upshot is that wimp tasks see all codes between
  163. &20 and &FF as normal characters, with control codes between &00 and &1F as
  164. usual, and function key values between &180 and &18F, giving you a possible
  165. 160 codes to use as hot keys etc. The only fly in the ointment is that,
  166. although the wimp will happily translate any function key code, you can't
  167. actually type 48 of them. I'm typing this with Deskedit, which uses all but
  168. 6 of the available function key combinations (i.e. the ones you get with the
  169. red keys), most control codes, and some extras of its own that it must get
  170. by reading the keyboard directly. Thus if you want to use a hot-key
  171. application, you're pretty restricted in your choices. Enter KeyChange!
  172.  
  173.   An initial look at the keyboard shows that the options are fairly limited,
  174. as most of the keys are in use already; the only realistic candidates for
  175. additional uses are the Alt keys, the right-hand Ctrl key, Num Lock and
  176. perhaps Scroll Lock (which doesn't appear to do anything in the desktop). To
  177. get extra "function key" codes you really need a shifting key, although I
  178. suppose you could use Scroll Lock if you ignored the LED and didn't use it
  179. outside the desktop.
  180.  
  181.   The most obvious candidates are the Alt keys, as they probably aren't used
  182. much by most people; unfortunately, with the InternationalKeyboard module
  183. active they don't generate buffer codes at all with most keys, and if you
  184. *Unplug it you can't type top-bit set characters. Thus I decided to use Alt
  185. with a fallback to the right-hand Ctrl for people who want to type
  186. top-bit-set characters.
  187.  
  188.   The next step was to see which codes you can already get, and look for the
  189. best way of generating the rest. Looking at the tables on p. 520 and p. 1198
  190. shows that under the Wimp, with the tab, cursor and copy keys producing
  191. codes rather than effects, you can get all of the codes between &80 and &BF
  192. inclusive, plus &CA-&CD, &DA-&DD, &EA-&ED and &FA-&FD. Thus you need to
  193. generate four extra codes from function keys F0-F9, plus the non-existent
  194. F14 and F15. You can do this with one shifting key, as long as you don't
  195. mind having to hit four keys to get some of the codes! With two shifting
  196. keys you could get all codes with no more than three keys pressed, but this
  197. clashed with my desire to have an option to use the right Ctrl, and would
  198. also mean that you'd have to remember which codes went with which Alt key.
  199. Anyway, you get up to another 36 codes with a maximum of three keys pressed
  200. at once, so this should be fairly acceptable.
  201.  
  202.   A further problem was that the mythical F14 and F15 are shifted versions
  203. of the up and down cursor keys. Ctrl-cursor is a standard way of moving
  204. around text in !Edit etc., and I always use the right-hand Ctrl key for this
  205. as it's obviously convenient; however, I almost never use the right-hand
  206. Ctrl with the function keys (possibly related to being right-handed). Thus I
  207. decided that when using the right-hand Ctrl key only F0-F9 would change, so
  208. you lose 8 possible codes but don't make so many mistakes! The Alt key still
  209. gives the full range, as you wouldn't normally use Alt with the cursor keys
  210. (note that this makes Alt-left cursor duplicate F12).
  211.  
  212.   Having sorted all this out, I turned to the keypad. My original idea was
  213. to use the Num Lock-off state for function keys, as there can't be many
  214. people who use this mode (or even know it exists). However, a look at the
  215. table on p. 528 shows that a) the codes it generates are bizarre, and b) the
  216. "5" key doesn't generate a code at all, which makes things difficult for a
  217. program that works by trapping buffer insertions. I therefore settled on the
  218. rather odd method of using the Num Lock-on state, and toggling between
  219. different modes with Num Lock plus Ctrl or Shift. I really don't think Acorn
  220. thought about what they were doing with the keypad! About the only useful
  221. thing is that there are 16 keys, plus Num Lock and Enter, which is just
  222. right.
  223.  
  224.   Since you don't normally use Ctrl with the keypad it's OK to use it as a
  225. shifting key for all of the function keys. Thus in either Alt or right-Ctrl
  226. mode you can generate all 128 codes, although pressing Ctrl-Ctrl-Shift-#
  227. does require you to have more than the standard number of hands!
  228.  
  229.   So, there's the rationale; I think I've done about the best that's
  230. possible, but things would have been a lot better if Acorn had provided
  231. extra shifting keys (as on the Mac, for example), if it had standardised the
  232. use of hot keys more, and if the keypad were easier to control.
  233.