The XForms home page calls XForms “a GUI toolkit based on Xlib for the X Window System. It features a rich set of objects, such as buttons, sliders, and menus, etc., integrated into an easy and efficient object/event callback execution model that allows fast and easy construction of X applications.” With this first of three articles on XForms, you can ease into programming for X without having to know exactly what “object/event callback execution” involves.
Where did Linux come from? That’s a good question, and one that seems to confuse a lot of new users. The short answer, of course, is that Linux was written by Linus Torvalds (the original and central force behind the Linux kernel). But that cursory response misses much of the spirit of Linux. When you go into a computer store and buy a Linux CD-ROM set, you’re getting a copy of the intellectual output of literally thousands of programmers. Most of these people have never met each other. Thanks to the Internet, however, this geographically dispersed group has managed to create a formidable array of tools and applications. Linux works so well that it creates the illusion that there is some kind of organization and control structure in place—some central authority directing every aspect of its development. This makes it easy to forget that every application you run—from an ASCII text editor to a Z-Modem download—exists because somebody, somewhere, sat down one day and said, “I can’t find a way to do this under Linux, so maybe I should try to write my own program.”
This article is the first in a three-part series designed to introduce the reader to a programming tool called The XForms Library. As its name suggests, XForms is a set of tools and routines that can be used to easily create programs that run under the X Window System. The overall goal is to take a reader who has never written an X-based piece of software to the point where he or she can start writing their own applications and utilities. The series assumes the reader is familiar with the C programming language, since XForms is C-based. If you don’t yet know anything about C programming, now may be a good time to take the plunge. Buy a book or two and start fiddling with it. With a few weeks of study, you’ll probably have enough C under your belt to be able to follow the series by the time the next article appears. It is also assumed you have a working C compiler and the X Window System is already installed.
It’s the author’s hope that readers will eventually be able to contribute an XForms-based program to Linux. The next time you post a “where can I find a program to do x” message to comp.os.linux.misc and don’t get an answer, think about whether it’s something you might be able to write yourself. You probably won’t earn a cent for your troubles, but the process is not without its rewards. One day, a few months after uploading your package to Sunsite, you may find yourself in a software shop that has just received a new shipment of Linux CD-ROMs. Up on a shelf, probably squeezed between the latest commercial software from Microsoft and Corel, will be a few kilobytes of code you wrote and which people all over the world are using.
Outline of the Series
The purpose of this first article is to explain how to get and install XForms. We also take a first glance at the process of creating an XForms application and actually write a couple of simple programs.
The next two articles, which will appear in the August and September issues of Linux Journal, will expand on this process. They will go through all the steps required to create useful software with XForms with the aid of an example application, a simple game theory simulator. Don’t worry if you have no idea what game theory is, since all you need to know about it will be explained in the process. The choice of programming example is driven by the author’s interests, and is irrelevant to the central purpose of the series: learning to use XForms.
Details on where to get all of the software mentioned are available in the Resources section at the end of this article. There is also a web page for this series which can be found at http://a42.com/~thor/xforms/. This site includes links to all relevant software, as well as listings of all the source code used in the series.
An Overview of XForms
The XForms library was written by T. C. Zhao and Mark Overmars. It is free for non-commercial use, but if you’re planning on selling your application, you will need to set up a monetary licensing arrangement with the XForms authors. If you’re a free software “purist”, you may want to think about using V instead of XForms (see the next section).
The most important parts of the XForms package are the actual library (libforms) and the forms.h include file. The former contains functions for creating buttons, menus, and so on. The include file declares these library functions, which makes them available for use in your software. If you’re a relative newcomer to all this, don’t worry—we’ll be going through every step required to get things working.
There is also a very thorough manual available in HTML format, which explains all of the available routines. A large set of example applications, which are referred to in the documentation, are included in the main distribution. These examples are very useful for getting good ideas on how to implement various procedures.
Finally, there is a program called fdesign included with XForms that can be used to design user interfaces. This is a real time saver, since you can use your mouse to control the placement of buttons, menus and other objects. Your design can then be saved to a file and easily brought into your source code. Complicated sets of overlapping windows with large numbers of graphical elements can thus be created in a relatively short period of time.
Since XForms is actually built around the X11 library, any program you write is highly portable to other X-capable systems. Although readers of this magazine will probably be developing for Linux, it’s nice to know users of FreeBSD, Sun and other systems will be able to run your application if they want.
Alternatives
Since learning any programming library involves a substantial investment of time, it may be worth your while to consider a few alternatives before jumping headlong into XForms.
The following discussion is far from exhaustive and is based solely on the idiosyncratic experiences of the author.
Motif is a very common library which is used to build many commercial X-based programs. To create your own Motif applications, you need the Motif development library, which is fairly expensive (at least by Linux standards). The main advantage to Motif is that it is a mature system which can create visually appealing applications. The main drawback is its price. There is a free version of Motif in the works (called LessTif), but it is not yet 100% functional.
Another library with a licensing arrangement similar to XForms is called Qt. The Qt library is free for non-commercial use under X, but is also available for Microsoft Windows and other operating systems. This has the great advantage that if you write a program under Linux, people can also use it on completely different operating systems. It is also the core of the new KDE Desktop Environment, which should be available by the time this article appears in print. If KDE catches on, then Qt will become very popular in the Linux world. The Qt library is based around C++ (rather than plain old C, which XForms uses).
If you want an X development system that is truly free, then you may want to look at V. This is another C++-based library, which includes all the standard features, such as buttons, menus, etc. As the author of V admits, it is probably not suitable for trying to write a state-of-the-art interface, but it is a reasonably complete package, and it’s difficult to argue with the price.
Finding and Installing XForms
The main task in installing XForms is to get the library and include file into the right places on your system. The Web and ftp sites for XForms are listed at the end of this article. Most people will want to grab the ELF version, but if you are still running a.out, then make sure you get the relevant file. The distribution includes the library, more than 50 example applications, and the fdesign program. You should also get the reference manual, which is available in a separate file.
At the time of writing, the most recent version of XForms is 0.81, and the Linux package is in a compressed tar file of roughly 600KB (i.e., it has a .tgz extension). You should make sure you are logged on as root and unpack the distribution somewhere like /usr/local/. The archive installs into a directory called xforms. It’s generally a good idea to check the Readme file included in the distribution for advice on installation.
If you have a more or less standard setup, then all you need to do is go to the xforms directory and type make install. This should copy the library and include files into the right places. If this doesn’t work (or you want to do things by hand), just make sure forms.h ends up somewhere gcc can find it (i.e., in /usr/include/) and all libform files end up in the same place as libX11 (i.e., in /usr/X11R6/lib/).
If you want to verify things are installed correctly, change to the DEMOS subdirectory and try make demo. If this does not work, go back and ensure the library and includes are where they’re supposed to be.
Your First XForms Program
With the library and include file installed, it’s time to write your first program. It is a C tradition that a first attempt should always say “hello world”, so we’ll write one that does just that. Either type in the source code for xhello.c (see Listing 1) or copy it from the series web site.
Listing 1. xhello.c
/* xhello.c -- An XForms Hello World Program On a "standard" Linux system, this program can be compiled with the command: gcc -lX11 -lforms -lm xhello.c -o xhello To have access to the XForms routines, we need to include the forms header file */ #include <forms.h> /* Since XForms applications are just standard C, we use a normal main() with command line arguments (if any) stored in argv. */ int main(int argc, char *argv[]) { /* We need a couple of XForms variables */ FL_FORM *hello_window; FL_OBJECT *hello_button; /* The first call is to fl_initialize(), which sets up XForms and handles relevant command line options */ fl_initialize(&argc, argv,"xldlas", 0, 0); /* We create a simple window with a helloworld button in it */ hello_window = fl_bgn_form(FL_UP_BOX, 150, 50); hello_button = fl_add_button(FL_NORMAL_BUTTON,10,10,130,30,\ "Hello World"); fl_end_form(); /* Now that we've created our window, we need to show it. */ fl_show_form(hello_window,FL_PLACE_FREE,FL_FULLBORDER,\ "Push the Button"); /* Wait for the button to be pressed before exiting */ fl_do_forms(); return(0); }
As the source code suggests, you should be able to compile the program with the command:
gcc -lX11 -lforms -lm xhello.c -o xhello
The command xhello should start up the program (make sure you’re running X). You may have to type ./xhello, depending on how your shell’s PATH variable is set. The running program should look something like Figure 1. Note, you must include the linking options for this to work. In particular, -lX11 links your code to the standard X library, which XForms depends on (libX11 is included in all X distributions). The forms library is linked in with -lforms, and it uses some math routines which must be linked with -lm.
Although it doesn’t do very much, the xhello program shows the basic steps involved in writing an XForms application. First, we include the forms header file, which gives us access to the XForms routines. Then, fl_initialize() is called to let XForms set itself up. We pass all command line options (stored in argv) to this function, so that XForms can pull out those it wants. For example, our xhello program already understands command options like -share (to share the colour map) and -display (to open itself on a specified X display).
With initialization taken care of, we can create as many graphic elements as we like. In this example, we have just one button located in a single window.5 We then show the window we’ve created with the fl_show_form() function. To get the program to wait for the button to be pushed before exiting, we invoke fl_do_forms() which waits until the state of our window changes before returning.
5. This brings up a note on terminology. Many people think of a rectangular collection of objects on a screen as a window. The XForms library refers to just such a collection as a form. For the rest of this series, it is best to consider the two terms interchangeable.
There are a couple of things to notice at this point. First, if you have never written an X application before, then congratulations are in order (give yourself a pat on the back). Second, although installing the library may have taken some time, the result was well worth it. With just two variables and well under a dozen function calls, we have a fully fledged running program. Not only that, our program is attractive: the colour scheme is easy on the eyes, the button is nicely shaded to appear three dimensional, etc. Finally, the program is quick and responsive, even on slow hardware. This is due to a combination of factors, the most important of which are that XForms is quite efficient, and everything has been done in pure C.
A Little More Detail
If you’re already thinking ahead to greater things, you are probably a little confused about how to get an XForms application to do anything other than return after a single button is pushed. The next programming example provides a hint, but the whole story will have to wait for the next two articles in the series.
The basic idea is to proceed as in the xhello example, but to add some functionality to each action. We do this by creating a multi-lingual “Hello World” program called xmulti. The source is shown in Listing 2, and is also available on the series web page. Save this file as xmulti.c. It should compile with the command:
gcc -lX11 -lforms -lm xmulti.c -o xmulti
Listing 2. xmulti.c
/* xmulti.c -- An XForms Multilingual Hello World Program On a "standard" Linux system, this program can be compiled with the command: gcc -lX11 -lforms -lm xmulti.c -o xmulti To have access to the XForms routines, we need to include the forms header file */ #include <forms.h> /* We create a few global variables that all functions have access to */ FL_FORM *hello_window; FL_OBJECT *english_button; FL_OBJECT *french_button; FL_OBJECT *done_button; FL_OBJECT *display_area; /* This function will set the display_area to the selected language */ void set_language(FL_OBJECT *obj, long arg) { fl_clear_browser(display_area); if(arg == 1) fl_addto_browser(display_area, "@cHello World"); if(arg == 2) fl_addto_browser(display_area, "@cBonjour Le Monde"); } /* Since XForms applications are just standard C, we use a normal main() with command line arguments (if any) stored in argv. */ int main(int argc, char *argv[]) { /* The first call is to fl_initialize(), which sets up XForms and handles relevant command line options */ fl_initialize(&argc, argv,"xldlas", 0, 0); /* We create a simple window with three buttons and a display area. Note that the english_button and the french_button are set to call the function set_language() */ hello_window = fl_bgn_form(FL_UP_BOX, 180, 125); display_area = fl_add_browser(FL_NORMAL_BROWSER,10,10,160,25,""); fl_set_browser_fontsize(display_area,FL_NORMAL_SIZE); fl_addto_browser(display_area,"@cChoose/Choisir"); english_button = fl_add_button(FL_NORMAL_BUTTON,10,45,75,30,"English"); fl_set_object_callback(english_button, set_language, 1); french_button = fl_add_button(FL_NORMAL_BUTTON,95,45,75,30,"Francais"); fl_set_object_callback(french_button, set_language, 2); done_button = fl_add_button(FL_NORMAL_BUTTON, 10, 85, 160, 30,"Done"); fl_end_form(); /* Now that we've created our window, we need to show it. */ fl_show_form(hello_window,FL_PLACE_FREE,FL_FULLBORDER,\ "Push Done to Quit"); /* When the Done button is pressed, fl_do_forms() doesn't know what to do (the done button has not been assigned to call anything), so it returns. */ fl_do_forms(); return(0); }
The program can now be executed by typing xmulti, and should look like the example shown in Figure 2. Examination of the xmulti source code reveals the fundamental steps involved in creating an XForms program are as follows:
- Include forms.h to access the XForms routines
- Call fl_initialize() as soon as possible
- Set up your graphical interface by creating forms
- Assign actions to relevant objects by setting callbacks
- Show one or more forms
- Turn control over to fl_do_forms()
The only thing new here is point 4, which our original xhello program did not include. In xmulti, the English and French buttons are set to call the routine set_language(), which changes the display. But the basic idea is very general, and you can easily add buttons, menus, etc., that call complicated functions, display other forms, or what have you.
Coming Next Month
Next month, we’ll expand on this basic discussion by writing a more complicated program. This will involve using menus, multiple windows, and a few other refinements. By the time we’ve done the third article, you should be well on your way to creating useful applications.
If you can’t wait to learn more, then you may want to start reading through the XForms manual. Browsing the example applications’ source code is also an excellent way to familiarize yourself with the XForms way of doing things.