XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  Keyman  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

          A small but powerful key manager library for the HP48  

Keyman supports three additional key-press options: shift-hold, the double-
click (like a double mouse-click), and a long-touch, i.e. the key is pressed 
somewhat longer. The library may be stored in any port  provided SmartKeys is
not present whose key-management is obsolated by Keyman. Some library commands
do different things, depending on whether they are pressed normally or a bit
longer. This will be explained in detail in the text below.
----------------------------------------------------------------------
NEW in vs 1.2003 (with high probability final version)
Longhold-functionality improved, see below. 

NEW in vs 9.2002 
Option KEVL renamed to KE?R (= KeyEval or Record). If normally pressed or in
a program EVALs a key. If longpressed, initiates a key recorder, see below. 

NEW in vs. 2.2001
An option KEVL is added. Runs like KEYEVAL for the HP49, see below. Older key
assignments based on shifthold must be reprogrammed: KEVL is now XLIB 1616 7
which has become XLIB 1616 10. A?D deflates the internal UserKeys list now
optimally and saves still more bytes to the benefit of the user. 

Description of the library commands
=============================================================================
|IfSH| Needs two arguments, arbitrary objects O2 and O1 in Level 2 and 1. Puts
       a program on the stack which, if assigned to shifted key, evaluates O2 
       if the key is pressed while the shift is hold (RS, LS or alpha), and O1
       else. Here RS abreviates Right-Shift and LS Left-Shift. The assignment 
       says << If shift is hold while beeing pressed I execute O2, else O1 >>. 
       Here the program delimiters are somewhat misused since this and infact
       no Keyman-option can be programmed in UsrRPL. Be careful in assigning 
       alpha-shifthold keys for character keys. The habit of printing letters
       while holding down alpha, may cause a problem. See Example 6.

|IfD?L| Needs two arguments, arbitrary objects O2 and O1 in Level 2 and 1. If
       this option is normally clicked it puts a program on the stack saying
       << If I am double-clicked I perform O2, otherwise O1 >>. However, if
       |IfD?L| is pressed a bit longer then a program is put onto the stack
       saying << If I am pressed a bit longer then I perform O2, else O1 >>. 
       It is indicated which of the two options (IfD or IfL) was chosen. The 
       output of |IfD?L| must perhaps be processed with |->TO?|, see below,
       also for examples of application. It's a matter of habit whether long-
       hold or double-click is prefered. About 0.3_s are needed to detect a 
       double-click. Also shifted keys can make a double-click decision. In 
       this case, you may double click the shift key as well. If the single-
       click option is wanted, a next key should not be pressed too rapidly 
       as this may erronously be interpretated as a double-click on the first
       key. For a shifted key assigned with a long-hold option, release the 
       shift before long-pressing the key. Otherwise the key press may be 
       interpreted as a shift-hold, and that may be a different
action. 


|IfE?P| Comprises of the former Keyman options |IfE| and |IFP|. Needs two 
       arguments, arbitrary objects O2 and O1 in Level 2 and 1. If the key
       is pressed normally then it puts a program onto the stack which, if 
       assigned to a key, evaluates O2 if the key is hit in  *edit mode* 
       (i.e., a command line or edit line exist, no matter whether or which 
       indicators are shown on top of the screen), and O1 else. Such a task-
       splitting is indispensable in assigning a cursor key which clearly 
       must preserve its functionality in the edit mode. In these cases O2 
       is usually the standard assignment of the key to be assigned which is 
       obtained with |SA| below. If |IfE?P| is pressed somewhat longer then
       a program is put onto the stack which, if assigned to a key, evaluates 
       O2 if the key is pressed in PRG-mode and O1 else. Which option was 
       chosen is always displayed ("IfEdit" or "IfPRG"). As above, O2 will 
       mostly be the standard assignment of the key and should not be a user-
       defined program (the key would then beep in PRG-mode), while strings,
       numbers and other objects are printed in the command line while in edit
       mode. If then the assigned key is hit without PRG-indicator, the edit 
       line is evaluated and O1 (not O2) is executed. Thus, choose carefully 
       between the two options. The output of either option must perhaps be 
       processed with |->TO?| before assigning it, see the next paragraph.

|->TO?| Puts a so-called TakeOver on to of any object. It mostly looks like 
       the original since the TakeOver command is unvisible at the user level. 
       If the output is assigned to a key or part of a temporary menu, it is
       directly evaluated in every mode. In a composition of the If-options 
       (see the Examples) only the output of the last used If-option, not of 
       its components, must be processed with |->TO?| before assigning it, to 
       achieve activity in all modes. If |->TO?| is pressed a bit longer then
       UnLockAlpha (system command to leave the alpha-mode) is put on top of 
       the object. Useful for assigning alpha-shifted keys, Example 6 below.

|A?D|  Assigns or deleates a key. If pressed normally, waits for a key-press 
       to assign the object in Level 1 to this key; if longer pressed waits 
       for a key to deleate its assignment. It is indicated whether the key 
       will assign or deleate. |A?D| errors if the AsnK-mode was chosen with 
       empty stack. The DelK option automatically fixes an old bug: it cleans
       UserKeys, making the procedure RCLKEYS-0-DELKEYS-STOKEYS recommended in
       Chapter 30 of the HP48-Manual dispensable. Moreover, the UserKeys list 
       will be deflated which saves several hundert bytes, in general.

|RclK| Pressed normally, invokes the user assignment of the key asked for. If
       long-hold, |RclK| yields the list of all user-assigned keys. Thus, you
       can always keep trace on the current assignment situation. |RclK| is a
       good example for getting a fealing for the long-hold option.

|SA|   Calls the (usually unreadable) standard assignment of a key into the 
       stack, menu keys included, and displays both its type and the type name
       of the assigned object. If this is a library name (alias rompointer), 
       then also its content is recalled and an asterix is appended to the 
       displayed content's type name. E.g., |SA| applied to itself displays
       "8: Program*", with the |SA|-program on Level 1 and the lib-name |SA| 
       on Level 2. With |SA| one may hack the commands of any library without
       splitting it as a whole. |SA| must be assigned to a key to ensure the 
       access to all menu keys (Example 3a below). Standard assignments of 
       operation- and function-keys are mostly lib names, not the operation 
       itself. E.g., pressing SIN after |SA| yields SIN on two levels, but 
       they are not the same! The SIN in Level 2 is the lib-name of the SIN-
       function in Level 1. It makes a difference whether a rompointer or its
       content is taken as a possible argument O2 for |IfE?P|. Only the first 
       will be printed in programming mode, the program will be executed. 

|KE?R| Normally takes a real of the form rp.c - If positive, runs the assigned
       key rc.p or the standard assignment if the key is not user-assigned. If
       negative, executes the standard key in any case. Useful for launching,
       e.g., the editor in a program, by 35.1 KE?R (or if 35.1 is assigned, by
       -35.1 KEVL), or the PLOT dialog box by 63.3 KEVL etc. NEW SINCE 9.2002:
       If longpressed, KE?R serves as a key-recorder, recording key-presses in
       a SysRPL-program (essentially a sequence of system binaries). A record 
       can only be ended with the CANCEL key. At most 15 key-presses -  their
       number is shown in the header - can be recorded in sequence. A record
       can directly be replayed or be used as an argument for the If-options.
       VERY IMPORTANT: Also keys valid only in a closed environement like the
       interactive stack are recorded, see Example 7.

What is particularly interesting in Keyman is the possibility of composing the
If-options (Examples 5,6). This yields an inexhaustible variety of possible 
assignments. It also generates pretty exercises in logical reasoning and is, 
at the same time, of great practical value. This is completely independent on
whether one can or cannot read the programs created with the If-options. The
only what has to be kept in mind is how they where created and combined.

-------------------------------------------------------------------------
Examples of applications - many of these examples are present in Topkeys,
a collection of useful key assignments for the HP48.  
-------------------------------------------------------------------------

1. |IfSH|.  Key 23.3 invokes the MODES dialog box. One has to pass through it
to launch the perhaps more often used Flag Browser. Hence, it would be more 
convenient get into the Flag Browser directly with RShold 23.3. No problem 
with |IfH?D|. Put the standard assignment of 23.3 onto Level 1 and put a key
record of launching the flag browser in level 2. Apply |IfH?D| on these two
arguments, process with |->TO?| and assign to 23.3. This assignment tells us
<< If the shift is hold I enter the flag browser else the MODES dialog box >>.
You may also put the program take use the program << # B41CFh LIBEVAL >> as 
the argument in level 2. This example is "RSH I FlagBr" in TopKeys.

2a. |IfD?L| double-click. Suppose you need the MATRX-menu very often. Put the 
program <<5 MENU>> onto Level 2, the standard assignment of the MTH-key onto
Level 1 (a SysRPL-Program), press |IfD?L| (you see IFD at the top), process 
with |->TO?| and assign the the MTH-key. Then in all modes, MTH double-clicked
invokes the MATRX-menu. Clearly, the same method lets you invoke the MATRX-
menu with MTH long-pressed instead of double-clicked. 

2b. |IfD?L| long-hold. It is convenient to have all important Keyman options
on key K (UParrow). Invoke of the Keyman library on alpha K longhold, say.
Put << 1616 MENU >> on level 2 after having processed this program with ->TO?
longhold; this adds a alpha-off to it (to avoid that setting Keyman leaves us
in alpha-mode). Next put the standard assignment of alpha K (the character K)
on level 1, press |IfD?L| somewhat longer so that you see IfL and process the
result with ->TO? short pressed. Finally, assign this unreadable program to
alpha K. It says << Normally pressed I do what I did before, no matter whether
already in Edit mode or not. But if longhold I set the Keyman menu, no matter
whether in Edit mode or not >>. Remember to release the alpha key before you
press K longhold outside edit mode. Otherwise you put only K in the editor.

3a. |IfE/P|. Key 25.3 (RS K or RS STACK) serves no purpose in default mode 
(also 25.1 enters the stack). This is a suitable key for assigning |RclK|. 
Clearly, in the edit mode 25.3 must keep is cursor moving function. Thus, put
the standard assignment of 25.3 on Level 2 and the lib-name |RclK| to Level 1 
(both obtained with |SA|). Press |IfE/P| not too long, process with |->TO| and
assign the output to 25.3. Then in the default mode, this key is asking for a 
key to get its assignment (or to get the list of assigned keys if longhold)
while in edit mode the key preserves its cursor moving function. The standard-
assignment of a key is conveniently recalled assigning <<If shift-hold then 
do SA else invoke the stack menu>> to left-shift K. Procede as in Example 1.

3b. Suppose you have program, XPUR say, which purges everything what can be 
purged. Put the PURGE command on Level 2, <<"PURGE" "{" INPUT OBJ-> XPUR>>
on Level 1 and press |IfE/P| long. Assign the result to the LS-PURGE-key 53.2. 
Then in the default mode this key waits for entries of names into a list for 
purging, while in PRG-mode the key keeps printing PURGE. In a similiar manner,
one may assign LS CLEAR and LS DROP, both dispensable in the default mode. 

4. |->TO?|, stand alone application. Apply |->TO?| to the command UPDIR on the 
stack. The result has the same look in the stack. Assign it to the UPDIR- or
any other key. Then this key does a desired UPDIR also in the edit mode.

5. Combining options. An easy but handy and very natural composition example 
of the above If-options is <<If in edit mode then move cursor left else if 
pressed normal go UPDIR and if long-pressed then go HOME>>, assigned to the 
LeftArrow key 34.1. The PICTURE environement, presently launched with 34.1, 
can as conveniently be entered also with LS LeftArrow 34.2. The assignment 
is made by applying IfL to HOME (Level 2) and UPDIR (Level 1), next putting 
the standard assignment of 34.2 onto Level 2 and then processing with |IFE| 
and finally with |->TO?|. A slightly improved version of this assignment is
contained in Topkeys under the title "P UPDIR REPEAT". 

6. If one wants to visit a large stack it is convenient to go with longhold UP
at once to the highest level. This is manually done by [UP][RS][UP]. We make a
key-record of the 3 key-presses with longhold KE?R. Put the record on Level 2,
the standard assignment of the UP key on Level 1, apply IfL, process this with
->TO and assign to the UP key. This is item "O K ->STKTop" from TopKeys.
-------------------------------------------------------------------------
REMARK. The outputs of the If-options can also be used as subprograms in 
temporary menus to make, for instance, a longhold decision with a menu key. 
Such menus cannot be compiled with ENTER anymore, but can easily be formed 
on the interactive stack as explained in several other tools, e.g. OT4. 

CREDITS. Some If-options were first realized in SmartKeys by Simone Rapisarda.
The ASM-codes used in shift-hold and longhold are written by Jonathan Busby.
--------------------------------------------------------------------------
 Wolfgang Rautenberg   raut@math.fu-berlin.de   www.math.fu-berlin.de/~raut   

                                        

