home *** CD-ROM | disk | FTP | other *** search
- *************************************************************************
- * >E-Command Documents how to add commands to Zap *
- *************************************************************************
-
- As mentioned in the ReadMe file, commands are added to Zap by registering a
- table of commands when the module providing the extra commands initialises.
- You should use the call Zap_AddCommands to register the table. The table has
- the format below. All offsets are from your module start unless otherwise
- indicated.
-
- #0 Offset of table from start of module (so Zap can convert the
- offsets below into addresses).
- #4 Offset from module start of 'Zap service call code' or 0
- if none. Zap calls this entry point to tell you about
- various things - see the section below.
- #8 List of commands, terminated by a zero word. Each element
- of the list has the format:
-
- <command name>+<0 byte terminator>+
- <ZERO bytes padding until word aligned>+
- <word giving command offset from module start>
-
- The command name must be in UPPER CASE in this table. In general, command
- names are not case sensitive, but they are converted to upper case in order
- to search for them in the command tables. The characters padding to the next
- word alignment MUST be ZEROs as the table is searched through in words not
- in bytes.
-
- When a command is found in the table, its address is calculated, and
- henceforth the command is referred to by its address. This unfortunately
- means that I cannot pass the command your module workspace when the command
- is called as I do not know which module the command lies in. This is not
- usually a problem however as you may claim workspace from Zap's heap. If this
- is not sufficient, then you will just have to store the address of your
- workspace in the module itself and read it when you are called (until I work
- out a better method).
-
- The address of the command is of course the address called when the command
- is executed. However, at offset -4, the word before the first instruction of
- the command, some flags are stored. These flags determine what type of
- parameter the command takes and how the command interacts with the
- minibuffer. This word must be filled in. It's meaning is as follows:
-
- b0 Set if the command doesn't need R10 on entry (eg called from
- b1 Set if the command doesn't need R8 on entry a menu).
- b2 Set if the command doesn't need R9 on entry
- b3-b5 Argument type for the command:
- 0 = Command takes no parameters
- 1 = Command takes a list of bytes as parameter
- 2 = Command takes a list of words as parameter
- 3 = Command takes a string as parameter
- 4 = Command takes a block of data as parameter
- 5-7 reserved
- b6 Set if you wished to be called before minibuffer opened
- b7 Set if you wish to be called after every minibuffer update
- b8 Set if you wish to be called before a key is inserted into
- the minibuffer (and possibly alter it).
- b9 Set if you want TAB to complete file names in the minibuffer
- b10 Set if you may want to kill the minibuffer when it starts up.
- b11 Set if you may want minibuffer to remain open when command
- has finished.
- b12 Set if you wish universal argument to multiply R1 by n on
- calling the instruction instead of calling it n times.
- If the command takes byte or word list data then the data
- is duplicated the given number of times.
- b13 Reserved for Paul Moore's system.
- b14 Set if the command should not be executed when loading a
- file to prevent Trojans.
- b15-b31 Reserved - set to 0
-
- Bits 0-2 are used by commands which may be called from a menu, and thus may
- not be typed. You should leave them as 0.
-
- The entry/exit conditions of your command depend on your flags word as I will
- detail below. You are ALWAYS called with the following registers set up on
- entry:
-
- R3 = info flags:
- b0 Set => The last command call was to this command as well.
- (eg to spot cumulative ctrl K's/Yanks).
- b1-b27 => Reserved
- b28-b31=> Top bits of R2 when command called via
- Zap_ProcessCommand.
- R8 = window of the input caret (see E-Windows) (unless flags b1 set)
- R9 = file block associated with R8 (see E-File) (flags b2=0)
- R10 = cursor block pointer of input cursor (see E-Cursors) (b3=0)
- (This is car_cursor if the cursors are combined and
- car_input if they are split - see E-Vars).
- R13 = small FD stack
-
- And in general registers R0-R2 have the meaning:
-
- R0 = data pointer (your input)
- R1 = number of times key was pressed (all key presses are buffered)
- R2 = action code (if you have a string argument)
-
- On exit from a command you may corrupt the registers R0-R11 and the flags.
- You should return V flag set and R0=error block on error. Some of the
- minibuffer calls with R2<>0 require you to return a result in R0. To detail
- the actual meaning of R0-R2 I have partitioned into cases below. Registers
- not mentioned are undefined.
-
- If you want to call a command yourself, then please use the call
- Zap_ProcessCommand or Zap_CommandString. All calls from Zap are made by this
- method. See the file 'Commands' for the syntax used when typing a command
- into the keys file, or sending it to Zap_CommandString.
-
- Data type = None (0)
- --------------------
-
- Then R1=Number of times key pressed, and R0,R2 are not used. If the same
- command is bound to more than one key then all the buffered keypresses may
- not be due to the same key! Eg, the command UP. In the keys file it should
- appear with no parameters.
-
- Data type = Byte list (1)
- -------------------------
-
- Then R0=Pointer to a list of bytes, and R1=Number of bytes in the list. Eg,
- the command CHAR. In the keys file, the command should appear with a byte as
- parameter, eg CHAR 143 (or CHAR n where n is substituted for the key number
- it lies on). Thus if the user types A,B,C which have the commands CHAR 65,
- CHAR 66, CHAR 67 assigned to them, then the command will be called once with
- the list 65,66,67 if the keypresses were buffered.
-
- Data type = Word list (2)
- -------------------------
-
- Then R0=Pointer to a list of words, and R1=Number of words in the list. This
- works as for the byte list data type except that the command takes a word
- (4 bytes) as parameter.
-
- Data type = String (3)
- ----------------------
-
- All strings in this section are zero terminated. When you are passed R0 as
- the contents of the minibuffer, this excludes the prompt (see Zap_MiniWrite).
- In the following calls, R2 gives the action code distinguishing them.
-
- CASE 1 - A string is specified after the command in the keys file (eg INSERT
- "Hello").
-
- In this case you are called with R0=pointer to the string R1=number
- of times the key was pressed. R2=0.
-
- CASE 2 - No string specified in the keys file (eg INSERT).
-
- In this case, a minibuffer is opened for the user to type in the string for
- the command to use. Most of the flags in the flags word control the way the
- minibuffer works. If the flags in bits 6+ are all clear then everything is
- handled automatically for you and you are called with R2=1 and R0=minibuffer
- contents when the user types RETURN. The detailed workings of the minibuffer
- are described below. Please supply a prompt (use b6) where possible.
-
- The following happens before the minibuffer is opened on screen:
-
- First of all, the minibuffer is cleared. If you wish to be called at this
- point (eg to add a prompt) then set b6 of your flags word and you will be
- called with R2=6 (R0,R1 undefined, R8-R10 setup as usual). You should then
- insert your prompt using Zap_MiniPrompt. Please look at Zap_MiniWrite for
- other ways of changing the minibuffer contents. It is possible that you may
- wish to kill the minibuffer at this point, before it is opened, as an null
- argument may sometimes be acceptable. For example, the command SAVEFILE
- (Emacs CTRL-X CTRL-S) only wants to open a minibuffer if the file is untitled
- (does not have a full path name). To do this, set b10 of your flags word (in
- addition to b6) and return R0=0 to open the minibuffer as usual, or
- R0=pointer to the string argument you want the command to be executed with.
- Your command will then be called again with R2=0 and R0=the parameter you
- have passed. This method ensures that the command is learnt correctly, as
- only command calls with R2=0 or R2=1 are learnt. Minibuffer setup calls with
- R2>1 are NOT learnt when you are in 'learn a key sequence mode'.
-
- Now the minibuffer is opened on screen. The following happens when a key is
- typed by the user:
-
- If you have b7 and b8 cleared then the key is inserted into the minibuffer
- automatically. ESCAPE and CTRL-G cause the minibuffer to close (without
- calling you) and RETURN causes your command to be called as described
- below.
-
- If you want to intercept keys BEFORE they are acted on then set b8 of your
- flags word. You will then be called with R2=&8000+Zaps internal key number,
- and R0=the minibuffer contents string when the key is typed. After you have
- dealt with the key, you return a value in R0 to tell the minibuffer what to
- do with the key. There are 3 possible cases:
- R0=-1 In this case no change is made to the minibuffer. Command
- processing continues as normal (you will be called if b7
- of your flags word set etc).
- R0=key number Then the given key is acted on as if it were the one typed.
- Hence you will usually exit by SUB R0,R2,#&8000.
- R0=&8000 In this case, the minibuffer is quitted as if Return had
- +key number been pressed (ie you are called with R2=1 as described
- below). Then, AFTER the minibuffer has been closed, the
- indicated key will be acted on as if typed in the editing
- window. This enables keyboard-search to be quitted by, for
- example, up arrow or ctrl X.
- (If you just want to quit the minibuffer then return R0=&1B=ESCAPE).
- One common use of this call is to trap the TAB key for completing an entry
- (eg command name or filename). If you set b9 of your flags word, then Zap
- assumes the buffer contains a file name and automatically completes the file
- name when TAB is pressed, saving you all the work!
-
- If you want to examine the minibuffer contents AFTER the character has been
- entered into the minibuffer by Zap, you should set b7 of your flags word. You
- will then be called with R0=the minibuffer contents string, and R2=7. This
- call (as with the previous one) is made before the minibuffer contents is
- updated on screen and thus you don't need to call Zap_MiniUpdate if you alter
- the minibuffer contents. For example, search as you type (CTRL-S) uses this
- call to jump to the next match after every key press.
-
- Zap enters keys into the minibuffer until the user presses ESCAPE, CTRL-G or
- RETURN. The first two quit the minibuffer.
-
- When the user presses RETURN, you are called with R0=pointer to string typed
- into the minibuffer, and R2=1. As usual, the string pointed to by R0 does not
- include the prompt. You should then perform the command action, with this
- string as input. Usually, the minibuffer will be closed after your command
- has finished. If you wish it to remain open (eg the COMMAND command) then
- set b11 of your command word, and return R0=0 to close the minibuffer and
- R0=1 to leave it open when you exit from being called with R2=1.
-
- The codes R2=1 and R2=0 should cause the same action to take place. This is
- to ensure the LEARN function works correctly. When a learnt function is
- executed, the minibuffer will not be opened again, but the command will be
- called with R2=0 and the previously typed string as input in R0. For example,
- if you learn the sequence: ctrl-S , "wibble" , RETURN typed in the
- minibuffer, then when this is played back the command SEARCHFORWARD will be
- called with R2=0 and R0="wibble" as opposed to opening the minibuffer. Only
- command calls with R2=0 or 1 are learnt.
-
- Data type = Block (4)
- ---------------------
-
- Then R0 = pointer to a data block (of command dependant format), and
- R1=number of times key pressed. This argument type is used by the command
- MULTICOMMAND which is used internally within Zap to execute a list of other
- commands. For example, when you type a sequence of commands separated by a
- ":" in the keys file, then this is converted to the one command MULTICOMMAND
- with data block as a list of the functions to call. You cannot put such a
- command in the keys file as there is no way of specifying a data block as
- parameter.
-
-
- EXAMPLE
- -------
-
- The code below implements a simple command which asks you to enter a number
- into the minibuffer and then switches to that display mode. FNcall is a macro
- which calls the named Zap entry point (see E-Zapcalls for its definition).
-
- EQUD (3<<3)+(1<<6) \ string argument + ask for prompt
- .command_start
- STMFD R13!,{R14}
- TEQ R2,#6 \ is the minibuffer about to open
- BEQ add_prompt
- FNcall(Zap_MiniEval) \ find the number typed
- LDMVSFD R13!,{PC} \ error
- LDMCSFD R13!,{PC} \ wasn't a valid number
- FNcall(Zap_NewMode) \ change mode
- LDMFD R13!,{PC} \ finished
- .add_prompt
- ADR R0,prompt_string
- FNcall(Zap_MiniPrompt) \ insert the prompt string
- LDMFD R13!,{PC}
- .prompt_string
- EQUS "New mode: "
- EQUB 0
- ALIGN
-
- It is the offset of command_start that you must place in your command table,
- not the offset of the EQUD flags word before it. Note that the command
- performs the same action regardless of whether R2=0 or R2=1.
-
-
- Zap service calls
- -----------------
-
- If the second word in your command table is non zero then it gives the
- module offset of a 'Zap service call handler'. This code is called at
- various points to tell you about things. In general the entry/exit
- conditions are:
-
- \E R1=reason code and other registers may hold data.
- R11=undefined
- R12=Zaps workspace pointer as usual.
- \X You should preserve R1-R13 unless otherwise stated.
- R0 and flags may be corrupted.
-
- The (current) service calls are listed below. You should ignore unrecognised
- values in R1 so I can add more if necessary.
-
- R1=0
- Zap is quitting and about to kill your module. Return R0=-1 to stop it.
- Your module will NOT be automatically killed if have no service call handler
- (for backwards compatibility).
-
- R1=1
- Zap has just started but has not set up its heap yet.
-
- R1=2
- Zap has started and set up its heap. You should use this call to claim any
- workspace via Zap_Claim.
-
- R1=3
- Zap is deleting a file. R9=file block of file being deleted. (See E-File)
-
- R1=4
- Zap is deleting a window. R8=window block of window being deleted.
- (See E-Windows)
-