From the IBM Canada web site ...

General information

Machine type: 5160
Announce date: March 8, 1983
List price: $7545.00 (5160-087)

Excerpt from the original announcement letter;

"The XT System Unit is the heart of the computer system. The XT System Unit and its companion keyboard are rugged and easy-to-use, and control a variety of input/output devices. Each XT System Unit comes with 128KB (131,078 bytes) of memory, a dual-sided (368,640 bytes) Diskette Drive, and a 10MB (10,240,000 bytes) Fixed Disk Drive. Asynchronous Communications (Async) is also standard on each XT System Unit. This provides an EIA-RS232C interface, which has a variety of uses. Based on a high performance Intel 8088 microprocessor, each XT computer includes an enhanced version of the popular BASIC language and provisions for attachment of a video display. The system can be further expanded through options that are customer installed."

System Characteristics

Physical description
Power supply: 130w
Weight: 12.7 - 13.9 kg
Dimensions (HxWxD): (147 x 498 x 410mm)

Mass storage
Drive bays: 2 full height
Floppy Disk
Size: 5.25 inch full height
Capacity: 360KB
Hard disk
Size: 5.25 inch full-height
Capacity: 10MB or 20MB
Access time: >85ms
Interface: ST-506

Display
Size: 11.5 inch (diagonal)
Display type: Optional IBM Monochrome Display (5151) - TTL green phosphor screen
Graphics modes supported: MDA (text 25 rows x 80 characters)

Keyboard
Type: 83 key or 101 key enhanced

Software
Operating system: IBM PC DOS Versions 2.0 and later for models 68,78,87, and 86 and Version 3.1 or later for models 267,277,88,268,278, and 89

And XT stood for eXtended Technology

The XT was Subaru's first attempt at producing a sports car. They launched this arrow shaped 4 wheel drive beast in 1985. The most notable thing about the XT was that it broke the record for air resistance with a .29 coefficient of drag. This record may still be standing today, (I can't find any records of it being broken).

The XT featured 4 wheel drive, (later changed to all wheel drive), 4 wheel independent adjustable suspension, (this used airbags like big diesel trucks have), and a turbocharger. The XT was eventually replaced by the Subaru SVX. But the SVX was in a different class. The XT was a Camaro fighter. While the SVX competed on Corvette level in the automotive arena.

Xt, or "X Toolkit Intrinsics", assists in the construction and use of widget sets under the X Window System. Xt doesn't directly provide any widget functionality; instead, it provides some depth of abstraction above Xlib, and above C itself, for creating and using high-level widgets. Xt widgets are written using Xlib with complicated Xt functions and data structures, and can be used with Xt calls or wrapper functions (a la Motif). There are a few major Xt widget sets still in major use, namely Athena (Xaw) and Motif, and a few others that are obsolete.

Most modern X widget sets are not made with Xt, partly because other languages and styles have proved to be a better foundation, especially as regards object orientation. GTK+, for instance, is built on it's own Xlib wrapper called GDK. In fact, the abstractive parts of Xt are analogous to those parts of GDK and GObject. QT uses C++ classes and its extension of C++ for similar purposes. (As a side not, GTK+ and QT completely hide XLib; XT does not.)

The original generation of X applications and utilities were created using the Xt widget sets Athena and Motif, and occasionally something obscure like OLIT. Some of these applications, like xterm and xclock, are still in use today. Motif and the CDE have historically been the X11 environment of choice for commercial Unix, though they are slowly being edged out by the newer GNOME, KDE, and others; and are rarely used on modern OSS systems.

The Xt specification states quite clearly that it is supposed to be somewhat object-oriented. Most OO nuts would balk at this, but it is true; Xt allows definition of classes (ostensibly all widgets), instantiation of classes as widgets, inheritance, encapsulation, and polymorphism. That said, it does not have the clarity or ease of use one would expect. Thus, it is Object Orientation proper and not the proverbial language-specific easy-as-pie OO that was supposed to be All That Is Programming by now 10 years ago. A diagram of that sentence is left to the reader as an excercise, and so is trying to figure out if I'm advocating C or eastern religion.

Literature

The definitive source of information about Xt is the specification, available in PostScript with the X11R6 distribution or available on the web (see below). There are a great number of books, mostly from the late 80's, with information on Xlib, Xt and Motif, most notably the Animal Books. It should be noted that the X manuals were some of O'Reilly's earliest publications.

Athena

The Athena widget set is included in the X Window System distribution and is used to build the popular client programs from that package. Xterm, xedit, xman, xload and so forth are all programmed with Xt using Athena. Athena is not visually impressive, but it is free, standard and well documented. I've written my examples in athena because I like it and it mainly uses Xt calls instead of wrappers, and because you are you are guaranteed to have it if you have X.

Big, scary example program

Here's an example program for your perusal. It's not really a tutorial, though I've included a simpler "Hello, world!" program below. Browse my Athena writeup for a slower intro. Real knowledge of the C language is expected (Pointers, function pointers, struct pointers...).

This program will let you enter text into a text box, and echo to standard output when you press the button. This program is not very useful, as it is just a simplified 'echo' with an unwieldy X interface. (It could be used as a hideous text editor via redirection, though.) If I added CLIPBOARD support to it, it could pass as a deranged xclipboard.


#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/AsciiText.h>
// Truly, you need a great number of include files for any Athena
// program of size. The three under X11 are for Xt, and the three
// under X11/Xaw are each for an Athena widget.

Widget window, box, command, clear_command, quit_command, ascii;
/* Each top level window, widget, and widget container is a 'Widget' */
XtAppContext app;
/* And one of these for each application... */

Arg args[2];
int nargs = 0;
/* These two variables will be used for passing Xt arguments the 'hard' way */

String app_resources[] = {
		"*command.Label: Write text to stdout",
		"*clear_command.Label: Clear",
		"*quit_command.Label: Quit",
		"*window.Title: Hello, world in Xt/Athena",
		"*window.Geometry: 300x200+10+10",
		"*ascii.Width: 280",
		"*ascii.Height: 150",
		NULL };
/* These are the 'fallback resources'; it's naive way of 
initially setting some widget properties. */


void print_text(Widget w, XtPointer data, XtPointer call_data) {
/* All functions used as callbacks have this signature. 
If you need to pass them special info, you have to do it 
through 'data', which is really just a (void *). It's typical 
to have a few well named globals so that this is trivial. */
	String string = NULL;

	/* This is the 'interactive' way to set and get resources. 
	 * We could set more than one at a time this way.
	 * In this case, we only need to set one value (to get).
	 * (The easy way is the XtVaGetValues, which you can look up yourself)
	 */
	nargs = 0;
	XtSetArg(args[nargs], XtNstring, &string); nargs++;
	XtGetValues(ascii, args, nargs);

	printf("%s\n", string);
}

void clear_text(Widget w, XtPointer data, XtPointer call_data) {
	String string = NULL;

	/* This is the aforementioned 'easy way'. 
	 * It can't be used to give a dynamically varying number of 
	 * arguments, since the arguments are given at compile time.
	 */
	 XtVaSetValues(ascii, XtNstring, &string, NULL);
}

void quit_app(Widget w, XtPointer data, XtPointer call_data) {
	/* The manual gives this as the "right way" to end the application. 
	 * Just exiting will work, but that may cause problems on some systems.
	 */
	XtUnmapWidget(window);
	XtDestroyApplicationContext(app);
	exit(0);
}

int main(int argc, char **argv) {
	window = XtOpenApplication(&app, "window", 
		// AppContext represents the whole program, and 
		// we need a name for the top level widget

			NULL, 0, // XrmOptions; not used in this example

			&argc, argv, 
		// This allows things like the -geometry or -display options 

			app_resources, // Pass the fallback resource array
			sessionShellWidgetClass, // Indicates we're making 
			//a normal, top level window.

			NULL, 0); // For extra options set on the top level widget

	box = XtCreateManagedWidget(
		"box", // These names are used for setting resources via
		// app_resources, et cetera
		boxWidgetClass, // The 'type' of the widget; this symbol is 
		// from the widget header file
		window, // The parent of this widget
		NULL, 0); // No arguments being passed, so these are empty.
	command = XtCreateManagedWidget("command", commandWidgetClass, box, NULL, 0);
	clear_command = XtCreateManagedWidget("clear_command", 
		commandWidgetClass, box, NULL, 0);
	quit_command = XtCreateManagedWidget("quit_command", 
		commandWidgetClass, box, NULL, 0);

	nargs = 0;
	XtSetArg(args[nargs], XtNeditType, XawtextEdit); nargs++;
	ascii = XtCreateManagedWidget("ascii", asciiTextWidgetClass, box, 
		args, nargs); // Set some initial values on this widget

	XtAddCallback(
		command, // Widget who's callback we want
		XtNcallback, // Just a plain callback; there are others
		print_text, // Function to call
		NULL ); // Data pointer to send the function; in our case, none

	XtAddCallback(clear_command, XtNcallback, clear_text, NULL );
	XtAddCallback(quit_command, XtNcallback, quit_app, NULL );

	XtRealizeWidget(window); // Maps window and contained widgets
	XtAppMainLoop(app); // Roll the event looop
	
	return (0);
}

/*
Save this as xt-example.c and try
gcc -o xt-ex -L/usr/X11R6/lib -lX11 -lXt -lXaw xt-example.c
for compiling this.
*/

This program is not quite trivial (by tutorial standards), but not useful. It seperates into initializing the tookit, creating basic elements, and running the event loop. Each of the buttons calls a function, and the text box takes care of itself. The non-trivial parts of the program mostly have to do with figuring out which widget resource does what, and how to use them. If you have trouble understanding this program, here is a "Hello, world!" to get you started a little slower. Understanding of the rest of the program will probably have to be derived from reading the manual and modifying the source yourself.

#include <X11/Intrinsic.h>
#include <X11/Xaw/Label.h>
#include <X11/Shell.h>

// A handy array for setting some properties initially.
// Forget the NULL and you'll segfault, probably.
String app_resources[] = {
	"*label.Label: Hello, world!",
	NULL
};

int main(int argc, char **argv)
{
	Widget top_level, label;
	XtAppContext app;

	top_level = XtOpenApplication(&app, "Hello, world!", 
		NULL, 0, &argc, argv, 
		app_resources, sessionShellWidgetClass, NULL, 0);
	// Consider most of this magic.
	// Note app_resources and &app.

	label = XtCreateManagedWidget("label", labelWidgetClass, 
		top_level, NULL, 0);
	// No "container widget", since we just need the one


	XtRealizeWidget(top_level);

	XtAppMainLoop(app);

	return 0;
}

In contrast to a great many widget sets, Xt handles all widgets using the same set of functions. Widget sets may (and do) implement wrapper functions and special widget functionality, but they are in many cases fungible.

Xt/Motif

The Motif library was for a long time the de facto standard in Unix GUIs. Motif, owned by The Open Group, is distributed with most Unices, and there are open source alternatives such as lesstif; still, it is not quite an open technology. The Motif widget set is more advanced, both technically and visually, than the Athena widget set. Motif is widely used for building legacy Unix applications, but some popular OSS programs like Netscape also use(d) it.

Motif, or Xm, is undoubtedly 'prettier' and more sophisticated than Athena. It is also somewhat abstracted away from Xt using wrapper functions, so Motif code is not as ideal for demonstrating Xt.

Writing widgets in Xt

Certainly, a really good writeup would have an example of how to create a widget in Xt. Unfortunately, even simple widgets like the label require a gigantic amount of boilerplate work just to get started, so I won't bother. If you would like to see it for yourself, browse to xc/lib/Xaw in the X Window System distribution source.

Quick guide to important Xt concepts

Here's a rundown of the basic things you need to construct an Xt program, emphasis on Athena. The first is a list of common data structures and data, the second is a list of functions, and last (which you may want to read first) is a description of passing arguments, both the easy way and the hard way.

Data structures
  • XtAppContext: You'll need one of these for a given Xt program. It's passed to XtOpenApplication as a pointer (&app) and passed plain to mainloop.
  • Widget: Every top level window, container widget, and widget is contained in a Widget. These are set from widget creation functions, and are passed directly. (They are actually typedef'd pointers.)
  • app_resources: The type here is char**, NULL terminated. Called the fallback resources, these are used to set some initial resource values. Passed to XtOpenApplication.
  • XrmOptionDescRec: Look the exact format of these up in the manual; each of these specifies a special command-line argument passed directly to a widget resource. A NULL-terminated list of these is passed to XtOpenApplication.
  • Arg: An array of Arg's, and an integer counter, are integral in using XtSetValues and XtGetValues. Args are typically set with XtSetArg.
  • Callback functions: The signature of these is void name(Widget w, XtPointer client_data, XtPointer call_data) and they are the only type of callback function in Xt. client_data is sent whatever data was specified in the callback, and call_data is a data structure specific to the callback.
Common functions

XtOpenApplication

This is the function you use to start any Xt app. It takes a whole list of things and returns the top-level widget. You can also start the app by calling four other functions manually, to do different tasks. (Most old code contains the function XtAppInitialize, which is 'deprecated' in the spec.) Arguments in order:

  • XtAppContext*: Pass &app, your typical XtAppContext.
  • String: The name of your application and top-level widget
  • XrmOptionDescRec*, int: Array of XrmOptionDescRec entries, and how many there are. Acceptably NULL and 0.
  • &argc, argv: Absolutely necessary. Enough said.
  • String*: Usually named app_resources or similar, it's a NULL terminated list of Strings indicating initial widget settings.
  • Widget: The type of top-level widget. Typically, use sessionShellWidgetClass.
  • Arg*, int: Arguments and number, for top-level widget. See explanation below.

XtCreateManagedWidget: The canonical way of making a widget. You could theoretically make a widget with XtCreateWidget and then manage it later, but this is the easy way.

  • Returns a Widget, representing the one you've just created.
  • String name: Name used in fallback resources, et cetera.
  • Class: Class of the widget, something like labelWidgetClass or boxWidgetClass (in Athena).
  • Widget parent: The widget will show up inside this widget, if possible. Should be a container widget of some sort.
  • Arg* list, int count: Argument list to pass. See below.

XtSetValues, XtGetValues: These are pretty simple. They are used for typical value setting and getting, in the same fashion.

  • Widget: The widget to get/set values on
  • Arg*, int: List of arguments and the number of items in the list. See below.

XtAddCallback: The function that holds the whole thing together, XtAddCallback can actually be done with XtSetValues but you don't want to do it that way, probably.

More to come. Work-in-progress. Sorry.

Setting and getting values

You should learn early on how to set and get widget resources, using both the XtSetArg macro with initializers and the set/get functions, as well as with the XtVa* functions. The fallback resources are also important.

The hard way is to pass normal initializers (XtOpenApplication, XtCreateManagedWidget) a special array, built up with XtSetArg macro. In contrast to regular argument passing in C functions, this is very laborious and inefficient, but it has advantages, such as being able to set or get a dynamic, arbitrary number of arguments with a single function call (since XtSetArg is a macro). Abstracting this process, though, is not a bad idea, as in the example function:

/* Example function for resizing a widget */
void resize(Widget my_widget, int width, int height)
{
Arg arg_list10; // Allocate more than we need, in this case
int arg_count = 0;

if( width > 0 )
 XtSetArg(arg_list[arg_count], XtNwidth, width); arg_count++;

if( height > 0 )
 XtSetArg(arg_list[arg_count], XtNheight, height); arg_count++;

if( width > 0 || height > 0 )
 XtSetValues(my_widget, arg_list, arg_count);
}

Sources, etc.

  • Much thanks to Linux Programming Unleashed
  • The Xt and Xlib specs can be gotten with the X11R6 source distribution, or found at ftp://ftp.x.org/pub/R6.6/xc/doc/hardcopy/
  • http://www.x.org

Log in or registerto write something here or to contact authors.