X Window System Programming with Tcl and Tk

Tcl and Tk will allow you to develop X Window System applications by writing simple, interpreted scripts. Learn how to unlock the power of X throught this unique programming paradigm.

Anyone who has ever programmed X applications through the Xlib interface, or the arcane X Toolkit Intrinsics, or even Motif, knows that it is an experience that cannot be fully appreciated without beating one's head against the desk several times an hour. X programming at the C level can often be quite complex, forcing the programmer to concentrate on messy technical issues instead of simply building an interface. (Of course, the tradeoff for this complexity is power and flexibility.) That's why we have Tcl and Tk.

Tcl (Tool Command Language) is an interpreted script language not unlike C Shell or Perl. It provides all of the basic facilities that you'd expect in such a language: variables, procedures, loops, file I/O, and so forth; nothing too flashy or bizarre. If you've ever written shell scripts you'll find Tcl quite easy to pick up.

What makes Tcl special is that it can be embedded in other applications. That is, the Tcl interpreter is a library of C routines which you can call from your own program. For example; let's say that you're writing a debugger, similar in nature to gdb.You need routines to allow the user to enter commands (such as “step 10” or “breakpoint foot c:23”) at a prompt. You'd also like to allow the user to customize the debugging environment by writing new command procedures or modifying state variables. A good way tohandle the user interface would be with Tcl. You can link the Tcl interpreter to your application, and all of the features of that language will be available. The user's commands, entered at the debugger prompt, would be executed by the Tcl interpreter, which could call C functions that you have written. If the user needs to customize aspects of the application, they can write Tcl scripts to implement new commands, and so forth.

Tcl itself may not be very exciting, but coupled with Tk it certainly is. Tk is a set of extensions to Tcl which implement commands for writing X Window System applications. These commands allow you to create buttons, scrollbars, text entry widgets, menus, and much more; permitting you to write X applications as simple Tcl scripts. With Tcl and Tk, there's little need to learn the C library interface for X programming; Tcl and Tk provide access to many X Window System facilities. In addition, you can embed Tcl and Tk in your own applications, written in C, to greatly enhance the power of this system.

This article is the first in a series on Tcl and Tk. In this article, I'm going to describe how to write simple X programs as Tcl/Tk scripts. Next month, I'm going to describe how to use the Tcl/Tk interpreter in conjunction with programs written in C or Perl.

The syntax of the Tcl language itself is relatively straightforward and will be obvious to anyone who has programmed, say, shell or Perl scripts. For this reason, I'm not going to spend much time describing the syntax of the Tcl language itself; I'm going to concentrate on the X- specific features of the Tk toolkit. See the sidebar, “Getting Tcl and Tk”, for other sources of information on Tcl.

Basic Tcl/Tk Scripts

Let's dive right in with a simple Tcl/Tk program. The Tcl/Tk interpreter is named wish (“window shell”). Assuming that you have Tcl/Tk installed on your system, and X running, you should be able to execute wish. You will be presented with a blank, rectangular window, and a wish prompt.

You can type Tcl/Tk commands at this prompt, and the results will be displayed in the wish window. For example, if you type: button .b -text “Hello, world!” -command { exit } pack .b

the wish window should reduce to a single button containing the string “Hello, world!”. (See Figure 1. next page ) Pressing this button will cause the wish process to exit.

What did we just do? Every Tcl command begins with a command name, followed by any arguments. button is a Tk command which creates a button. In this case, we want the button to contain the text “Hello, world!”, and we wish it to execute the Tcl exit command when it is pressed. The first argument to button,“.b”, is the name that we wish to give to the button widget.

Figure 1

(A widget is simply a graphical object, such as a button, scrollbar, etc., which has certain visual and functional properties. Tk supports many types of widgets, as we'll see.) We can later refer to the button with this name.

The pack command is a geometry manager; it controls how widgets are placed within the wish window. pack is a simple geometry manager which “packs” (hence the name) widgets one at a time next to each other. The widget is not made visible until it is given a position with pack.

In this case, we wish to pack the button widget into the wish window. pack can take a number of arguments to specify the position of the widget relative to other widgets. However, here we have but one widget, so the default behavior is acceptable.

Instead of typing commands to the wish process, you can write scripts to be executed via wish. Here's a simple program which will prompt you for a filename, and then start an xterm running vi to edit the file.

#!/usr/local/bin/wish -f
label .1 -text "Filename:"
entry .e -relief sunken -width 30 -textvariable\
pack .1 -side left
pack .e -side left -padx
lm -pady lm
bind .e <Return> {
exec xterm -e vi $fname

If you save the above in a file named edit.tcl, and then run it, you should be presented with a window as in Figure 2. (This assumes, of course, that you have wish installed in /usr/local/bin. Edit the pathname on the first line of the script if not.) Just as with shell scripts, you will need to make the file executable before running it.

Let's walk through this script. The first line is a label command, which (as you might guess) creates a label widget. A label contains only a static text string. We name this widget .1 (more on widget naming conventions later), and give it the text value “Filename:”.

The second line creates an entry widget, named .e. An entry widget is like a label, except that it allows the user to edit the text. The -relief sunken option indicates that the widget should appear as though it is “recessed” in the window, as you can see in Figure 2. The -width option sets the width of the entry widget in characters, and the -textvariable option indicates that the value of the entry text should be stored in the variable fname.

The next two lines pack the label widget, followed by the entry widget, into the wish window. In both cases we specify -side left, which indicates that the widgets should be packed into the left side of the window, one after the other. When packing the entry widget, we use the -padx and -pady options to leave a bit of “paddingH (here, one millimeter) around the sides of the widget. The Tcl pack man page describes these options in detail.

The last three lines of our script use the bind command to create an event binding for our entry widget. A binding allows you to execute a series of commands when a certain event occurs in a widget; for example, a mouse button click or a keypress. In this case, we wish to execute a command whenever the RETURN key is pressed in the entry widget. The command:

exec xterm -e vi $fname

will start up an xterm running vi on the filename entered by the user. Note the use of the fname variable,

Figure 2

which we associated with the entry widget on the second line of the script. The variable name is prefixed with a dollar sign, to refer to the value of fname itself. This is similar to the variable syntax used in shell scripts.