Go to the previous, next section.

Tcl/Tk Interface

The tcltk library package is a bidirectional interface to the Tcl (pronounced Tickle) language and the Tk toolkit. Tcl is an interpreted scripting language with many extension packages, in particular the graphical interface toolkit Tk.

You can read about Tcl/Tk in [Ousterhout 94] or in various articles. The articles and the Tcl/Tk system can be found by anonymous FTP at ftp.cs.berkeley.edu or harbor.ecn.purdue.edu.

To load the package, enter the query:

| ?- use_module(library(tcltk)).

The `library/tcltk/README' contains up-to-date information on how to include Tcl/Tk extensions.

Prolog to Tcl

To use Tcl, you must create a Tcl interpreter object and send commands to it. The following predicate executes a single Tcl command:

test_command(Command, Result) :-
        tcl_new(Interp),
        tcl_eval(Interp, Command, Result),
        tcl_delete(Interp).

The Tcl command and its arguments is specified in Command (see section Command Format), and the result will be returned as a string (list of character codes) in Result.

These are the predicates to use Tcl/Tk from Prolog:

@
Creates a new interpreter, initializes it and returns a reference to it. If you don't have a standard Tcl installation you can tell tcl_init/1 where to look for the initialization files by setting the environment variable TCL_LIBRARY.

@
Deletes an interpreter and the memory used by it.

@
Lets TclInterpreter interpret the command specified by Command. The result will be stored as a string (list of character codes) in Result.

@
This call is similar to tcl_eval/3. Events is a list of terms stored from Tcl by the prolog_event command (see section Tcl to Prolog).

Command Format

A Tcl command is specified as follows:

Command           --> Atom           { other than [] }
                          | Number
                          | chars(PrologString)
                          | write(Term)
                          | format(Fmt,Args)
                          | dq(Command)
                          | br(Command)
                          | sqb(Command)
                          | ListOfCommands

ListOfCommands    --> []
                          | [Command|ListOfCommands]

where

@
@
denote their printed representations.

@
denotes the string represented by PrologString (a list of character codes).

@
denotes the string that is printed by the corresponding built-in predicate.

@
denotes the string that is printed by the corresponding built-in predicate.

@
denotes the string specified by Command, enclosed in double quotes.

@
denotes the string specified by Command, enclosed in braces.

@
denotes the string specified by Command, enclosed in square brackets.

@
denotes the strings denoted by each element, separated by spaces.

Examples of command specifications and corresponding translations:

'set x 32'
        ==> set x 32

[set,x,br([a,b,c])]
        ==> set x {a b c}

['.panel.value_info.name',configure,'-text',br(write('$display'/1))]
        ==> .panel.value_info.name configure -text {$display/1}

Tcl to Prolog

There are two new Tcl commands defined in this library:

@
Goal is a string containing the printed representation of a Prolog goal. The goal will be called in the user module unless it is prefixed with another module name. The call is always deterministic. The result of the call is returned as:

@
if execution succeeds. The value of any of the variables in the goal that is bound to a term will be returned to Tcl in the array prolog_variables with the variable name as index.

Note that the value is always a string, even if the result from Prolog is a complex term.

@
if the execution fails.

@
if a Prolog exception is raised. The error message will be "Prolog Exception: " appended with a string representation of the Prolog exception.

An example:

test_callback(Result) :-
        tcl_new(Interp),
        tcl_eval(Interp,
                 'if {[prolog "foo(X,Y,Z)"] == 1} \\
                     {lappend res $prolog_variables(X) \\
                                  $prolog_variables(Y) \\
                                  $prolog_variables(Z)}',
                 Result),
        tcl_delete(Interp).

foo(1, bar, 4.2).

The query

| ?- test_callback(Result).

will succeed, binding Result to:

        "1 bar 4.200000"

  • prolog_event Terms... Terms are strings that contain the printed representation of Prolog terms. These are stored in a queue and retrieved as Prolog terms by tcl_event/3 or tk_next_event/2-3.
  • An example:

    test_event(Event) :-
            tcl_new(Interp),
            tcl_event(Interp, [prolog_event,dq(write(zap(42)))], Event),
            tcl_delete(Interp).
    

    The query

    | ?- test_event(Event).
    

    will succeed, binding Event to the list [zap(42)]

    Tk

    The following example is a simple "Hello, world" program:

    tk_hello_world :-
            tk_new([], Interp),
            tcl_eval(Interp, 
                     'button .b -text "Hello" -command "destroy ."', _),
            tcl_eval(Interp, 'pack .b', _),
            tk_main_loop,
            tcl_delete(Interp).
    

    The program brings up a tiny window with a button labeled "Hello" and is terminated by pressing the button.

    These are the predicates to use Tk from Prolog:

    @
    Performs basic Tcl and Tk initialization and creates the main window of a Tk application. If you don't have a standard Tk installation you can tell tk_new/2 where to look for the initialization files by setting the environment variable TK_LIBRARY. Options is a list of optional elements according to:

    @
    Event handling will be installed in the Prolog top-level loop. This means that Tk windows and the Prolog prompt can be simultaneously active.

    @
    Sets the Tk application name. The application name will be displayed in the main window and is also used for communicating between applications in Tk. Default name is an empty string.

    @
    Gives the name of the screen on which to create the main window. Default is normally determined by the DISPLAY environment variable.

  • tk_main_window(+TclInterpreter, -TkWindow) Gets a reference to the main window of the application using this interpreter.

  • tk_make_window_exist(+TkWindow) This will force a window to be mapped to the screen, i.e. it will force it to show up immediately. Normally, mapping is delayed as long as possible.

  • tk_destroy_window(+TkWindow) Destroys a window or widget.

  • tk_num_main_windows(-NumberOfWindows) Returns the number of main windows currently in use.

  • tk_do_one_event
  • tk_do_one_event(+ListOrBitmask) Passes control to Tk for handling a single event. This predicate may be called to give Tk time for handling the windows. You can specify what events to handle in a List of event flags or in a Bitmask as specified in the Tk documentation. The flags you can have in List are:

    @
    Don't wait for new events, process only events that are ready.

    @
    Process X events.

    @
    Process Tk's file events.

    @
    Process timer events.

    @
    Process Tk_DoWhenIdle callbacks.

    @
    Process any event.

    tk_do_one_event/0 is equivalent to tk_do_one_event/1 with all flags set. If the tk_dont_wait flag is set and there is no event to handle, the call will fail.

    It is straight-forward to define a predicate which handles all events in the queue and then returns:

    tk_do_all_events :-
            tk_do_one_event, !,
            tk_do_all_events.
    tk_do_all_events.
    

    tk_do_one_event/0-1 is an interface to the Tk C-function TkDoOneEvent().

  • tk_next_event(+TclInterpreter, -Event)
  • tk_next_event(+ListOrBitmask, +TclInterpreter, -Event) Processes events until there is at least one Prolog event associated with TclInterpreter. Event is the term corresponding to the head of a queue of events (strings representing terms) stored from Tcl with the prolog_event command (see section Tcl to Prolog). Only events associated with TclInterpreter are returned; other events remain in the queue. If there are no windows left the term [] will be returned. This predicate does not correspond directly to any Tcl/Tk C function.

  • tk_main_loop Passes control to Tk until all windows are gone.

  • There are basically two alternatives for invoking Prolog actions on user events. The first is to directly call Prolog by means of the Tcl command prolog. Tcl/Tk must then be repeatedly invoked, either by calling tk_main_loop/0 or using the option top_level_events, possibly in conjunction with calling tk_do_one_event/0-1 in lengthy computations.

    The second alternative is using the Tcl command prolog_event. The user program then, by calling tk_next_event/2-3, passes control to Tcl/Tk until one or more invocations of prolog_event has occurred. The Prolog event determines the Prolog action to take. This approach has the advantage that context variables might be passed around in the event loop.

    Go to the previous, next section.