Using apptalk, you can initiate communication with another application
without having to know it's specific application name (as returned by
[tk appname]
). You do, however, need to know how to start the application with which
you want to communicate.
Apptalk uses logical names to associate an application (or applications)
with a particular set of functionality. If multiple applications are
running on a display, all with the same logical name, when a client request
is made you will be given the opportunity to pick which server application
to use (see the discussion on the X resource
apptalk*policy
, below).
Apptalk manages the communication by keeping track of the internal application name, and can start up an application automatically before the first command is sent to it.
apptalk init
name
, associates a logical name with the application. Logical names are used to
associate a given functionality with a program. Examples of useful logical
names are ``textedit'', ``testutil'', and so forth.
When a server is initialized, there are five commands that are created
automatically. They may be overridden by the server with appropriate
apptalk proc
commands. These predefined commands are:
exit 0
(but may be redefined by the server)
info
server command.
Within the documentation string a sequence of %N
will be replaced with the name of the server. Using %N
instead of hard-coding the server name makes it easier to rename a server,
or to cut and paste procedures between servers.
When the new command is called, all arguments are available to the
procedure via the standard tcl argument args
. The global variables
apptalkServer
and apptalkClient
are also available.
Example:
apptalk proc printargs { usage: %N printargs prints the name of the calling client, the name of the server, and each argument. } { puts stdout "client: $apptalkClient" puts stdout "server: $apptalkServer" foreach arg $args { puts stdout "argument: $arg" } }
apptalk connect tkhello
will create a command named @hello
. This command can then be used to issue commands to the server
application.
If no suitable server application is presently running on the same display,
one will be started. If no exec args
are provided, target
will be passed to exec. Otherwise, exec
args
will be passed to exec. For example, apptalk connect foo
will run the server app foo
by issuing the tcl command exec foo
. On the other hand, apptalk connect foo wish4.2 tkfoo
will start the server application by issuing the tcl command exec wish4.2
tkfoo
. Note that it is not required that target
be the same as any of the exec args
.
If a suitable server application is not
running, the connection will be established in one of three ways based on
the value of the resource apptalk*policy:
@target
command may be used to send commands to the server. For example, to cause
the server ``hello'' to pop up you would use the command:
apptalk connect hello @hello popup
wm title . "Hello, world!"
button .b -text "Hello, world!" -command {puts stdout "Hello, world!"} pack .b
apptalk init hello
apptalk proc press_button { usage: %N press_button causes the hello, world button to be pressed. } { .b invoke }
From within some other script, we can cause the button to be pressed with the following sequence (assuming the above script was saved in a file named hello.tcl :
wish> apptalk connect hello wish hello.tcl wish> @hello press_button
To see the documentation for the press_button command, we can do the following in an interactive wish shell:
wish> @hello info press_button press_button: usage: @hello press_button causes the hello, world button to be pressed. wish>
apptalk connect
and request an application that is not apptalk enabled, the client program
will wait forever for the application to start up. That is because the
client program waits for notification that is sent by the server. If the
server isn't apptalk enabled, it won't know to send the notification. Such
is life.
Running an apptalk enabled server or client in an application that can't use send is a problem. Most likely the send command will fail but you'll have no way to know. Many of the times send is used the errors are caught (and ignored) or never seen (such as when using send -async). I need to do something about this. Perhaps I need to use sockets instead of send.