Technical Notes
OverviewWindowing System Assumptions and Limitations
The Spontaneous Assembly windowing system is designed from the ground up to be high-speed and highly flexible. The windowing system is not designed to be compatible with windowing or console I/O systems available through other software manufacturers.
_win_init must be called to initialize the windowing system before windowing functions may be used. This restriction is documented in the reference section.
Note that _console_init must also be called before _win_init is called. This allows _console_init to determine the state of the screen for _win_init.
Each window is like a logical screen. Every window supports its own cursor position, cursor shape, clipping region, attribute table, current and default attributes, etc. Characters and attributes are displayed to a window using the standard console I/O functions. Output which does not fall within the boundaries of the window is clipped and lost.
Windows must be created before they can be manipulated. When a window is created it is assigned a handle. This handle is used to identify the window when a windowing function is performed (i.e., opening, closing, removing, changing the shadow, or selecting the window as the active window). Up to 4095 window handles may be in use at one time.
Each window is assigned a distinct buffer when it is created. This buffer is used to maintain all the information about the window, including the cursor position, cursor shape, border appearance, shadow information, etc. In addition, all of the characters and attributes which are displayed to the window are maintained in the buffer. These buffers must be allocated by the application and passedto the _win_create function when the window is created. This allows the programmer to select the window buffer memory allocation scheme.
(-32K,-32K) ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ (32K,-32K)
³ ³ ³
³ ³ ³
³ ³ ³
³ ³ ³
³ ³ ³
³ (0,0)³ ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄ´
³ ³ Screen ³ ³
³ ³ ³ ³
³ ÃÄÄÄÄÄÄÄÄÙ ³
³ ³ ³
³ ³ ³
³ ³ ³
(-32K,32K) ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ (32K,32K)
The Window Plane
Windows may be moved from one level to another by calling _set_wlevel. An attempt to move a window to a nonexistent level results in an error.
In most cases, handles and level numbers are interchangeable. This means that functions which require a window handle will generally accept a level number instead. This makes it easy to manipulate windows on the basis of their relative order. For example, the current top window may be closed simply by calling _win_close with 1, and the bottom window may be closed by performing the same operation with -1.
STDWIN is the default window. This means that it becomes the active window when the windowing system is initialized or when the active window is deleted and there are no remaining open windows in the system.
The word "STDWIN" is a symbolic constant that may be used as a handle for STDWIN. It is defined in WINDOW.INC.
Because STDWIN is temporary and resides on the top level (above all other windows), it CANNOT be used as a background or backdrop window. See The Backdrop, below, for a discussion of different methods of creating a background or backdrop for the windowing system.
Two types of backdrops are supported. The first kind of backdrop is made up of a fill character and attribute. This creates a uniform background. The second type of backdrop is a full screen "snapshot" which defines a character and attribute for every position on the screen. This allows windowing to take place on top of a predefined background screen. The data structure which defines the appearance of the screen for this second type of backdrop is called a backdrop buffer. Information is maintained in the backdrop buffer in the same format as the buffer returned by the _save_screen function. This allows windowing to be performed on top of an existing screen simply by calling save_screen to take a "snapshot" of the screen and then installing the snapshot as the backdrop.
When the windowing system is initialized, _win_init establishes a default character/attribute backdrop using the space character (0x20) and the console I/O system default attribute. A different character/attribute pair may be specified for the backdrop by calling _set_backdrop, or a backdrop buffer may be installed by calling _set_backdropbuf. The background character and attribute are not used as long as a background buffer is installed. _set_backdropbuf may be used to remove the currently installed background buffer at any time, in which case the backdrop is again defined by the backdrop character and attribute.
An alternate method of creating a background effect is to create a full-screen window which is always kept at the lowest window level. Such a window is technically not a "backdrop" as defined above since its level can change, it can obscure other windows in the system, and it can even be written to, but this can be advantageous in some applications. To establish a full-screen window as a backdrop, following these steps:
The top open window has particular significance because it is the window which defines the position and shape of the hardware cursor. If the cursor is at the home position in the top openwindow, the hardware cursor appears at the screen position which corresponds to the upper left corner of the top open window. If a block cursor is specified for the top open window, the screen cursor appears as a block cursor. If the cursor has been turned off in the top open window, the hardware cursor does not appear on the screen. If the top open window has been moved off the screen, the hardware cursor is not visible. In short, the top open window "owns" the hardware cursor.
If no windows are open or if there are no windows in the system, STDWIN acts as the default top open window.
Each of the windows below have different border regions and active regions. In each case, the active region is shown in gray and the border region is the remainder of the window. Window #1 has a border region of one column or row per side. Window #2 has a border region of 2 columns on each side and one row on the top and bottom. Window #3 has a border region of two rows on the top, two columns on the right side, one row on the bottom, and four columns on the left side. Window #4 has no borders. Note that the border region may be more than one column or row wide, even though the border is only drawn around the outside edge of the window. The border region must be explicitly reserved by specifying the width of each border edge when the window is created.
ÕÍÍÍÍÍÍÍÍ͸ ÚÄÄÄÄÄÄÄÄÄ¿ ÖÄÄÄÄÄÄÄÄÄ· ±±±±±±±±±±±
³±±±±±±±±±³ ³ ±±±±±±± ³ º º ±±±±±±±±±±±
³±±±±±±±±±³ ³ ±±±±±±± ³ º ±±±±± º ±±±±±±±±±±±
³±±±±±±±±±³ ³ ±±±±±±± ³ º ±±±±± º ±±±±±±±±±±±
³±±±±±±±±±³ ³ ±±±±±±± ³ º ±±±±± º ±±±±±±±±±±±
ÔÍÍÍÍÍÍÍÍ; ÀÄÄÄÄÄÄÄÄÄÙ ÓÄÄÄÄÄÄÄÄĽ ±±±±±±±±±±±
WINDOW #1 WINDOW #2 WINDOW #3 WINDOW #4
The border descriptor defines the eight characters used to create the window border. The border structure is defined in WINDOW.H as follows:
typedef struct { /* example border descriptor */
char upper_left; /* upper left corner border character */
char top; /* top row border character */
char upper_right; /* upper right corner border character */
char right; /* right side border character */
char bottom_right; /* bottom right corner border character */
char bottom; /* bottom row border character */
char bottom_left; /* bottom left corner border character */
char left; /* left side border character */
} border;
The border attribute specifies the foreground and background colors of the border characters. This attribute applies to all eight border characters. If an attribute table has been assigned to the window, the border attribute is interpreted as a table index and the corresponding attribute table entry is used as the border color. Blinking borders are supported.
The four border size parameters determine the number of rows or columns in the border region on each side of the window. If any of these parameters is zero, the corresponding side of the window will not have a border. Setting all of these parameters to zero results in a window without a border. A value larger than zero reserves the specified number of rows or columns as border region on the specified side of the window.
The shadow descriptor defines the nine characters used to create the window shadow. A shadow descriptor must be structured as follows:
typedef struct { /* example shadow descriptor */
char upper_left; /* upper left corner shadow character */
char top; /* top row shadow character */
char upper_right; /* upper right corner shadow character */
char right; /* right side shadow character */
char bottom_right; /* bottom right corner shadow character */
char bottom; /* bottom row shadow character */
char bottom_left; /* bottom left corner shadow character */
char left; /* left side shadow character */
char fill; /* shadow fill character */
} shadow;
If -1 is specified as a shadow character, the corresponding shadow position is transparent. This is most commonly used to create a "see through" shadow (all positions set to -1) or a shadow with a transparent center region (fill character set to -1).
The shadow attribute specifies the foreground and background colors of the shadow characters. This attribute applies to all nine shadow characters. If an attribute table has been assigned to the window, the shadow attribute is interpreted as a table index and the corresponding attribute tableentry is used as the shadow attribute. Special attribute values may be specified to designate attributes which are transparent (-2) and attributes which have a transparent background and a specified foreground color (0xF0 through 0xFF). (See Transparent Shadows, below, for more information.) Blinking shadows are not supported.
The shadow offset controls the position of the shadow relative to the window position. The shadow position is specified using signed horizontal and vertical offsets. This allows the shadow to be positioned an arbitrary distance in an arbitrary direction from the window.
The shadow type defines the type and state of a shadow. It is specified using the following symbolic constants:
S_HALFHGHT produces a shadow which is the same width as the window and one row longer than the window. This shadow type should be specified when creating a shadow using half-height top and bottom characters such as the half-height block characters 'Ü' (0xDC) and 'ß' (0xDF) or the single horizontal line character 'Ä' (0xC4).
S_HALFWIDTH produces a shadow which is the same height as the window and one column wider than the window. This shadow type should be specified when creating a shadow using half-width side characters such as the half-width block characters 'Ý' (0xDD) and 'Þ' (0xDE) or the single vertical line character '³' (0xB3).
S_HALFHW is a combination of the S_HALFHGHT and S_HALFWIDTH constants. It produces a shadow which is one row and one column larger than the window. This shadow type may be used to produce shadows suitable for both monochrome and color monitors. (The window below demonstrates this type of shadow. The shadow consists of single horizontal and vertical line characters.)
ÛßßßßßßßßßßÛÄ¿
Û Û ³
Û Û ³
Û Û ³
Û Û ³
ÛÜÜÜÜÜÜÜÜÜÜÛ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÙ
S_OFF turns the shadow off. It may be logically ORed with any of the other shadow type constants.
The symbolic constants described above are defined in WINDOW.H.
The SHADOW_TRNSPRNT shadow style specifies transparent characters as the nine shadow characters. This causes the characters beneath the shadow to remain visible while inheriting the shadow attribute. This gives the shadow the appearance of being "see through."
The SHADOW_HALFHGHT shadow style specifies the 'Ü' (0xDC) and 'ß' (0xDF) half block graphic characters for the top and bottom shadow characters and the 'Û' (0xDB) block graphic character for all other shadow characters. This style also specifies S_HALFHGHT as the shadow type, and it forces the background color of the shadow attribute to be BK_TRNSPRNT. This style creates the narrowest possible shadow. This type of shadow is suitable for creating "buttons" like the one shown below:
±±±Ü
ßßßßßßßßß
Using Attribute Tables in Windows
Each window maintains its own attribute table address. If an attribute table is specified for the active window, all console I/O is performed using the attributes defined in that table. (See Using Attribute Tables in the Console I/O technical notes for more information about using attribute tables with console I/O functions.)
Attribute tables are also supported by the windowing functions. If an attribute has been specified for a window, the window, border, or shadow attributes for the window are interpreted as attribute table codes. (The STDWIN attribute table is used when the backdrop attribute is specified.) The attribute in the table which corresponds to the attribute code is then used as the actual display attribute. This makes it possible for different windows to be displayed using different colors simply by specifying different attribute tables for each window. This also makes hardware independent windowingpossible. (See Using Attribute Tables in the Console I/O technical notes for more information about hardware independence.)
Window descriptors may be created using the sawin structure defined in WINDOW.H. This structure is organized as follows:
typedef struct {
int left; /* left margin of window */
int top; /* top row of window */
unsigned char width; /* width of window (in columns) */
unsigned char height; /* height of window (in rows) */
unsigned char dattr; /* window default attribute */
unsigned char tprows; /* number of top border rows */
unsigned char rtcols; /* number of right border columns */
unsigned char bmrows; /* number of bottom border rows */
unsigned char ltcols; /* number of left border columns */
void * border; /* pointer to the border descriptor */
unsigned char battr; /* border attribute */
char horz; /* shadow horizontal offset */
char vert; /* shadow vertical offset */
unsigned char stype; /* shadow type flags */
void * shadow; /* pointer to shadow descriptor */
unsigned char sattr; /* shadow attribute (the shadowed area's color) */
void * attrtbl; /* pointer to the window attribute table */
unsigned char curstate; /* cursor on/off state */
unsigned int curshape; /* cursor shape */
} sawin;
See Sample Code, below, for an example which demonstrates the use of the sawin structure.
Each field of the sawin structure specifies one of the characteristics of the window. sawin structure fields are defined as follows:
w_sattr Shadow attribute. If an attribute table is specified, this value is interpreted as an attribute code. If the W_INHERIT flag is used as the attribute, each shadow character inherits the attribute of the character beneath it. If the BK_TRNSPRNT flag is used as the background color, each shadow character uses the specified foreground attribute while inheriting the background color of the character beneath it. The default is DARKGRAY on BLACK.
_win_open and _win_close open and close a window. Opening a window makes it visible; closing a window makes it invisible. Both of these functions only affect the screen if auto update is on. If auto update is off, the window is flagged as open or closed, but the screen is not affected until one of the _update_... functions is called. Opening an already open window or closing an already closed window has no effect.
_win_remove is the inverse of the _win_create function. It deletes a window from the windowing system and returns the address of the buffer originally assigned to the window. It is the programmer's responsibility to properly dispose of the window buffer. Window buffers are commonly allocated on a heap and may be freed when a window is deleted. Deleted windows are automatically closed.
_win_move and _set_wpos move a window to a new position in the window plane. _win_move moves a window relative to its current position. _set_wpos moves a window to a new absolute position. The new coordinates specify the position of the upper left-hand corner of the window.
Accessing the Border Region
_draw_wborder redraws the border of the active window by overwriting the outermost rows and columns of the window. If the border size for any of the sides is zero, that side remains unchanged. Only the outermost rows and columns of the window are redrawn, even if more rows or columns have been reserved for the border.
_set_wborder installs a new border descriptor and/or border attribute in any window. If auto update is on and the window is open, the border is immediately redrawn on the screen using the new border definition.
If auto update is on, the screen is immediately updated to reflect changes in the window hierarchy.
_get_wlevel and _get_whandle are inverses of each other. _get_wlevel returns the level of the window associated with a specified handle. _get_whandle returns the handle of a window at the specified level.
_get_wpos returns the current position of the upper left-hand corner of a window in the window plane.
_get_wspec returns a window descriptor for a given window (see Creating Windows, above, for a detailed description of window descriptors). This specifies all current information about a window, including its shadow offset, border style, border descriptor address, etc. This information is frequently used to resize a window (see Resizing Windows, below).
_set_backdrop and _get_backdrop set and return the current backdrop character and attribute. The backdrop attribute is interpreted using STDWIN's attribute table if one is installed. This character/attribute pair is only used as the backdrop if a backdrop buffer has not been installed. If auto update is on, the entire screen is automatically updated with the new backdrop character and attribute when _set_backdrop is called.
_set_backdropbuf and _get_backdropbuf set and return the current backdrop buffer address. Any buffer in _save_screen format may be used as a backdrop buffer. If a backdrop buffer is installed, its contents are used as the backdrop. If auto update is on, the entire screen is automatically updated using the new backdrop buffer when _set_backdropbuf is called. Setting the backdrop buffer address to -1 using _set_backdropbuf function removes any backdrop buffer which is currently installed. This causes the backdrop character/attribute to specify the appearance of the backdrop.
_update_rect redisplays a specified rectangular region of the screen with the current backdrop and all open windows. _update_screen updates the entire screen. These updates take place whether or not auto update is on. _update_screen forces the cursor to the screen position and state specified by the top open window. _update_rect has no effect on the hardware cursor.
_update_window redisplays a specified window. If the window is open, the window and shadow are completely redisplayed. If the window is closed, the region beneath the window and shadow is redisplayed, effectively erasing the window from the screen if it was previously visible. If the window is positioned completely off the screen, this function has no effect. This update takes place whether or not auto update is on.
_update_cursor forces the hardware cursor to the cursor position and state specified by the top open window. STDWIN is the default top open window if no other window is open.
Fortunately, resizing a window is a straightforward task. The following steps outline how a window may be resized:
For information on how to reassemble the underlying assembly functions to exclude selected portions of the Windowing system, refer to the Windowing technical notes in the Spontaneous Assembly 3.0 manual.
#include "console.h"
#include "window.h"
#include "alloc.h"
#define U_ARRO 72
#define D_ARRO 80
#define R_ARRO 77
#define L_ARRO 75
sawin win = {31,8,18,6,0x47,2,2,1,2,BORDER_SINGLE,
W_INHERIT,2,1,S_NORMAL,SHADOW_TRNSPRNT,
8,W_INHERITPTR,W_INHERIT,W_INHERIT};
void main (void)
{
void *pointer, *screen;
int bufsize, winhandle, flag = 1;
char chr;
_console_init ();
pointer = malloc (WWORKBUF_SIZE);
if (pointer == NULL)
return;
_win_init (pointer);
screen = malloc (_screen_bufsize());
if (screen == NULL)
return;
_save_screen (screen);
_set_backdropbuf (screen);
bufsize = _win_bufsize (&win);
if (bufsize == 0)
return;
pointer = malloc (bufsize);
if (pointer == NULL)
return;
winhandle = _win_create (&win, pointer);
if (winhandle == -1)
return;
_cput_str ("Use arrow keys\r\nto move window");
while (flag)
{
if (_cget_chra (&chr) == -1) /* if it's an extended keystroke */
switch (chr)
{
case U_ARRO: _win_move (winhandle, 0, -1); break;
case D_ARRO: _win_move (winhandle, 0, 1); break;
case R_ARRO: _win_move (winhandle, 1, 0); break;
case L_ARRO: _win_move (winhandle, -1, 0); break;
default: flag = 0;
}
else
flag = 0;
}
_restore_screen (screen);
}
The sample program shown above (WIN.C) is provided on the distribution diskettes and may be compiled and linked using the following Microsoft C and Borland C command lines:
Microsoft C:
cl /c /I\msc\include /I\sa\include win.c
link win,win,,\sa\lib\_sas \msc\lib\slibce
Borland C:
bcc /c /ms /I\bc\include /I\sa\include win.c
tlink \bc\lib\c0s win,win,,\sa\lib\_sas \bc\lib\cs