SWAPI - Simple Windowing Application Programmer Interface


IMPORTANT NOTE:

Don't believe a word of what I've written here. This is only a draft of the documentation, but the library itself hasn't been written yet. I have some parts of it working under DOS and UNIX/X11 (taken from DEU), but nothing yet for Windows, OS/2 or Mac.

Every time you read ``SWAPI does this or that'', think about it as ``SWAPI will do...'' or ``SWAPI should do...''. This document explains what I want to do with SWAPI, but I wrote it as if SWAPI was already done so that I can re-use this text in the final documentation.

1. What is SWAPI?

SWAPI is a graphics library which provides a common interface for creating applications under different systems: DOS, Windows, OS/2, Mac and UNIX/X11. A program developped for SWAPI can be compiled on any of these systems without any modifications. SWAPI can be freely distributed and used, and a program compiled with this library can be distributed without any restrictions, although a credit notice in the program and its documentation would be appreciated.

SWAPI provides only a limited set of functions (hence the prefix ``simple'') in order to ensure the best compatibility between the different systems. But it has enough features to allow the creation of programs managing several windows with pull-down menus, scrollable areas, dialog boxes, etc. Under DOS, this library also provides a simple user interface with some windows management functions. Under all other systems, it uses the existing user interface.

Although it is based on object-oriented concepts, SWAPI only requires an ANSI C compiler and does not use C++. Free ANSI C compilers are available on different systems, which is not the case for C++ (GNU g++ is an excellent free compiler, but the license for the g++ classes library restricts the distribution of compiled programs). Personal note: another reason why I did not choose C++ is because I think it is a dead end since Java does a much better job at introducing object-oriented concepts in a C-like language.

SWAPI also provides a small set of miscellaneous functions for accessing various features of the underlying operating system in a portable way. This includes the file I/O functions, reading the list of files in a directory or folder, playing sounds, getting the current time, setting timers, etc.


2. Structure of an application

The typical structure of an application using SWAPI is very similar to what one can find in X Window, Windows and other windowing environments.

  Application
    |
    +-- Main window
    |     |
    |     +-- Menu bar
    |     |     |
    |     |     +-- Menu
    |     |     |     |
    |     |     |     +-- Menu entry
    |     |     |     |
    |     |     |     +-- Menu entry
    |     |     |     |
    |     |     |     +-- ...
    |     |     |
    |     |     +-- Menu
    |     |     |
    |     |     +-- ...
    |     |
    |     +-- Document window
    |     |     |
    |     |     +-- (see list of gadgets below)
    |     |     |
    |     |     +-- ...
    |     |
    |     +-- Document window
    |     |
    |     +-- ...
    |
    +-- Popup window (exclusive or not; for dialog boxes, toolbars, ...)
    |     |
    |     +-- (see list of gadgets below)
    |     |
    |     +-- ...
    |
    +-- Popup window
    |
    +-- ...

No gadgets in the main window?

Note: Usually, the document windows will be children of the main window and will be confined into it. But this feature is not supported by all systems, so they could also be independent windows that can be moved freely. However, this minor difference in the user interface doesn't change anything for the programmer.

Here is the list of elements (``gadgets'') that can be included in a window:

Should I use ``gadget'' or ``widget'' or ``element''?

  Document window, popup window or frame
    |
    +-- Frame (divides a window into several non-overlaping frames)
    |     |
    |     +-- (any gadgets)
    |     |
    |     +-- ...
    |
    +-- Text label (single line)
    |
    +-- Text box (multi-line with word wrap)
    |
    +-- Image
    |
    +-- Scrollable drawing area (for general use)
    |
    +-- Button (with image and/or text label)
    |
    +-- List box (scrollable)
    |
    +-- Text or number input box
    |
    +-- Check box
    |
    +-- Radio button
    |
    +-- ...

The last six elements (drawing area, button, list box, input box, check box and radio button) are ``active'' elements: they have one or several callback functions associated with them, which will be called when the user performs some action such as pressing or releasing a key or mouse button while the pointer is inside the active area of the element. The other elements (frame, text and image) are ``static'': the user cannot perform any action on them, although their contents can be updated by the program in response to an action on one of the ``active'' elements.

The programmer should provide a callback which redraws the contents of a drawing area. All other elements (buttons, text, images) are re-drawn automatically by the library or by the underlying system.


3. Summary of the functions provided by SWAPI

3.1. Data types

The following data types are defined in the include file for this library. They are used by almost all functions of this library. Some of them are provided for OS compatibility reasons (all integer types) and some others are new types defined by SWAPI.

Int8, Int16, Int32
Signed integers with the specified number of bits. These types should always be used when a fixed number of bits is required, instead of using short or long which do not have the same meaning on all machines. The only exception is the standard type int which should be used when the number of bits doesn't matter (i.e. not in structs or in data files, but as a control variable for loops or other internal stuff).
UInt8, UInt16, UInt32
Unsigned integers with the specified number of bits. See above.
Bool
Boolean variable which can take two values: TRUE or FALSE.
SWindow
Window identifier. This should be considered as an opaque identifier because it will be mapped on different types of structures, depending on the environment for which SWAPI is compiled. The SWindow type is used for the main window, a document window or a popup window.
SGadget
Gadget identifier. It contains a reference to the window in which the gadget is included.
struct SBitmap
{
  Int16   width;
  Int16   height;
  UInt8  *data;
}
Defines an image, using the current 256-colors palette.
struct SPosition
{
  SGadget attach_left;
  Int16   offset_left;
  SGadget attach_up;
  Int16   offset_up;
  SGadget attach_right;
  Int16   offset_right;
  SGadget attach_down;
  Int16   offset_down;
}
Defines the position of a gadget and how it should behave when the window is resized. Its position can be relative to another gadget (gadget identifier stored in attach_*) or to the border of the window (using the special gadget identifiers S_LEFT_BORDER, S_UPPER_BORDER, S_RIGHT_BORDER and S_LOWER_BORDER). The offset_* fields define the spacing between gadgets. See section 3.5 for more details.
SFontType
Font identifier. Valid values are: S_FIXED_FONT, S_SERIF_FONT and S_SSERIF_FONT, which are equivalent to Courier, Times and Helvetica (if these fonts are available on the system).
SCallback

Missing description

3.2. OS abstraction and miscellaneous functions

Several functions are provided in order to make sure that DEU can run in the same way on all systems. They provide a common way to access OS-dependent features or common functions which have a slightly different behaviour on some systems (like malloc). Some other useful functions are also provided by SWAPI, although they are not directly related to the user interface.

Missing stuff (sounds, list of files)...

void *SMalloc(UInt32 size);
void *SRealloc(void *old_ptr, UInt32 new_size);
void SFree(void *ptr);
These functions provide a safe way to allocate memory: they will never return a NULL pointer. If an error occurs (e.g. out of memory or attempt to allocate zero bytes), the SWAPI error handler will be called. If a NULL pointer is passed to SRealloc, it will behave as SMalloc. If a non-NULL pointer is passed to SRealloc and the size is zero, it will behave as SFree. If a NULL pointer is passed to SFree, it will simply return.
S_ASSERT(condition)
This is not a function, but a macro. It will stop the program and report an error assertion violated if the condition is not true. The error message will be sent to the SWAPI error handler and will contain the name of the source file in which the error occured, as well as the line number. By default, these tests will be deactivated (removed by the preprocessor). In order to enable these tests, your program must be compiled with the SDEBUG symbol defined (this is different from the ASSERT macro provided by some systems, which only works when NDEBUG is not defined).

3.3. Windows

void SMainLoop(SWindow main_win);
This is the main loop of the application. It should be called after the main window has been created and it will not return until that window is closed. This function will deal with all the events that are sent to the application and will call the various callback functions.
SWindow SCreateMainWindow(char *title, Int16 sugg_x, Int16 sugg_y,
                          Int16 sugg_width, Int16 sugg_height);
This creates the main window for your application and initializes the SWAPI library. This should be the first function that you call in your application (except for the functions listed in section 3.2, which can work before the graphical part of SWAPI is initialised). The coordinates and size of the window may be overriden by the underlying windowing system or by the user, so your application should not rely on a specific size of its windows. This is why the parameters are prefixed with sugg_ for suggested. If the user tries to close the main window while there is still a document window open, the close_cb function for each document window will be called first, and its return value will be checked. You can only have one main window in your application.
SWindow SCreateDocumentWindow(SWindow main_win, char *title,
                              Int16 sugg_width, Int16 sugg_height,
                              SCallback *close_cb);
Creates a document window, as a child of the main window. The function close_cb will be called when the user wants to close the window. It may be used to check if all files are saved or to ask for confirmation. If the callback function returns TRUE, the window will be closed. Otherwise it will not be affected.
SWindow SCreatePopupWindow(SWindow main_win, char *title,
                           Int16 sugg_x, Int16 sugg_y,
                           Int16 sugg_width, Int16 sugg_height,
                           Boolean exclusive, SCallback *close_cb);
Creates a popup window. If exclusive is TRUE, the other windows will be frozen until this one is closed. If exclusive is FALSE, the application will continue normally. Non-exclusive popup windows may be used for floating toolbars or dialog boxes. The function close_cb will be called when the user wants to close the window.
SWindow SDisplayWindow(Swindow win);
Displays a window. When you create a window, it is not displayed immediately on the screen. This allows you to create the gadgets inside the window before it is shown to the user. Functions that require the window to be displayed on the screen (such as SGetWindowWidth) will fail if you call them before calling SDisplayWindow. The main window must be displayed before you can create a document window.
SWindow SDestroyWindow(Swindow win);
Closes a window and destroys all its gadgets.

3.4. Menus

3.5. Gadgets

SGadget SCreateTextLabel(SWindow win, SPosition pos, char *text);
Adds a single line of text in the current window. The position of this label is given indirectly by the constraints in the pos structure. This label will be automatically redrawn by SWAPI when he system requests it. If the window is resized, the label will be moved to a new position according to the constraints in pos.
void SChangeTextLabel(SGadget g, char *text);
Changes the text.
SGadget SCreateTextBox(SWindow win, SPosition pos, char *text);
Creates a multi-line text area. The position and size of the box are given indirectly in pos. The text will be displayed on multiple lines if necessary, with word wrapping. The box doesn't have a frame around it: it only refers to the area inside which the text will be displayed.
void SChangeTextBox(SGadget g, char *text);
Changes the text.
SGadget SCreateImage(SWindow win, SPosition pos, SBitmap *image);
Displays a static image. If the image is larger than the bounding box given indirectly by pos, it will be clipped.
void SChangeImage(SGadget g, SBitmap *image);
Replaces the image by a new one.
SGadget SCreateDrawingArea(SWindow win, SPosition pos, Int16 max_width,
                           Int16 max_height, SCallback *action_cb,
                           SCallback *repaint_cb);
Creates an empty drawing area. The size and position of this area on the screen are given indirectly by the constraints in pos. The maximum size of this area is given by max_width and max_height. If the screen size is smaller than the maximum size, scrollbars will be displayed.
The function action_cb will be called when the user presses a key or a mouse button while this area is active (while the pointer is inside it).
The function repaint_cb will be called every time the contents of that area have to be redrawn: when the area is displayed on the screen for the first time, when the scrollbars are moved, when the window has been resized or cleared, etc.
void SChangeDrawingAreaSize(SGadget g, Int16 max_width, Int16 max_height);
Changes the maximum size of a drawing area. This will usually call the repaint_cb function for this area.
SGadget SCreateButton(SWindow win, SPosition pos, SBitmap *image,
                      char *text, SCallback *action_cb);
Adds a button, which can contain either an image or a text label. If image is NULL, only the text will be displayed. When the button is pressed, action_cb is called.
void SChangeButton(SGadget g, SBitmap image, char *text);
Changes the image or the text which is displayed in the button.
SGadget SCreateListBox(SWindow win, SPosition pos, Int16 num_elems,
        char **elems, SCallback *action_cb);

void SChangeListBox(SGadget g, Int16 num_elems, char **elems);

Missing description here...

SGadget SCreateInputBox(SWindow win, SPosition pos, );

void SChangeInputBox(SGadget g, );

Missing description here...

SGadget SCreateCheckBox(SWindow win, SPosition pos, char *text,
                        Boolean checked, SCallback *action_cb);
Creates a check box with an optional text label. If checked is TRUE, a tick mark will be displayed in the box.
void SChangeCheckBox(SGadget g, Boolean checked);
Changes the status of the check box.
SGadget SCreateRadioButton(SWindow win, SPosition pos, Int8 group,
                           char *text, Boolean selected,
                           SCallback *action_cb);
Creates a radio button. Several radio buttons will be logically linked if they use the same group number. Only one button in a given group can be selected. If no buttons are selected when the window is displayed, the first one will be selected by default. The action_cb will be called when the selection changes (first, the callback of the button which is unselected, then the one for the button which is selected).
void SChangeRadioButton(SGadget g, Boolean selected);
Changes the status of the radio button. The only meaningful value for selected is TRUE, because you can only select a radio button which was previously unselected. An attempt to unselect a button without selecting another one will be ignored.
Boolean SIsGadgetActive(SGadget g);
This function returns TRUE if the specified gadget is active (i.e. if it accepts user input). If the gadget has been deactivated, it will return FALSE. If an ``exclusive'' popup window is open, this function will return FALSE for all gadgets that are not in that window, regardless of their normal status.
void SActivateGadget(SGadget g);
Activates a gadget that has been deactivated.
void SDeactivateGadget(SGadget g);
Deactivates a gadget. By default, all gadgets are created in the active state. If you want to display a window in which some gadgets are already deactivated, you must explicitely call SDeactivateGadget before you call SDisplayWindow.
UInt16 SGetScreenWidth(void);
UInt16 SGetScreenHeight(void);
Gets the maximum dimensions of the screen. This can be useful if you want to know how large your windows can be or if you want to center a window on the screen. Remember that you can only supply a suggested position and size for your window: the system or the user can override your settings.
UInt16 SGetWindowWidth(SWindow w);
UInt16 SGetWindowHeight(SWindow w);
Gets the size of a window. Just in case you forgot to save its dimensions when you created it, or after having received a resize notification.

3.6. Graphics

If all systems support multiple ``graphics contexts'', ``brushes'' or ``pens'', it would be better to add this as a parameter to all drawing functions. Or maybe each drawing area gadget could contain a reference to a graphic context (which could of course be shared by several gadgets). It should be possible to use different default colors and scale parameters in different drawing areas.

void SDrawScreenLine(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SDrawScreenRectangle(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SFillScreenRectangle(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SDrawScreenCircle(SGadget g, Int16 x, Int16 y, UInt16 radius);
void SFillScreenCircle(SGadget g, Int16 x, Int16 y, UInt16 radius);
void SDrawScreenBitmap(SGadget g, Int16 x, Int16 y, SBitmap bitmap);
void SDrawScreenText(SGadget g, Int16 x, Int16 y, char *text);
These functions are self-explanatory. They can only be used inside a drawing area gadget. The x and y coordinates are relative to the top left corner of the drawing area.
void SDrawScaledLine(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SDrawScaledRectangle(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SFillScaledRectangle(SGadget g, Int16 x1, Int16 y1, Int16 x2, Int16 y2);
void SDrawScaledCircle(SGadget g, Int16 x, Int16 y, UInt16 radius);
void SFillScaledCircle(SGadget g, Int16 x, Int16 y, UInt16 radius);
Same functions as above, except that they use world coordinates instead of screen coordinates. The figures are scaled and translated according to the parameters defined in the following functions.
void SConvertToScaledCoords(Int16 x, Int16 y, Int16 *new_x, Int16 *new_y);
void SConvertToScreenCoords(Int16 x, Int16 y, Int16 *new_x, Int16 *new_y);
void SSetScale(Int16 x_mult, Int16 x_div, Int16 y_mult, Int16 y_div);
void SGetScale(Int16 *x_mult, Int16 *x_div, Int16 *y_mult, Int16 *y_div);
void SSetRealScale(float x_scale, float y_scale);
void SSetOffset(Int16 x_off, Int16 y_off);
void SGetOffset(Int16 *x_off, Int16 *y_off);
These functions define the scale and offset that should be applied to all objects drawn in world coordinates. The scale is stored internally as a pair of integers (multiplier and divider), but the SSetRealScale function can be used to set these parameters from a floating point value (approx.).
void SSetFont(SFontType font, int pt_size);
Changes the current font. SWAPI will try to use a font that matches the given parameters (type and size), but not all systems provide all fonts with all font sizes. If there is no exact match, SWAPI will pick the best one. Your mileage may vary.
void SSetColor(Int8 red, Int8 green, Int8 blue);
Selects a color by giving its R,G,B components.
void SSetColorPalette(SPalette pal);
Changes the color palette.
void SSetColorIndex(Int8 pal_idx);
Selects a color by choosing its index in the current palette.
void SSetLineWidth(int width);
The line width can be 1 or 3. No other widths are supported (that's a limitation in some graphics packages).

Should this option be supported? Who will use thick lines?

void SSetLineStyle(int style);
The line style can be S_SOLID_STYLE, S_DOTTED_STYLE or S_DASHED_STYLE. Some systems will not support non-solid styles for circles, so it is better to use the special styles for lines only.
void SSetDrawMode(int mode);
The drawing mode can be S_NORMAL_MODE or S_XOR_MODE.

4. xxxxx

4.1. Callback functions

Several functions in the

4.2. Resizing the windows


5. Portability

5.1. xxx

ANSI C only: C++ comments (``//'') are not allowed.


The name of this page is likely to change as the specification evolves. Do not put this page in your bookmarks; put the previous one instead.