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
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.