XView-PC: Graphical User Interface for Turbo C and Turbo Pascal
By:
Antonio Carlos Moreirao de Queiroz
Department of Electronic Engineering and COPPE
Federal University of Rio de Janeiro, Brazil
e-mail: acmq@coe.ufrj.br

INTRODUCTION

  This is the English version of the documentation for the XView-PC GUI. It
is a translation of the documentation in Portuguese contained in the XVIEW
and MICKEY unit headers, in the files XVIEW.INT and MICKEY.INT.
  The XView-PC graphical user interface attempts to be similar to the XView
toolkit used in Sun workstations, in a simplified from, and in Pascal.
There is also a C version, that is a direct translation of the Pascal
version.
  The interface was initially developed as an intermediate step in porting
programs from the PC to Sun workstations, by implementing a subset of the
Sun XView toolkit in the PC. The work was not completed because it soon
become clear that a total translation would be unnecessarily complex. Even
so, the working of the two interfaces was kept similar when reasonable, and
functions and variables with similar function were kept with the same
names.
  What can be done with the interface in its present form can be repeated
with the Sun XView without significant structural changes, although with
differences due to the various simplifications done. The porting of an
application to Windows is also not complex.
  The interface code is of simple use and adds only about 25 k to the
executable program. It works with any PC compatible computer, in any
graphics mode supported by the BGI drivers and installed mouse driver. If a
mouse is not installed, a mouse emulator using the keyboard is
automatically used.
  To simplify the interface code generation, an interface editor program,
X_MAKE.EXE, is included. It allows the edition of a complete user
interface, and the automatic generation of an skeleton program in Pascal or
C, that is a fully functional program that the user can edit and complete.

TYPICAL PROGRAM STRUCTURE

  Below is the structure of a typical program using the interface:

- Program header:
- Declaration of global variables and interface "objects".
- Normal subroutines.
- Subroutines called from the interface objects ("callbacks").
- Main program:
- Normal initialization.
- Interface initialization: call to "xv_init".
- Creation and initialization of the interface objects: calls to
"xv_create" followed by direct initialization of the object parameters.
- Passing of control to the interface "notifier": call to "xv_main_loop".
- Normal termination.

INTERFACE OBJECTS

  The user interface is composed of "objects". Note that the interface was
not programmed with "object-oriented" specific techniques, but some ideas
are used.
  There are eight types of predefined objects, listed below. Their names
are the parameters to be passed to the "xv_create" procedure.

- "frame":     Base windows, where the other objects are.
- "button":    Command buttons.
- "textfield": Input fields for text and numerical values, with edition.
- "setting":   Input fields for logical values (choices).
- "message":   Messages or icons in the windows.
- "canvas":    Graphical output subwindows.
- "tty":       Text output subwindows.
- "menu":      Pop-up menus.

  Other types of objects can be programmed, if necessary, by adding the
desired functionality to "canvas" objects through their "callback"
routines.

EVENT-ORIENTED PROGRAMMING

  The interface is intended to be used in an event-oriented program. The
basic ideas are:

  The program does not follow a predefined fluxogram, but is commanded by
the user, acting on the objects in the windows, what causes calls to the
"callback" routines.
  Any "callback" subroutine can be called at any moment. In its initial
code, it can be necessary for the routine to check the program status to
determine what is to be done. The program status can be maintained in a set
of global logical variables, and/or in the "textfield", "setting", and
"menu" objects.
  A "callback" routine acts based on the program status. For example, it
should not prompt the user for additional input (the interface provides
means for this, if necessary). Text output shall go to "tty" objects (using
"ttysw_output"), and graphical output to "canvas" objects (using the normal
drawing functions). Usually, several "callback" routines also open or close
windows (using "open_window" and "close_window").

  The objects call "callback" routines by three mechanisms, associated with
the objects attributes:

"notify_handler": A "callback" routine, called when:
- "frame": The window is closed.
- "texfield": The return key is pressed, at the end of an edition.
- "canvas": The window is redrawn, on the opening and resizing of the
window.
- Other objects: The left mouse button is pressed over the object.

"event_handler": A "callback" routine, called when the state of the mouse
changes over the object, or when a key is pressed, with the mouse pointer
over the object.

"menu_name": Name of a "menu", opened with the right mouse button pressed
over the object. The menus normally have an associated "notify handler",
called when a selection is done. It is also possible to open a menu
programatically, using the "menu_show" procedure. The items of a menu can
have an associated "item_submenu" (name of another menu),also opened with
the right mouse button. The same is valid for submenus of any order. The
left mouse button always cause the selection of the present item, even if
there are submenus. The central mouse button (or both right and left
buttons simultaneously) cause the dismiss of menus without a call to the
menu "notify_handler".

  The "callback" routines have always the same structure. They are far
procedures receiving a single argument, that is the calling object. Using
this pointer, the parameters of the calling object can be accessed.

EVENTS

  The "event_handler" routines can read the event that caused the call in
the global variable "ie_code". Its meanings are:

- Mouse events: "ie_code" contains:
LOC_MOVE: Movement.
LOC_DRAG: Movement with some button pressed.
MS_LEFT: Left button pressed.
MS_MIDDLE: Central button pressed.
MS_RIGHT: Right button pressed.
  The names above are predefined constants. In the general case for button
events, "ie_code"=1000+10*<buttons before>+<buttons after>.
  The mouse position, relative to the object upper left corner, is in the
global variables "ie_locx" and "ie_locy". The state of the mouse buttons
(as returned by the DOS interrupt 33) is in the global variable
"ie_shiftcode". The absolute mouse position is also available in the
variables "mousex" and "mousey", defined in the MICKEY module.

- Keyboard events: "ie_code" contains the ASCII code of the pressed key. In
the case of keys with extended codes, "ie_code" contains 0, and the second
code can be read with "ReadKey" in Pascal or "getch" in C. If the second
code is not read, a second event is generated with the second code in
"ie_code". With the mouse emulator in operation (see the MOUSE section),
events with extended codes are not generated, unless the ScrollLock key is
active.

  Some events interpreted by the interface are not passed to the
"event_handlers". Only the "canvas" objects receive all the events. In any
way, there is no much sense in detecting events over other objects.

WINDOWS

  There is always an active window, which "frame" pointer is equal to  the
global variable "active_w". The active window is the last opened by the
program, or where a button mouse was pressed most recently.
  To press a mouse key over a window partially covered causes its movement
to the foreground before the processing of the event. The procedures
"open_window", "close_window", "xv_set", "ttysw_output", and "xv_main_loop"
also move their parameter window to the foreground and turn them into the
active window.
  Windows are closed with the procedure "close_window", or by pressing the
central mouse button in an empty area of the window. The "frame" parameter
"adjust_exit" controls if the window can be closed by the central mouse
button. To press simultaneously the right and left mouse buttons has the
same effect.
  Windows are always movable and resizable. Their minimum sizes are
controlled by the "frame" parameters "dxmin" and "dymin". If the window
contains objects with bitmaps or "tty" and "canvas" objects, these values
shall be set to a value high enough to impede the window to be reduced
below the size needed for these objects. The default minimum sizes are
dxmin=99 and dymin=99 (100x100 pixels).
  Objects of type "canvas" and "tty" can change in size to accommodate
changes in their window sizes. This behavior can be controlled by the
parameters "canvas_xext", "canvas_yext", "tty_xext", and "tty_yext", that
control if the objects extend to the window right and bottom edges. As
default, they do it.

GRAPHICAL OUTPUT

  Usually, graphical output is created with the normal Pascal and C
procedures and functions, called from the "callback" routines. When the
"callbacks" are called, the "viewport" is set to the last "canvas" of the
active window, or by the active area of the active window if there is no
"canvas" on it (not recommended). It is possible to change the "viewport"
to draw in other areas, but usually it is not necessary. The present
"viewport" is contained in the parameter "gr_out" of the active window.
When it points to a "canvas" area, there is a 1 pixel margin for the
"canvas" border, so the usable area is from (0,0) to (dx-2,dy-2), where
"dx" and "dy" are the canvas width and height parameters.
  The mouse support is totally transparent. It is not necessary to turn off
the mouse cursor to draw, as the "callbacks" are always called with the
cursor off.
  The simplest way of generating drawings correctly is from the "canvas"
notify and event handlers. The "notify_handler" is called when the window
is opened or resized. The code in it shall be able to reproduce the entire
drawing. The "event_handler" can cause editing functions in a drawing,
provide cursor functions, etc.
  Frequently it is desirable to draw in a "canvas" from other "callbacks".
It is possible if the window containing the "canvas" is first turned into
the active window.
  There is no problem when the owner of the "callback" belongs to the same
window, or to a menu called from a window object. If it is not the case,
the "canvas" window can be activated with a call to "open_window". The
operation can be impossible due to memory limitations, and so after the
call the global boolean variable "xv_ok" shall be tested before any drawing
operation.
  It is frequently useful also to call a "canvas" "notify_handler" from
another "callback" to cause a complete redrawing. The "canvas" window must
be the active window for correct results. Note that a call to "open_window"
when the window is not in the screen causes a call to the "canvas"
"notify_handler". So, if the "canvas" window is not in the screen, the call
to the "notify_handler" after the call to "open_window" is not necessary
(it would cause two redrawings).
  If the canvas window is on the screen (the "frame" attribute "mapped"
contains this information), a safe procedure is to close all the windows
that are above it before drawing. In Pascal the code is:
WHILE not active_w = <desired window "frame"> DO close_window(active_w);
  If a "callback" routine changes the graphical configuration (LineStyle,
TextStyle, etc.) and calls a procedure that draws interface objects, as
"open_window" or "ttysw_output" (not recommended), it must replace the
configuration as it was before the call.
  Only one "canvas" shall be put in each window, or only the last defined
one will be automatically accessible (See the example program CANVAS).

TEXT OUTPUT

  The procedure "ttysw_output" draws text in "tty" objects. The "tty"
window is opened automatically. The procedure can be called from anywhere
in the program. All the written text is stored in a buffer, and can be
reviewed using the "tty" scrollbar.

BITMAP IMAGES

  Objects of types "button" and "message" can display a bitmap image
instead of a text label. If the parameter "icon_label" or "icon_msg" is
set, the parameter "xv_label" is interpreted as the name of a file
containing the image, that is loaded and plotted when the object is drawn.
The supported format is the Windows BMP format, in 16 colors. If the global
variable "use_palette" is set (default), the palette in the VGA screen is
set to the palette in the bitmap. Note that the default Windows palette is
not the same used in Turbo Pascal and C. The gray shade is darker, for
example, so it may be necessary to change some of the default colors of the
interface objects if Windows bitmaps are used. Bitmaps cannot have more
than 640 pixels horizontally, and a "frame" containing bitmap objects must
be big enough to contain the complete images. The bitmap plotting routine
used internally, "drawbitmap", is available for other uses.

MEMORY USAGE

  In the normal usage, the objects are allocated at the beginning of the
program execution, and are kept until the end. Dynamic allocation is also
possible. All the memory used for the interface objects is allocated in the
heap. In Turbo Pascal 7, in protected mode, the heap can use all the
available extended (XMS) memory. The needed .TPP units are included in the
XVIEW.ZIP file.
  Window movement and reordering use additional memory, freed at the end of
the operation. Window operations that need more memory than the available
are refused, and a "beep" sounds. The global variable "xv_ok" turns into
false or 0 when this occur.   Programs shall avoid to put big windows above
other windows, to minimize memory use. Large windows shall be put directly
over the background.

  The objects allocate the amounts of heap memory listed below (Pascal
version):
- "SizeOf(xv_widget)" bytes (262).
- The size of the strings used in the "menu" and "setting" items.
- The size of the buffer used in "tty" objects ("bsize"+1 bytes).
- The bitmap area in a "button" or "message" with a bitmap.
- For a window that is in the screen and covering others, the window area
(contained in the "frame" attribute "areaw").
  Images of window backgrounds and bitmaps are saved in "figstruct" records
or structures.
  Programs that use dynamic allocation of objects shall contain object
"destructors". A "destructor" is a procedure that deallocates the four
first items listed above when the corresponding objects are "destroyed".
The most usual procedure is to use a "destructor" as the "notify_handler"
of a window "frame". The "destructor" is automatically called when the
window is closed, and deallocates all its objects. The window area is
automatically freed when the window is closed. New windows are created
normally with calls to "xv_create". Note that the procedures "xv_create"
and "item_create" allocate memory, and so can fail if there is not enough
heap memory. See the example program XBITMAP for an example of how to use
dynamic allocation.
  Heap memory for the program can be allocated or deallocated at any
moment. The Turbo Pascal  "Mark" and "Release" functions cannot be used.

COLORS AND GRAPHICS MODES

  All the graphics boards and modes supported by the BGI drivers are
accepted. The default colors are used in the EGA and VGA boards. In modes
with two colors, a pattern of black and white dots is used in place of the
gray color in the objects. The colors can be changed changing some global
constants, or changing the palette.

FILES, COMPILATION, AND DIRECTORIES

  For compilation, the files XVIEW.TPU and MICKEY.TPU (or the equivalent
.TPP files for protected mode programs) must be accessible for the
compilation in Turbo Pascal (Version 7.0). The C version uses the files
XVIEW.H, MICKEY.H, and the corresponding .OBJ files.
  For compilation in C, the "large" memory model must be used, and the
option "word align" must be set.
  For execution, the BGI driver and the font LITT.CHR must be in the local
directory, or in a path pointed by the DOS environment variable TPBGI.
Bitmaps used in buttons or messages, or drawn by the "drawbitmap" routine,
must be in the local directory, or in a path pointed by the DOS environment
variable BMP.

LICENSING AND USE OF THE XVIEW-PC INTERFACE

  The use of the interface is free for educational and academic purposes,
not commercial. The compressed file XVIEW.ZIP can be distributed freely,
respected these restrictions, and that it cannot be changed in any way
without the consent of the author.
The code is offered "as is". The author believes that everything is working
correctly, but cannot be responsible for eventual losses caused by
imperfections or bugs in the code. For the clarifying of doubts,
information about detected problems, or information about licensing for
commercial use, the interested shall contact the author:

Dr. Antonio Carlos Moreirao de Queiroz
COPPE/UFRJ - Programa de Engenharia Eletrica
CP 68504
21945-970 Rio de Janeiro, RJ, Brasil
e-mail: acmq@coe.ufrj.br

CONSTANTS AND VARIABLES DEFINED IN THE XVIEW UNIT AND .H INCLUDE FILE

  The variables below marked with "#" are object parameters that usually
are changed immediately after the object creation. All have safe default
values.
  The variables marked with "*" are reserved for internal use, and shall
not be modified in the normal interface operation.
  The others can be changed at any moment.
  The constants, types, and variables are listed in Pascal notation. The C
versions are equivalent. See the actual headers in the .INT and .H files
(with comments in Portuguese) for details.
  The main difference in the C version is the way how the object fields are
accessed. See the examples and the code generated by the X_MAKE program.

CONST
LOC_MOVE=256;    {event: mouse moved}
LOC_DRAG=257;    {event: mouse moved with pressed button(s)}
MS_LEFT=1001;    {event: left mouse button pressed}
MS_MIDDLE=1004;  {event: middle mouse button pressed}
MS_RIGHT=1002;   {event: right mouse button pressed}
m_itens=20;      {maximum number of items in menus and setting (only 16 in
these)}
m_chars=60;      {characters in strings}
mrgx=5;          {lateral and bottom window margins}
mrgy=22;         {upper window margin}

CONST
normal_bsize:WORD=1000;   {"bsize" (tty) attributed by "xv_create"}
normal_length:INTEGER=16; {"value_length" (textfield) attributed by
"xv_create"}
wallpaper:BOOLEAN=FALSE;       {if the screen background is retained}
c_normal:INTEGER=lightgray;    {color of object background}
c_active:INTEGER=green;        {color of pressed buttons}
c_light:INTEGER=white;         {color of lighted corners}
c_shadow:INTEGER=black;        {color of shadowed corners}
c_white:INTEGER=white;         {default "back_color"}
c_black:INTEGER=black;         {default "fore_color"}
c_overwrite:INTEGER=lightred;  {edition color for "textfields"}
c_edit:INTEGER=blue;           {selection color for "textfields"}
c_insert:INTEGER=yellow;       {insertion color for "textfields"}
c_hatch:INTEGER=cyan;          {color of the background pattern}
type_hatch:INTEGER=XHatchFill; {type of the background pattern}
use_palette:BOOLEAN=TRUE;      {if the bitmap palettes are used}
normal_client_data:POINTER=nil;{"client_data" attributed by "xv_create"}
nlines:INTEGER=60;             {* number of lines in each image block}

TYPE
figstruct=RECORD                     {structure for images}
  blocks:INTEGER;                    {number of image blocks-1}
  blocksize,lastblocksize:WORD;      {size of the allocated image blocks}
  v:ARRAY[0..2000] of POINTER;       {only allocated until "blocks"}
END;
ptrfig=^figstruct;                   {image pointer}
Xv_opaque=^xv_widget;                {generic object}
xv_handler=PROCEDURE(pt:Xv_opaque);  {"callback" procedure}
xv_label_type=STRING[m_chars];       {all strings}
tty_buffer=ARRAY[0..65534] OF CHAR;  {"tty" buffer. Only "bsize"+1 bytes
are allocated and used}
xv_package=(frame,button,textfield,setting,message,canvas,tty,menu);
xv_widget=RECORD
  {Parameters used in all the objects}
  xv_label:xv_label_type;         {# title}
  x,y,dx,dy:INTEGER;              {# position and size}
  fore_color,back_color:INTEGER;  {# colors}
  owner:Xv_opaque;                {* owner "frame"}
  next:Xv_opaque;                 {* next object}
  menu_name:Xv_opaque;            {# associated menu}
  notify_handler:xv_handler;      {# associated notify handler}
  event_handler:xv_handler;       {# associated event handler}
  client_data:POINTER;            {# pointer to other parameters}
  {Specific parameters for each object}
  CASE o_type:xv_package OF       {* object type}
    frame:(over,under:Xv_opaque;  {* neighbor windows}
      Pw:ptrfig;                  {* covered image}
      areaw:WORD;                 {* window area size}
      dxmin,dymin:INTEGER;        {# minimum dimensions}
      interfere:BOOLEAN;          {* internal use}
      mapped:BOOLEAN;             {* if it is on the screen}
      adjust_exit:BOOLEAN;        {# if central button can close}
      mouse_obj:Xv_opaque;        {# object pointed by the mouse when the
window is opened. nil if none (default)}
      gr_out:ViewPortType);       {* associated "ViewPort"}
    button:(icon_label:BOOLEAN;   {# if "xv_label" is a file name}
      Pimageb:ptrfig);            {* button bitmap}
    message:(icon_msg:BOOLEAN;    {# if "xv_label" is a file name}
      Pimagem:ptrfig);            {* message bitmap}
    textfield:(panel_value:xv_label_type;  {# text value}
      panel_real:REAL;            {# real value}
      panel_int:INTEGER;          {# integer value}
      min_value,max_value:INTEGER;{# limits for integers}
      value_length:INTEGER;       {# edition length}
      field_type:(text_field,real_field,int_field)); {# type}
    setting:(itens_setting:INTEGER; {# number of itens}
      sel_setting:INTEGER;          {# selection}
      item_setting:array[1..m_itens] OF ^xv_label_type;{* item names}
      exclusive:BOOLEAN);           {# if the selection is exclusive}
    canvas:(can_xext,can_yext:BOOLEAN);  {# if the "canvas" extends to the
window borders}
    tty:(tty_xext,tty_yext:BOOLEAN; {# if the "tty" extends to the window
borders}
      xc,yc:INTEGER;    {* graphical cursors}
      bsize:WORD;       {* buffer size}
      bstart:WORD;      {* buffer start}
      tstart:WORD;      {* shown text start}
      bcsr:WORD;        {* shown text end}
      tend:WORD;        {* text end+1}
      dxtty:INTEGER;    {* panel width}
      Pb:^tty_buffer);  {* buffer pointer}
    menu:(itens_menu:INTEGER; {* number of items}
      sel_menu:INTEGER;       {# selected item}
      item_menu:ARRAY[1..m_itens] OF ^xv_label_type; {* item names}
      item_submenu:ARRAY[1..m_itens] OF Xv_opaque);  {# submenus}
  END;

VAR
  insert:BOOLEAN;          {if text is inserted in "textfields"}
  xv_end:BOOLEAN;          {ends "xv_main_loop"}
  ulttxt:xv_label_type;    {last text entered in "textfields"}
  xv_ok:BOOLEAN;           {* result of the last window operation}
  ie_locx,ie_locy:INTEGER; {* mouse position relative to active object or
window}
  ie_code:INTEGER;         {* event code}
  ie_shiftcode:INTEGER;    {* mouse buttons state}
  active_w:Xv_opaque;      {* the active window "frame"}
  active_o:Xv_opaque;      {* active object}
  w_base:Xv_opaque;        {* base window for "xv_create"}
  o_base:Xv_opaque;        {* base object for"item_create"}
  redrawing_frame:BOOLEAN; {* if a window is being redrawn}

{Public subroutines. Only the first four are of essential use}

PROCEDURE xv_init(board,mode:INTEGER);
{General initialization. Enters the specified graphics mode, initializes
colors and mouse, and sets "active_w" to "nil"}

FUNCTION xv_create(obj_type:xv_package):Xv_opaque;
{Allocates and initializes with default values an object. Returns its
"handle" pointer.
Allocates the buffer "tty_buffer" of "tty" objects, with
"GetMem(Pb,bsize+1)".
Must be called once for each object, beginning by the window "frame".
Does not test possible "heap overflow"}

PROCEDURE item_create(txt:xv_label_type);
{Creates "menu" or "setting" items.
Call once for each item, immediately after "xv_create". The items are
enumerated from 1. In the Pascal version, the texts are allocated with
GetMem(<item>,Length(txt)+1). In the C version, nothing is allocated.
Does not test "heap overflow"}

PROCEDURE xv_main_loop(w:Xv_opaque);
{Opens a window and starts the cycle wait for event - process event.
Ends when all the windows are closed or when "xv_end" is true.
Does not deallocates the objects at exit.
Can be called more than once, if needed. For example, the following code
opens a new window (that must be closed before) over the present ones, and
returns to the calling point when the window is closed:
  temp1:=active_w;   remembers the present windows
  temp2:=wallpaper;  if the background was being retained
  wallpaper:=TRUE;   the background must be retained
  active_w:=nil;     to force the creation of another linked list
  xv_main_loop(<window "frame");
  xv_end:=FALSE;     do not terminate the present loop
  active_w:=temp1;   restores the window list
  wallpaper:=temp2;  restores previous state of background
  The "viewport" is invalid at the end of the operation. A call to
"open_window", for example, restores a valid one}

PROCEDURE open_window(w:Xv_opaque);
{Opens a window, turning it the active one.
The selected window is opened and/or put in the foreground.
Causes calls to "canvas" "notify_handlers" if the window is not in the
screen.
Can be called at any time after "xv_init". Calls before "xv_main_loop" can
be used to start a program with several open windows}

PROCEDURE close_window(w:Xv_opaque);
{Closes a window. Causes a call to the "frame"notify_handler", if
installed. Can also be called at any moment after "xv_init". The window is
moved to the foreground and erased. The window objects are kept allocated}

PROCEDURE ttysw_output(terminal:Xv_opaque; text:STRING);
{Writes a text in a "tty" terminal. The "tty" window is opened and turned
the active window}

PROCEDURE back;
{Circulates back the windows, moving the present active window to the
background. Useful in window menus}

PROCEDURE xv_set(obj:Xv_opaque;new_label:xv_label_type);
{Changes the "xv_label" of an object. The window object is turned the
active window. Mainly used to change "messages". Can be used to update also
other parameters, as "textfield" values, directly set before the call}

PROCEDURE menu_show(obj:Xv_opaque);
{Opens a menu at the mouse location (mousex, mousey). It is better to
associate menus to the objects. This is the routine used internally to open
menus. A typical use is to make a button open a menu, by calling
"menu_show" from the button "notify_handler"}

PROCEDURE draw_object(obj:Xv_opaque; active:BOOLEAN);
{Draws an object. Can be used causing the fast redraw of a window (use the
"frame" as parameter), as a more powerful version of "xv_set". "active"
affects only buttons. For objects that are not "frames", the background is
not erased, and labels are only drawn if the global variable
"redrawing_frame" is true. This routine is used internally. Use not
recommended}

PROCEDURE Nothing(obj:Xv_opaque);
{Default "notify_handler" and "event_handler". No action. Can be used to
inactivate "callbacks" (unusual)}

PROCEDURE wait_button;
{Waits until the mouse buttons are released (unusual).}

FUNCTION Cpct(x:REAL):STRING;
{Returns a more compact form of a real number}

PROCEDURE DrawBitmap(x,y:INTEGER; VAR dw,dh:INTEGER; VAR Pimg:POINTER;
filename:xv_label_type);
{Draws a Windows 16 colors bitmap at (x, y).
If "Pmgi=nil", loads the bitmap from disk (BMP format) and, if possible,
allocates memory and saves it in "Pimg^" as a "figstruct" structure.
Posterior calls cause a faster drawing. The used memory is
"FigureSize(0,0,dw,dh)" bytes.
The dimensions "dw" and "dh" are returned (1 pixel less).
It is used internally to draw "buttons" and "messages" with images.
"Pimg" can be the address of another "figstruct" variable.
Note that, as "PutImage" does not clips at the "viewport" limits, the
window that contains bitmaps must be always of enough size to contain them}

{The routines below are used internally in operations involving images.
They are also available for other uses}

FUNCTION FigureSize(x1,y1,x2,y2:INTEGER):LONGINT;
{Memory needed for an image. Size of the "figstruct" structure}

PROCEDURE GetFigureMem(VAR p:ptrfig; dw,dh:INTEGER);
{Allocates memory for an image. "dw" and "dh" are width-1 and height-1}

PROCEDURE FreeFigureMem(p:ptrfig);
{Frees memory allocated previously with "GetFigureMem"}

PROCEDURE GetFigure(x1,y1,x2,y2:INTEGER; p:ptrfig);
{Captures an image from the screen. "ptrfig" must be allocated with
"GetFigureMem" before the call}

PROCEDURE PutFigure(x,y:INTEGER; p:ptrfig; bitblt:WORD);
{Draws an image captured with "GetFigure" at (x, y) in the screen}

THE MOUSE DRIVER (MICKEY MODULE)

  The Mickey unit or object file implements the mouse functions of the
interface. Normally it is not necessary for a program to use the mouse
functions directly, but they are available.
  If the mouse is not installed, the keyboard emulates it. The cursor moves
the arrow, and the buttons are substituted by:
  left:    Return
  central: Escape
  right:   Space
  The keys Home, PgDn, and PgUp change the cursor step.
  With CapsLock or Shift (in the Pascal version) active, the buttons work
in toggle mode.
  ScrollLock suspends the emulation when active, allowing normal use of the
keyboard. With the emulator active, and the cursor displayed, keys with
extended codes are not recognized.
  The unit can be used alone. For the correct working of the emulator, the
function "mouse_read" must be called regularly.
  Below are listed the available variables and procedures, in Pascal
notation. The C versions are identical.

CONSTANTS AND VARIABLES DEFINED IN THE MICKEY UNIT AND .H INCLUDE FILE

VAR
  mousex,mousey,mouseb,x_factor:INTEGER; {mouse state}
  cursor_active:BOOLEAN;

PROCEDURE mouse_init;              {Initialization}
PROCEDURE cursor_on;               {Cursor on}
PROCEDURE cursor_off;              {Cursor off}
PROCEDURE mouse_read;              {Reads current state}
PROCEDURE mouse_move(x,y:INTEGER); {Moves cursor}
FUNCTION KeyPressed:BOOLEAN;       {KeyPressed substitute}
