### 1.6 Lisp Functions Invoked from Graphics ¶

It is possible to make certain areas of a window mouse sensitive, or to run commands on reception of certain events such as keystrokes, while the focus is in a certain window. This is done by having a lisp function invoked or some lisp form evaluated. We shall refer to such a lisp function or form as a command.

For example

    (button '.button :text "Hello" :command '(print "hi"))
    (button '.jim :text "Call Jim" :command 'call-jim)

In the first case when the window `.button` is clicked on, the word "hi" will be printed in the lisp to standard output. In the second case `call-jim` will be funcalled with no arguments.

A command must be one of the following three types. What happens depends on which type it is:

‘`function`’

  If the value satisfies `functionp` then it will be called with a number of arguments which is dependent on the way it was bound, to graphics.

‘`string`’

  If the command is a string, then it is passed directly to TCL/TK for evaluation on that side. Lisp will not be required for the evaluation when the command is invoked.

‘`lisp form`’

  Any other lisp object is regarded as a lisp form to be eval’d, and this will be done when the command is invoked.

The following keywords accept as their value a command:

       :command
       :yscroll    :yscrollcommand
       :xscroll    :xscrollcommand
       :scrollcommand
       :bind

and in addition `bind` takes a command as its third argument, see See bind.

Below we give three different examples using the 3 possibilities for a command: functionp, string, and lisp form. They all accomplish exactly the same thing. For given a frame `.frame` we could construct a listbox in it as:

    (listbox '.frame.listbox :yscroll 'joe)

Then whenever the listbox view position changes, or text is inserted, so that something changes, the function `joe` will be invoked with 4 arguments giving the totalsize of the text, maximum number of units the window can display, the index of the top unit, and finally the index of the bottom unit. What these arguments are is specific to the widget `listbox` and is documented See listbox.

`joe` might be used to do anything, but a common usage is to have `joe` alter the position of some other window, such as a scroll bar window. Indeed if `.scrollbar` is a scrollbar then the function

    (defun joe (a b c d)
      (.scrollbar :set a b c d))

would look after sizing the scrollbar appropriately for the percentage of the window visible, and positioning it.

A second method of accomplishing this identical, using a string (the second type of command),

    (listbox '.frame.listbox :yscroll ".scrollbar set")

and this will not involve a call back to lisp. It uses the fact that the TK graphics side understands the window name `.scrollbar` and that it takes the option `set`. Note that it does not get the `:` before the keyword in this case.

In the case of a command which is a lisp form but is not installed via `bind` or `:bind`, then the form will be installed as

    #'(lambda (&rest *arglist*) lisp-form)

where the lisp-form might wish to access the elements of the special variable `*arglist*`. Most often this list will be empty, but for example if the command was setup for `.scale` which is a scale, then the command will be supplied one argument which is the new numeric value which is the scale position. A third way of accomplishing the scrollbar setting using a lisp form is:

    (listbox '.frame.listbox :yscroll '(apply '.scrollbar :set *arglist*))

The `bind` command and `:bind` keyword, have an additional wrinkle, see See bind. These are associated to an event in a particular window, and the lisp function or form to be evaled must have access to that information. For example the x y position, the window name, the key pressed, etc. This is done via percent symbols which are specified, see See bind.

    (bind "Entry" "<Control-KeyPress>" '(emacs-move  %W %A ))

will cause the function emacs-move to be be invoked whenever a control key is pressed (unless there are more key specific or window specific bindings of said key). It will be invoked with two arguments, the first %W indicating the window in which it was invoked, and the second being a string which is the ascii keysym which was pressed at the same time as the control key.

These percent constructs are only permitted in commands which are invoked via `bind` or `:bind`. The lisp form which is passed as the command, is searched for the percent constructs, and then a function

    #'(lambda (%W %A) (emacs-move %W %A))

will be invoked with two arguments, which will be supplied by the TK graphics server, at the time the command is invoked. The `*arglist*` construct is not available for these commands.