< BACKMake Note | BookmarkCONTINUE >
152015024128143245168232148039199167010047123209178152124239215162148043124062198187105063

Overview of Other GUI Modules

Python's powerful object implementation and portability has encouraged the development of many other GUI toolkits. Consequently, you have a number of options to try before deciding which one is the best solution for your project.

Pythonwin/MFC

Pythonwin is a wrapper, written by Mark Hammond, to the Microsoft Foundation Class Library (MFC). It is included within the Windows Python distribution.

Actually, Pythonwin is distributed as two key components—Pythonwin.exe and win32ui.pyd. The latter contains all the bindings to the MFC (tens of MFC objects are exposed, including Common Controls, Property Pages/Sheets, Toolbars, and so on), and the former is a simple wrapper that hosts win32ui.pyd, being just a sample program for the MFC user interface environment.

Pythonwin runs only on Windows, hence, if you need to have your program running on both Win32 and UNIX platforms, you can use the Tk libraries instead.

Using Pythonwin, you can design applications that are bound very tightly to Windows, using MFC in an interactive and interpreted environment to provide the features of the Windows user interface. The user interface environment provided by Pythonwin can be embedded in almost any other application—such as OLE clients/servers, Netscape plugins, and so on.

Inside the Pythonwin distribution, you will find a Help File (Pythonwin.hlp), which is a reference manual for all the objects exposed in Pythonwin. That is a great start for you.

Pythonwin's homepage provides resources documenting the Pythonwin GUI environment. There is also some general documentation on the MFC Architecture. After you install Pythonwin, you can find more details in the documentation that comes bundled in it. For more information, check out the Pythonwin home page at

http://www.python.org/windows/pythonwin/

This next document describes how to imbed the win32ui extension module in your own application:

http://www.python.org/windows/pythonwin/EmbeddingWin32ui.html

wxPython

wxPython is a GUI toolkit for the Python programming language that works like a wrapper to the wxWindows C++ library. It is written in Python and uses the LPGL license.

wxPython is a relatively fast cross-platform toolkit, and maybe it hasn't become the standard Python GUI yet because Tkinter is more portable. As a matter of fact, wxPython is the second most common GUI, coming just after Tkinter.

Currently only Win32 and UNIX-like systems with GTK are supported. There are plans to support wxPython on any platform running wxWindows.

wxWindows is a free, well-established, and well-documented set of libraries that allows C++ applications to compile and run on several different types of computers, with minimal source code changes.

The wx in the name wxWindows means w for Windows, and x for X system. It is supposed to be a way to say that it is a Windows system that supports both platforms.

Each supported GUI (such as GTK+, Windows, Motif, and Mac) has its own library provided by the wxWindows, which exposes natural API for all of them. The API is much simpler to use than other native GUI APIs. Note that you cannot use wxWindows as a GUI translator.

wxWindows provides a lot of extra built-in functionality for you as well, and you can decide whether you want to use it. Such extra features have the main goal of providing ways for you to develop user-friendly GUI applications. Included in this functionality are many useful dialogs, built-in HTML display and printing, support to virtual filesystems, OLE automation controller class, and Open GL support. It also offers access to common operating system operations, such as file copying and deletion, and network support for threads and sockets. wxWindows also supports basic data structures such as arrays, strings, linked lists, and hash tables. If you are coming from an MFC architecture, you can consider yourself lucky because both frameworks are very similar, which makes it easier to port applications from one to another. Python and wxWindows have a great thing in common, both had a object-oriented conception. That was one thing that made it possible to develop wxPython, a fully compatible interface to the libraries. Remember that it is very easy to translate C++ calls to Python calls.

wxPython is a very active Open Source project that makes its source code freely available for anyone who wants to use or modify it. If you want, you can also participate by contributing with new ideas and bug solutions for the project.

Using wxPython, it is easier to run the same program on multiple platforms without modification. Currently, wxPython supports Microsoft Windows and most UNIX-like systems.

This extension module allows programmers to use a strong, highly functional graphical user interface to easily write Python programs that can create instances of wxWindows 2.0 C++ classes, and invoke their methods.

wxPython classes are mirrored as closely as possible to the wxWindows class hierarchy. But, we need to consider the difference between Python and C++, and understand that we don't have a 100% match. However, these distinctions can be easily handled by Python. For example, some methods in the wxWindows library return multiple values by returning argument pointers; the equivalent Python method returns a tuple of values instead.

If you go to wxPython's Web site, you can get the latest version of wxPython, and optionally download a self-installer for Win32 systems. The distribution includes a pre-built extension module, documentation in HTML help format and a set of demos. You also have available, among other things, a Linux RPM, wxPython sources, and documentation in raw HTML.

If you will build wxPython from sources yourself, you will also need the wxWindows sources, available from http://www.wxwindows.org/.

wxPython has its own mailing list. It is not that difficult to find WxPython's creator, Robin Dunn, answering messages on the list. But as in any other list, always check the archives before posting a question.

A number of documentation resources are available for both wxPython and wxWindows. The wxPython interface is very close to the wxWindows implementation in C++, which makes most of the wxPython documentation be just simple notes attached to the C++ documents that describe the places where wxPython is different.

The Web site has a series of sample programs and documentation pages that can assist you in getting started with wxPython.

By downloading wxPython, you get two other documentation resources, on Ogl (for graphics) and an introduction to wxWindows, which has received additional wxPython material from Robin. This addendum demonstrates how all wxWindows classes are implemented in wxPython. Not all binaries contain this document, hence, you might need to get it directly from the Web site.

wxPython home page

http://wxpython.org/

wxPython Tutorial

http://wxpython.org/tutorial.html

STDWIN

STDWIN stands for Standard Window Interface. It is a platform-independent interface to C-based window systems. Currently, STDWIN is obsolete and unsupported, without any further development effort being made. The stdwin module has been removed for Python 2.0. The Python people say that if you want to use stdwin, you should grab an older Python release. There is not really any reason you would want to use this toolkit.

Python's stdwin module defines several new object types and functions that provide access to the functionality of the Standard Window Interface, STDWIN.

Tip

For a complete description of STDWIN, take a look at the documentation of STDWIN for C programmers (CWI report CR-R8817).



This module is available on systems to which STDWIN has been ported, including UNIX, Mac, and Windows. Initially, many Python developers had adopted this module, but later, most of them migrated to Tkinter mostly because of the limited functionality imposed by stdwin's design. However, if you install the latest available version available of this module, you can still use it as a solution for many types of applications. Of course, you probably wouldn't want to use stdwin ever.

The next example demonstrates a simple implementation of the stdwin module.

						
  1: import stdwin, stdwinevents
  2:
  3: def mainloop():
  4:     appwin = stdwin.open('Hello')
  5:     while 1:
  6:         (type, win, detail) = stdwin.getevent()
  7:         if type == stdwinevents.WE_DRAW:
  8:             draw = win.begindrawing()
  9:             draw.text((0, 0), 'Hello Python world')
 10:             del draw
 11:         elif type == stdwinevents.WE_CLOSE:
 12:             break
 13:
 14:  mainloop()

					

This small program works by creating a main loop, and checking the events that occur in the windowing environment. When the program starts, it creates and draws a window. Every time the window needs to be redrawn, a WE_DRAW event is caught by this program (line 7), triggering the line of code that draws a message in the window (line 9). This program only ends when the user closes the window, sending the WE_CLOSE event notification to the main loop (line 11).

The latest STDWIN distribution can be downloaded at

ftp://ftp.cwi.nl/pub/stdwin/index.html

PyQt

PyQt is a set of straightforward Python bindings for the Qt toolkit, which is written in C++. The bindings are implemented as a single Python module called qt, and this module exposes a very comprehensive collection of useful classes. The current version supports Qt versions 1.42 to 2.1.x. The main new feature is support for the new Qt v2.0.x widgets. PyQt will also compile with Qt v2.1.0-beta3, but the new Qt v2.1.x widgets are not yet supported.

Tip

QT is a cross-platform product between UNIX and Windows. The main difference is that you have to pay for using it on Windows platforms, whereas on UNIX, you just need to pay for proprietary usage. It is completely legal to use Qt commercially if you meet its license conditions.



PyQT's Web site is a good source of documentation about PyQT and QT itself. You can even learn how to migrate your QT calls from C++ to Python. But if you need more information about PyQT, you can use the PyQT mailing list.

PyQT: Development Tools for Qt Libraries

http://www.thekompany.com/projects/pykde

Check the following article, written by Boudewijn Rempt and Cameron Laird, about implementing QT bindings on the next release of Python:

http://www.sunworld.com/sunworldonline/swol-05-2000/swol-05-qt.html

PyKDE

PyKDE is a set of Python bindings, developed by Phil Thompson, for the KDE toolkit—the KDE classes. It is important to know that the Python bindings for the Qt toolkit (PyQt) must also be installed because it comes in a different package, and that KDE 2 is not yet supported. Just as KDE uses QT, PyKDE uses PyQT.

The bindings are implemented as a number of Python modules corresponding to the names of the separate KDE libraries; that is, kdecore, kdeui, kfm, kfile, khtmlw, and kspell. They support all KDE version 1 releases. Keep in mind that KDE is licensed under the LPGL.

You can find help and more information about PyKDE in the project mailing list, which is the same mailing list as for PyQT. Also, note that because PyKDE requires the KDE libraries, it runs only on the UNIX platform.

PyKDE: Development Tools for KDE Libraries

http://www.thekompany.com/projects/pykde

Python + KDE Tutorial and Examples, by Boudewijn Rempt

http://www.xs4all.nl/~bsarempt/python/tutorial.htmlhttp://www.valdyas.org/python/tutorial.html

Wpy

Wpy is a class library system, based on the Microsoft Foundation Classes, that is used for writing GUI code easily in Python. Wpy is designd for simplicity and portability.

The Wpy Web site provides instructions about how to install the library and use it to run Python programs with windowing GUI capability on UNIX using Tk, Windows 3.1 (16-bit native), and Windows 95, 98, and NT (32-bit native). The source code and the main standard binary ports are available for download.

A Python/Wpy Netscape plug-in DLL is also provided. This plug-in enables you to write Wpy programs that access the Netscape plug-in API and run in the browser window.

Wpy Index

http://www.cwi.nl/ftp/python/wpy/

PyGTK

GTK+ is a Free Software GUI Toolkit that has a large number of widgets, primarily developed for use with the X Window System. Everything about GTK+ from the object-oriented design to the Free Software LGPL licensing allows you to code your project with the most freedom possible. GTK is similar to Qt, but the difference is that you can develop open software, free software, or even commercial non-free software without having to pay anything for licenses. GTK's license allows linking to proprietary applications although the library itself must remain free (in the sense of freedom). The upcoming GTK+ 2.0 includes multi-language support, and framebuffer, Mac, Windows, and BeOS ports are being worked on.

http://www.gtk.org/

PyGTK is a set of bindings developed by James Henstridge, for the GTK widget set and GNOME libraries that runs on any platform that supports GTK. It provides an object-oriented interface that is a slightly higher level than the C one. It automatically does all the type casting and reference counting that you would have to do normally with the C API. Talking about C, all the underlying C classes are documented on the GTK homepage.

Many simple examples come with PyGTK. They are a good start for your projects. Look in the pygtk/examples or pygnome/examples directory for details. The pygnome/examples directory is only part of the gnome-python package that is covered in the next section.

The following code, extracted from James Henstridge PyGTK's Web site, shows how simple it is to use the PyGTK module:

						
from gtk import *

def hello_cb(button):
    print "Hello World"
    window.destroy()

window = GtkWindow(WINDOW_TOPLEVEL) # create a top level window
window.connect("destroy", mainquit) # quit the event loop on destruction
window.set_border_width(10)          # set padding round child widget

button =GtkButton("Hello World")
button.connect("clicked", hello_cb) # call hello_cb when clicked
window.add(button)                   # add button to window
button.show()                         # show button

window.show()
mainloop()                            # enter the main event loop

					

PyGTK is available for download at the following FTP sites:

http://ftp://ftp.gtk.org/pub/gtk/python/

http://ftp://ftp.python.org/bub/contrib/Grahics/

http://ftp://ftp.daa.com.au/pub/james/python/

More information about PyGTK can be found at James Henstridge's PyGTK home page:

http://www.daa.com.au/~james/pygtk/

pygtools, a Web site maintained by J.W. Bizzaro, is an excellent resource for PyGTK information. It contains the latest news about GNU development for Python, including GTK projects.

http://theopenlab.uml.edu/pygtools

If you need to implement GTK application on Windows, there are a couple of Python wrappers over GTK+ that you can use, such as

PyGTK on Win32, by Kevin J. Butler

http://theopenlab.uml.edu/pygtkwin/

PyGTK on Win32, by Hans Breuer

http://hans.breuer.org/ports/

Gnome-Python

The Gnome project has built a complete free and easy-to-use desktop environment for the user, as well as a powerful application framework for the software developer. For more information, check out

http://www.gnome.org/

The next Web address points you to a set of bindings for the Gnome libraries for use with python. Although gnome-python uses PyGTK, you don't need to have the PyGTK package compiled or individually installed before compiling gnome-python. This library runs on UNIX only, and it is licensed under the LGPL.

ftp://ftp.gnome.org/pub/GNOME/stable/sources/gnome-thon/

Developing Gnome Applications with Gnome-Python is a very comprehensive article written by Daniel Solin that covers the main aspects of writing a program using Gnome-Python. It is located at

http://www.linuxdev.net/features/articles/05.24.2000/

PyOpenGL

OpenGL is the premier environment for developing portable, interactive 2D and 3D graphics applications from modeling to scientific to games. Since its introduction in 1992, OpenGL has become the industry's most widely used and supported 2D and 3D graphics application programming interface (API), bringing thousands of applications to a wide variety of computer platforms. OpenGL fosters innovation and speeds application development by incorporating a broad set of rendering, texture mapping, special effects, and other powerful visualization functions. Developers can leverage the power of OpenGL across all popular desktop and workstation platforms, ensuring wide application deployment.

PyOpenGL (Python Tk-OpenGL Module) is the OpenGL-Widget for Python/Tk. Initially based on the Togl widget, this module was written by David Ascher, Mike Hartshorn, Jim Hugunin, and Tom Schwaller. PyOpenGL contains both a wrapper for the Togl Tk widget and bindings for OpenGL. The non-Tk portions of PyOpenGL can be used with other toolkits, such as PyGTK and others. For more information, see the following sites:

History, installation, and tutorial for the Python Tk-OpenGL Module (with sample code).

http://www.python.de/

wafepython

Wafe, which stands for Widget Athena front end, is a package that implements a symbolic, string-based interface based on Tcl to the X Toolkit, the Athena Widget Set, the OSF/Motif Widget Set (versions 1.1 to 2.0), and various complementary widget classes and extension packages. Using Wafe, one can develop applications with high-level graphical user interfaces in the scripting language Tcl, or one can use Wafe mostly as a graphical front end that provides an easy access to GUI programming for various programming languages.

Because Wafe can be easily linked with C programs, it can also be used to provide GUI functionality for other interpretative languages by extending these languages by a few commands. In the Wafe distribution are sample implementations for embedding Wafe in interpretative languages, including Python. These implementations provide a bidirectional interface from and to Wafe (for example, Wafe calls Python and Python calls Wafe).

wafepython (a version of Python enhanced with Wafe commands)

http://www.wu-wien.ac.at/wafe/wafe.html

pyFLTK

FLTK (Fast Light Tool Kit, pronounced "fulltick") is a C++ graphical user interface toolkit for X (UNIX), OpenGL, and WIN32 (Microsoft Windows NT 4.0, 95, or 98). It is also largely compatible with the XForms library. FLTK is currently maintained by a small group of developers across the world with a central repository in the United States, and it is distributed under the GNU Library GPL (LGPL).

FLTK was originally created to build in-house applications at Digital Domain for image processing and 3D graphics. The original author, Bill Spitzak, received permission from Digital Domain to release it to the public domain in the hopes that it could be used to make better, faster, and nicer-looking UNIX programs. Digital Domain has since withdrawn support for FLTK, but Bill is still able to work on it from time to time.

pyFLTK is the Python wrapper for the Fast Light Tool Kit graphical user interface library. The development team is using SWIG to create the wrapper.

Kevin Dalhausen and Bjorn Petterson, among others, are working on these bindings for Python. They conduct their work through a mailing list. The main goals of the Project are to develop usable Python and Perl wrappers for the FLTK library; to demonstrate the wrapper's functionality by converting the test programs supplied with FLTK to Python and Perl; and to allow the use of Fluid (FLTK User Interface Designer) to generate Python and Perl graphical user interfaces.

http://netpedia.net/hosting/fltk/

FXPy

FOX is a C++ based toolkit for developing GUIs easily and effectively. FOX runs on UNIX and Windows, and supports the LGPL kind of license. It offers a wide, and growing, collection of Controls and provides state of the art facilities such as drag and drop, selection, as well as OpenGL widgets for 3D graphical manipulation. FOX also implements icons, images, and user-convenience features such as status line help, and tooltips. Tooltips can even be used for 3D objects!

Considerable importance has been placed on making FOX one of the fastest toolkits around. To minimize memory use, FOX uses a number of techniques to speed up drawing and spatial layout of the GUI. Memory is conserved by allowing programmers to create and destroy GUI elements one-fly.

Even though FOX offers a large collection of Controls already, FOX leverages C++ to allow programmers to easily build additional Controls and GUI elements by taking existing controls and creating a derived class that simply adds or redefines the desired behavior.

One of the prime design goals of FOX is the ease of programming; thus, most controls can be created using a single line of C++ code; most parameters have sensible default values so that they may be omitted, and layout managers ensure that designers of GUIs do not have to worry about precise alignments.

Another nice feature of FOX that significantly reduces the number of lines of code which have to be written is FOX's ability to have widgets connect to each other, and pass certain commands between them. For example, a menu entry Hide Toolbar can be directly connected to the Toolbar, and cause it to hide.

Finally, FOX makes it easy to maintain the state of the GUI in an application by having the GUI elements automatically updating themselves by interrogating the application's state. This feature eliminates the large amount of effort that might go into sensitizing, graying out, checking/unchecking, and so on depending on the application state. For more information, check out

FOX

http://www.cfdrc.com/FOX/fox.html

FXPy is a Python extension module, written by Lyle Johnson, which provides an interface to the FOX GUI library. FXPy is a good Python extension, and up to this date, has a quite complete documentation.

FXPy

http://home.hiwaay.net/~johnson2/FXPy/

Motif

Fearing the success of Sun in creating a GUI standard, other UNIX vendors created a committee called the Open Software Foundation (OSF). Motif is a widely-accepted set of user interface guidelines developed by this committee around 1989, to specify how an X Window System application should look and feel.

Motif is the market leader among UNIX GUI toolkits—the single most widely used toolkit in the UNIX world, and almost 10 years after its creation, it enjoys both the advantages and disadvantages of maturity. It has the most advanced support for text from languages other than English, a wealth of third-party tools support it, and hundreds of books and online documents explain it. The disadvantages are that it has regular performance, it is in decline, it is a lot more difficult to program than many other toolkits, and it is not suitable for the current object-oriented programming styles.

Motif is so ubiquitous that many UNIX users confuse it with GUI operations, window managers, or other pieces of technology, and some speak as if Motif is the only GUI foundation or toolkit.

Sjoerd Mullender bound Motif to Python in a package he calls the Python X Extension. Currently, this is a work in progress. For more information, check out

Source of the Python X Extension

http://www.cwi.nl/ftp/sjoerd/index.html

The following files are currently found in this site:

X-extension.tar.gz—The complete source (including source of documentation).

X-extension.ps.gz—The complete documentation in Postscript.

X-extension.html.tar.gz—The complete documentation as a set of HTML files.

vpApp.tar.gz—A GUI application framework for (X)Python.

PyAmulet

PyAmulet is another Python GUI. It wraps an underlying C library, called OpenAmulet. This GUI has been successfully tested on Windows platforms. For more information, check out

PyAmulet home page

http://www.openip.org/html/pyamulet/

PyAmulet Documentation

http://www.openip.org/html/PyAmulet/

DynWin

DynWin is a dynamic GUI class library for Windows (Win32) and Python. It looks similar to Java's Swing library. For more information, check out

http://www.nightmare.com/~rushing/dynwin/index.html

JPI

The Java Python Interface (JPI) is an interface that allows Java and Python (the C Implementation, not JPython) to primitively work together. Therefore, you can use Python as a scripting language for the Java language. Prototyping routines in Python, and later migrating them to Java is a simple and straightforward process because the similarity between both syntaxes is huge. This interface is a work in progress because it currently doesn't provide a total match between both languages.

This interface enables one to dynamically manipulate Java objects using a Python application, including GUI widget managers such as AWT, for example.

http://www.ndim.edrc.cmu.edu/dougc/jpi/Home.html

AWT

The Abstract Windowing Toolkit (AWT) is a user interface toolkit provided by the Java programming language class library.

AWT is very simple to use. Although the documentation that is currently provided in the Java distribution seems to scare AWT programmers away, the language is very strong and flexible. After you find the right direction, you will see yourself creating GUIs with your eyes closed.

As AWT is written in Java, you might want to use JPython in order to manipulate it because JPython gives convenient access to Java classes and packages. However, you can also try to use Python, also known as CPython, and JPI. Together, they can be used to prototype AWT objects and create bindings calling Python routines.

For more information about JPython and AWT, see Chapter 18, "JPython."

FORMS

FORMS is a module for the SGI IRIX platform that provides an interface to the FORMS Library developed by Mark Overmars.

Among other things that might interest you, you better pay attention to the terminology used by FORMS: The word object is used for buttons, sliders, and anything else that you can place in a form.

The Python interface to FORMS introduces two new Python object types: form objects (representing an entire form) and FORMS objects (representing one button, slider, and so on).

There are no "free objects" in the Python interface to FORMS, nor is there an easy way to add object classes written in Python. The FORMS interface to GL event handling is available, though, so you can mix FORMS with pure GL windows.

FORMS library interface for GUI applications

http://www.python.org/doc/current/lib/module-fl.html


Last updated on 1/30/2002
Python Developer's Handbook, © 2002 Sams Publishing

< BACKMake Note | BookmarkCONTINUE >

Index terms contained in this section

Abstract Windowing Toolkit (AWT) module
AWT (Abstract Windowing Toolkit) module
Bizzaro, J.W.
Developing Gnome Applications with Gnome-Python
Dunn, Robin
extensions
      Python X
Fast Light Tool Kit (pyFLTK) module
FORMS module
FOX (FXPy) module
FXPy module
Gnome-Python module
graphical user interfaces (GUIs)
     toolkits
            Abstract Windowing Toolkit (AWT)
            FORMS
            FXPy
            Java Python Interface (JPI)
            Motif
            pyFLTK
            PyGTK 2nd
            PyKDE 2nd
            PyOpenGL
            PyQt
            Pythonwin
            stdwin
            wafepython
            wxPython 2nd 3rd
GTK+ module
Hammond, Mark
Henstridge, James 2nd
interfaces
     graphical user (GUI)
            toolkits;Abstract Windowing Toolkit (AWT)
            toolkits;FORMS
            toolkits;FXPy
            toolkits;Java Python Interface (JPI)
            toolkits;Motif
            toolkits;pyFLTK
            toolkits;PyGTK 2nd
            toolkits;PyKDE 2nd
            toolkits;PyOpenGL
            toolkits;PyQt
            toolkits;Pythonwin
            toolkits;stdwin
            toolkits;wafepython
            toolkits;wxPython 2nd 3rd
Java Python Interface (JPI) module
Johnson, Lyle
JPI (Java Python Interface) module
MFC (Microsoft Foundation Class Library)
Microsoft Foundation Class Library (MFC)
modules
      Abstract Windowing Toolkit (AWT)
      FORMS
      FXPy
      Gnome-Python
      GTK+
      Java Python Interface (JPI)
      Motif
      pyFLTK
      PyGTK 2nd
      PyKDE 2nd
      PyOpenGL
      PyQt
      Pythonwin
      stdwin
      wafepython
      wxPython 2nd 3rd
Motif module
Mullender, Sjoerd
Og1
Open Software Foundation (OSF)
OSF (Open Software Foundation)
Overmars, Mark
pyFLTK module
PyGTK module 2nd
pygtools
PyKDE module 2nd
PyOpenGL module
PyQt module
Python Tk-OpenGL (PyOpenGL) Module
Python X Extension
Pythonwin module
Solin, Daniel
Standard Window Interface (stdwin module)
stdwin module
Thompson, Phil
toolkits
     graphical user interfaces (GUIs)
            Abstract Windowing Toolkit (AWT)
            FORMS
            FXPy
            Java Python Interface (JPI)
            Motif
            pyFLTK
            PyGTK 2nd
            PyKDE 2nd
            PyOpenGL
            PyQt
            Pythonwin
            stdwin
            wafepython
            wxPython 2nd 3rd
wafepython module
Widget Athena front end (Wafe) module
wxPython module 2nd 3rd

© 2002, O'Reilly & Associates, Inc.