Xterminal
An Object Oriented text-based User Interface with a
Client-Server Architecture

Dragos Acostachioaie
Adrian Teohar
dragos[at]biosfarm[dot]ro




Abstract


This paper presents a project we start working to. Xterminal is an Object Oriented User Interface with a client-server architecture. The main purpose is a friendly interface for the UNIX-like operating systems. It is designed to be used to build text based applications, and is written in C++ using the ncurses library.
It consists in a complete object oriented library including multiple, resizeable, overlapping windows, pull-down menus, dialog boxes, buttons, scroll bars, input lines, check boxes, radio buttons, etc. Mouse support will come too, soon.
Xterminal is not just a object hierarchy; it includes advanced object management, events handling, communications between objects, and so on...


Introduction

During the last few years, the importance of the program's user interface have become crucial. So, the attention of software developers is moved, in most cases, from the application itself to it's user interface. Because of the interface's complexity, it is more convenient to partition it in more pieces, in small objects. The object oriented programming seemed to be a good candidate for the user interfaces development.
Nowadays, object oriented programming have become very popular. That's because it's well-known advantages which helps the development of today's projects, that are becoming more and more complex. It makes the applications to split into several modules, relieves the developer of a module of having knowledge of the other's implementation details. This way, the application's development time and it's price is decreasing, and it's quality is growing.
These things leads to the idea that the user interface should be implemented as a library, and the programmer should not have any idea about it's internal implementation, but only about the results.
Xterminal is such of library, for the UNIX-like operating systems. It operates in text mode, because we think that is a very amount of applications that does not need a graphically environment. It is very useful for building text based applications that need high implementation level, high performance, flexibility, and a interactive user interface.
Xterminal is a hierarchy, not just a collection of disjoin objects. It includes almost everything that you need for a coherent user interface. Anyway, you can use only one or more objects. It won't force you to use all of it, as Turbo Vision does.


Implementation

To give our library fully compatibility on different UNIX systems and on different terminal types, we use the ncurses library. The ncurses library gave us some terminal independent methods to use the full screen with reasonable optimizations. Also, Xterminal uses the gpm mouse server on Linux consoles to provide the mouse support.
The requirements in order to compile Xterminal are:
- GCC 2.6.8 or higher
- ncurses 1.8.6 or higher
Xterminal was developed under Linux and it's appearence on console is great. It should work without modifications on other systems, too.

Every object is derived from an abstract object, XObject. It have an object id associated to it. The library itself maintain a internal table of instantiated classes. It knows how to send a message to a specific object, too. There are three types of objects:
- abstract objects, which cannot be instantiated, but only declared. It's purpose is to provide a general manipulation to a class of objects;
- passive objects, which only displays something, but the user cannot control them;
- active objects, which the user can do something with them, and which knows to answer in a way to the user input.

class XObject {
  unsigned id;                        // object's id
  XPoint origin, size, cursor;        // origin relative to the server, size, cursor position
  XRect bounds;                       // these are the real bounds, in absolute coordinates
  XObject *server, *client;
  unsigned state;
  XObject(XRect _bounds);
  virtual void calculateBounds();
  virtual void draw();
  virtual void handleEvent(XEvent *); // draw the object on the screen
  virtual void registerClient(XObject *newClient);
  ...
}

Each object have a 'state' field associated with it, which indicates the current properties of the object. Some possible values are:
- SM_VISIBLE indicates that the object is visible on the screen, so it is in a drawn state;
- SM_FOCUSED indicates that the object have the control at the respective moment (oly one object can have the control at a moment, so if the user press, let's say, a key, this object will receive the event);
- SM_DISABLED indicates that the object is deactivated at a moment;
- SM_ACTIVE indicates that the object is active, so the user have a control to it.
The 'server' field points to the server (owner) of the object, or NULL if object have no server or it's a server itself.
The 'client' field is a linked list of registered clients of the object (if he is a server).
If the object is a server (a dialog box, for example), you can insert a client in it with 'registerClient()' method. This will register the new client and will adjust his bounds (which are relative to the server). When the 'draw()' method is called, the server will automatically draw all his clients. When an event is passed to the server, he'll automatically ask it's clients to treat the event.

The events are not passed sincronously to the objects to which are addressed, but using a event queue. That doesn't mean the events will be delayed, anyway. The application will automatically query the system for events (from keyboard, from mouse, messages from other objects, UNIX signals), will find the object that event is addressed to, and will insert them into the queue.
The structure of an event looks like this:

struct XEvent {
  unsigned oid;                  // object that event appart to
  unsigned what;                 // type of event
  struct ev_mouse {              // an event from mouse
    int buttons;
    unsigned dbl;
    XPoint where;
  } evMouse;
  struct ev_keyboard {           // an event from keyboard
    int keyCode;
    char charCode;
    unsigned char scanCode;
  } evKeyboard;
  XMessage evMessage;            // a message
}

struct XMessage {
  unsigned sid, rid;             // Sender and Receiver's ID
  unsigned msgClass;             // message class
  int message;
  char *msgText;
  void *ptr;
}

Message classes:

- MC_CLIENTTOSERVER, from a client to a server;
- MC_CLIENTTOCLIENT, from a client to another client;
- MC_SERVERTOCLIENT, from a server to a client;
- MC_BROADCAST, broadcast message which is sent to all the objects.

Basically message texts:

- MT_ANSWERREQUEST, used by a server to ask something from a client;
- MT_REQUESTHONORED, used by a client do answer to a server request;
- MT_RELEASEFOCUS, used by a server to ask a client to release the focus (the client will loose the user control);
- MT_RESUMEFOCUS, used by a server to ask a client to resume the focus (the client will gain the user control).

Type of events:

- EV_NOTHING, no event for an object;
- EV_MOUSE, an event from mouse;
- EV_kEYBOARD, an event from keyboard;
- EV_MESSAGE, a message from an other object.

A message to an object is, in fact, an event that points to it. The messages are very important in Xterminal. In fact, Xterminal is based on the communications between objects.


Conclusions and future work

The latest version of Xterminal may be found on sunsite.unc.edu ftp server, in /pub/Linux/libs. Further work will be to develop a graphical user interface for Linux, and to finish the whole object hierarchy.


Xterminal's Hierarchy



Xterminal
  |
  +- XObject
  |   +- XtDialog ---- XtDialogBox
  |   +- XtWindow ---- XtTextEditor
  |   +- XtButton
  |   +- XtInputStringField
  |   +- XtStaticText
  |   +- XtScrollBar
  |   +- XtProgressbar
  |   +- XtBackground
  |   +- XtDesktop
  |   +- XtApplication
  |   +- XtCheckButton
  |   +- XtRadioButton
  |   +- XtListBox
  |   +- XtStatusItem ---- XtStatusLine
  |   +- XtMenuItem   ---- XtSubMenu ---- XtMenu
  +- XPoint
  +- XRect
  +- XMessage


Note: this text was published in ROSE'96 Proceedings (Technical Sessions) Book, p. 59-63.
You can also read the speech I had.