'\"!  tbl | mmdoc
.if n .pH ref.class @(#)class	40.2

.ig
imagen 8/31/89
docformat -c -s4 -dqm4 -p1 class
..
.SO mstr.hdr
.SO BP.HEADER
.ds Lb Shapes
.\" turn off automatic hyphenation -- JHevelin (08-09-89)
.am RT
.nh
..
.\" BEGIN SHAPES------------------------------------------------
.if !"\*(Lb"Paint" \{\
.br
.BK "Shapes Reference Manual"
.CH "Classes" "2"
.H 1 "Classes"
.H 2 "Introduction"
.IX "classes"
.P
.nh
As an object-oriented graphic interface,
all operations manipulate objects that contain both data
(attributes) and a set of operators for controlling
and manipulating the attributes.
You can extend the capabilities of Shapes by creating
new classes to accommodate new devices or by adding
attributes or operators to existing classes.
.P
A collection of objects with the same attributes and
operators is known as a \f2class\fP.
An \f2object\fP is simply one member of a class.
For example, all rasters have the same attributes,
such as RAS_ORG and RAS_DIM,
and also the same operators,
like Display_Raster and Copy_Raster.
At the same time,
each individual raster is an object that belongs to the RASTER class.
.P
The implementation of a class is not exposed:\ \&
you manipulate an object by passing its handle to
its associated operators.
Querying or updating of attributes is done via the Get
and Set operators.
The internal representation of the object is never directly revealed.
.P
Classes can be of different types,
depending on the hardware implementation,
memory raster, or screen raster.
For example, a context associated with a memory raster
renders a path in a way different from a context associated
with a graphics processor-based raster.
.H 2 "Inheritance"
.P
A class may be derived from an existing class.
The parent class is known as the \f2superclass\fP,
and the derived class, the \f2subclass\fP,
inherits the operators and attributes from the superclass.
You can override the inheritance of individual operators or attributes,
and you can create new operators and attributes for the subclass.
.P
The subclass may override the existing operators of
its superclass or define additional ones to implement
new features.
In the following figure,
CLASS B is a subclass of CLASS A.
The operators Destroy, Set, and Get are common to both classes,
and an additional operator (Print) has been created for the subclass.
.\" begin new page
.SK
.FG "Class Inheritance"
.DS
.BP PSART/ps.class 3.75i 0
.EP
.DE
The maximum number of superclasses is 255.
.H 2 "Structure"
.P
The class data structure describes how one is to determine
the functionality for a particular object (OBJ).
Each class determines its functional potential
along a two-dimensional grid,
where each element on the grid is a pointer to a dispatch vector table.
.\" begin new page
.FG "Class Grid"
.DS
.BP PSART/ps.cls_grid 2.25i 0 "".5 .5 0
.EP
.DE
See the bottom of the file di/raster.c for an example
of a dispatch table.
.P
The particular functional implementation of an object
is determined by the interaction of the CLASS_ID, CLASS_TYPE,
and the class from which the new class is inheriting functionality.
.P
\f3CLASS_ID\fP
.P
\f1This dimension of the grid described above allows you
to specify conceptual objects.
The file include/sh_main.h contains the following list
of the initial Shapes object classes that the CLASS_ID represents.
.PC
#define       CLASS_SCR       1
#define       CLASS_RAS       2
#define       CLASS_CMAP      3
#define       CLASS_CURS      4
#define       CLASS_TRANS     5
#define       CLASS_CTX       6
#define       CLASS_RTM       7
#define       CLASS_PATH      8


#define       CLASS_PAT       10
#define       CLASS_SHAPE     11
#define       CLASS_CTM       12
#define       CLASS_SRAS      13
#define       CLASS_FPATH     14

#define       CLASS_ET        16
#define       CLASS_LAST      16
.ft1
.SF
.P
\f3CLASS_TYPE\fP
.P
\f1This dimension represents the varying devices for which
any object might be implemented.
Many objects only apply to the generic device.
Others, like color maps and rasters,
may have an implementation for each device.
.TB "Devices"
.TS
box tab (;);
cf2 | cf2
l | l .
Device;Description
=
SCR_DEV_GENERIC;Generic class implementations
SCR_DEV_MEM1;Depth 1 memory framebuffer
SCR_DEV_MEM4;Depth 4 memory frame buffer
SCR_DEV_MEM8;Depth 8 memory framebuffer
SCR_DEV_MEM32;Depth 32 memory framebuffer
SCR_DEV_CG2;Sun CG2 framebuffer (depth 8)
SCR_DEV_BW2;Sun BW2 framebuffer (depth 1)
SCR_DEV_CG4;Sun CG4 framebuffer (1 or 8)
SCR_DEV_TEC;Sun CG6 (Lego) with TEC
SCR_DEV_CG6;Sun CG6 (Lego) framebuffer
SCR_DEV_GPFB;GP1/GP+/GP2 framebuffer (depth 8)
SCR_DEV_VGA;VGA display controller (depth 4 or 1)
SCR_DEV_LAST;Last built-in device code
.TE
.TT
.P
\f1The structure of a class is as follows:
.PC
 * Class descriptor
 */
typedef struct
  {
   CLASS_TYPE   type   /* type of class (implementation) */
   CLASS_ID     id;    /* class identifier */
  } CLASS;

.ft1
.SF
.H 2 "Accessing Superclass Capabilities"
.P
The most powerful feature of object extension mechanism
is inheritance.
Classes may be based upon other classes and can inherit
their operators and attributes.
.P
A function that implements a class operator may invoke
the operators of its superclass.
This allows the object to build upon existing capabilities
as well as replace functionality.
.H 2 "Adding Attributes"
.P
The following discussion may illuminate the subject
for you and is not intended for actual use.
.P
Most objects have a set of attributes that are accessed
by the Get and Set operators for the object.
The attributes are in sequence,
and each object has an identifier that designates
the largest attribute number.
Larger numbers can be used for user attributes without conflict.
The table below gives the name of the operator identifier
for the last attribute of each class.
They are defined at compile time so that a switch statement
may be used to quickly select individual attributes.
.P
Adding an attribute usually involves enlarging the
size of the object to accommodate the value of the new attribute.
The existing classes have public structure definitions,
struct class_XXX, that define public and private attributes
of the class.
These definitions can be used to define classes that
are based on existing classes
(they contain the same attributes and respond to the
same operators).
.AB N
Although the internal representations of all
classes are available in the Shapes header files,
these should be considered subject to change without notice.
Objects should only be accessed via their operators,
even inside object extensions.
.AC
.br
.TB "Attribute Values and Structures"
.TS
box tab($);
cf4I | cf4I | cf4I
l | l | l.
Class$Largest Attribute$C structure
=
CONTEXT$CTX_ATTRS$struct class_CTX
_
RASTER$RAS_ATTRS$struct class_RAS
_
TRANSFORM$TRANS_ATTRS$struct class_TRANS
_
PATH$PATH_ATTRS$struct class_PATH
_
CMAP$CMAP_ATTRS$struct class_CMAP
_
PATTERN$PAT_ATTRS$struct class_PAT
_
CURSOR$CURS_ATTRS$struct class_CURS
.TE
.TT
.H 4 "NAME"
.P
Call_Class \- Invokes the function that implements a particular
operator ID for the specified class.
.IX "Call_Class"
.tm .CE U 3 "Call_Class" \n(PN
.H 4 "SYNOPSIS"
.P
\f3Call_Class\f2(classtype, classid, n)\f1
.br
CLASS_TYPE classtype;
.br
CLASS_ID classid;
.br
int n;
.H 4 "DESCRIPTION"
.P
Invokes the \f2nth\f1 operator from the specified class type.
You can use Call_Class to call any operator from any
class from any function,
but you should use it only to invoke operators from
the superclass.
.P
Call_Class differs from Call_Obj in that Call_Class
requires you to specify both the type and ID of the class.
Therefore, the exact operator implementation is known
at compile time.
Since Class_Obj gets the class type from the object,
the exact operator implementation is not known until run time.
.P
\f2classtype\f1
Represents the varying devices for which any class might
be implemented.
Many classes only apply to the generic device.
Others, like color maps and rasters,
may have an implementation for each device.
.TB "Device Types"
.TS
box tab (;);
cf2 | cf2
l | l .
Device;Description
=
SCR_DEV_GENERIC;Generic class implementations
SCR_DEV_MEM1;Depth 1 memory framebuffer
SCR_DEV_MEM4;Depth 4 memory framebuffer
SCR_DEV_MEM8;Depth 8 memory framebuffer
SCR_DEV_MEM32;Depth 32 memory framebuffer
SCR_DEV_CG2;Sun CG2 framebuffer (depth 8)
SCR_DEV_BW2;Sun BW2 framebuffer (depth 1)
SCR_DEV_CG4;Sun CG4 framebuffer (1 or 8)
SCR_DEV_TEC;Sun CG6 (LEGO) with TEC
SCR_DEV_CG6;Sun CG6 (LEGO) framebuffer
SCR_DEV_GPFB;GP1/GP+/GP2 framebuffer (depth 8)
SCR_DEV_VGA;VGA display controller (depth 4 or 1)
SCR_DEV_LAST;Last built-in device code
.TE
.TT
A class type may have its own device-dependent implementation
for each of the built-in classes.
Typically, only a few classes are actually device-dependent.
.P
\f2classid\f1
The ID of object class to be called:
.br
CLASS_SCR	CLASS_PATH
.br
CLASS_RAS	CLASS_PAT
.br
CLASS_CMAP	CLASS_SHAPE
.br
CLASS_CURS	CLASS_SRAS
.br
CLASS_TRANS	CLASS_FPATH
.br
CLASS_CTX	CLASS_ET
.P
\f2n\f1
The number of the operator (from the table below).
.br
.TB "Class Operator Sequences"
.TS
box tab($);
cf4I | cf4I | cf4I | cf4I | cf4I | cf4I
lp-3 | lp-3 | lp-3 | lp-3 | lp-3 | lp-3 .
TRANSFORM$PATH$RASTER$CONTEXT$CMAP$CURSOR
=
TRANS_OP_Destroy$PATH_OP_Destroy$RAS_OP_Destroy$CTX_OP_Destroy$CMAP_OP_Destroy$CURS_OP_Destroy
TRANS_OP_Init$PATH_OP_Init$RAS_OP_Init$CTX_OP_Init$CMAP_OP_Init$CURS_OP_Init
TRANS_OP_Get$PATH_OP_Get$RAS_OP_Get$CTX_OP_Get$CMAP_OP_Get$CURS_OP_Get
TRANS_OP_Set$PATH_OP_Set$RAS_OP_Set$CTX_OP_Set-I$CMAP_OP_Set$CURS_OP_Set
TRANS_OP_Print$PATH_OP_Print$RAS_OP_Print$CTX_OP_Set-F$CMAP_OP_Print$CURS_OP_Install
TRANS_OP_Scale$PATH_OP_Clear$RAS_OP_Read$CTX_OP_Print$CMAP_OP_Install$CURS_OP_Remove
TRANS_OP_Translate$PATH_OP_Transform$RAS_OP_Write$CTX_OP_Copy$CMAP_OP_Remove$CURS_OP_Display
TRANS_OP_Rotate$PATH_OP_Union$RAS_OP_Display$CTX_OP_Extend$CMAP_OP_Read$CURS_OPERS
TRANS_OP_Identity$PATH_OP_Intersect$RAS_OP_Store$CTX_OP_Winview$CMAP_OP_Write
TRANS_OP_Copy$PATH_OP_Differ$RAS_OP_Attach$CTX_OPERS$CMAP_OPERS
TRANS_OP_Mul$PATH_OP_Area$RAS_OP_Path
TRANS_OP_Point$PATH_OP_Read$RAS_OP_Color
TRANS_OP_Invert$PATH_OP_Copy$RAS_OP_Clear
TRANS_OP_Transpose$PATH_OP_Overlap$RAS_OP_Dispatch
TRANS_OP_Read$PATH_OP_PointIn$RAS_OP_Glyph
TRANS_OP_Write$PATH_OP_Translate$RAS_OP_Image
TRANS_OP_Path$PATH_OP_Inside$RAS_OPERS
TRANS_OP_InversePoint$PATH_OP_Attach
TRANS_OP_Select$PATH_OP_Extend
TRANS_OP_DeSelect$PATH_OP_Update
TRANS_OPERS$PATH_OP_ReadFile
$PATH_OP_WriteFile
$PATH_OP_Pen
$PATH_OP_RasterPen
$PATH_OPERS
.TE
.TT
.H 4 "RETURNED VALUE"
.P
Return value of the invoked class operator.
.H 4 "SEE ALSO"
.P
Call_Obj
.br
CLASS_OPERS
.br
NewType_Class
.br
GetOper_Obj
.br

.H 4 "NAME"
.P
Call_Obj \- Calls the specified operator from another class.
.IX "Call_Obj"
.tm .CE U 3 "Call_Obj" \n(PN
.H 4 "SYNOPSIS"
.P
\f3Call_Obj\f2(obj, id, n)\f1
.br
OBJID obj;
.br
CLASS_ID id;
.br
int n;
.H 4 "DESCRIPTION"
.P
Invokes the \f2nth\f1 operator on the specified class ID,
using the class type of the specified object.
This operator provides a limited run-time inheritance.
The specified implementation of the operator is derived
from the class type of the object.
Changing the class type changes the implementation.
.P
Call_Obj should be used whenever possible.
Call_Class should only be necessary within the initialization
code or to call the same operator from within a subclass.
.P
Call_Class differs from Call_Obj in that Call_Class
requires you to specify both the type and ID of the class.
Therefore, the exact operator implementation is known
at compile time.
Since Class_Obj gets the class type from the object,
the exact operator implementation is not known until run time.
.P
\f2obj\f1
Specifies the object.
.P
\f2id\f1
The ID of the object class to call.
(See \f2classid\fP for Call_Class.)
.P
\f2n\f1
The number of the operator to be returned.
(See the table in Call_Class.)
.H 4 "RETURNED VALUE"
.P
Value of the called class operator
.H 4 "SEE ALSO"
.P
Call_Class
.br
NewType_Class
.br
CLASS_OPERS
.br
GetOper_Obj


.H 4 "NAME"
.P
Create_Class \- Creates a new class.
.IX "Create_Class"
.tm .CE U 3 "Create_Class" \n(PN
.H 4 "SYNOPSIS"
.P
\f3Create_Class\f2(super, numops, size, func)\f1
.br
CLASS super;
.br
int numops;
.br
int size;
.br
CLASS_OPER func[];
.H 4 "DESCRIPTION"
.P
Creates a new class and returns the classid identifier.
This identifier can be used in conjunction with Create_Obj
to define objects within the new class.
The new class will not collide with other classes.
.P
Create_Class creates a new class for every type that currently
exists.
The implementation of the new class may be derived
from the generic class or from other types.
.P
\f2super\f1
The class on which the new class will be based.
The operators and attributes of the superclass are inherited
by the new class.
The super argument consists of two parts:\ \&
the \f2super.id\fP,
and the \f2super.type\fP.
.P
If \f2super.id\fP is set to NULL,
the next available CLASS_ID number will be used.
If you choose to specify an ID number,
it must be larger than the number of CLASS_LAST and
smaller than the number of CLASS_MAX.
Although you may choose either of the super types listed here,
CLASS_VARIABLE is the most common choice.
.TB "Super Types"
.TS
box tab(/);
cf4I | cf4I
l | l.
Type/Description
=
CLASS_VARIABLE/T{
Creates a device-dependent class using the operators
and attributes from the designated superclass.
It is determined at runtime.
Each class type may have a different implementation.
T}
_
CLASS_GENERIC/T{
Creates a non-device-dependent class using the operators
and attributes from the designated superclass.
It is known at compile time.
All class types have the same implementation.
T}
.TE
.TT
.P
\f2numops\f1
The number of operators for the class.
This argument determines the number of functions in
the operator set.
.P
\f2size\f1
The byte size of the data area for all objects in this class,
including the storage requirements of the superclass
on which the new class is based.
.P
\f2func\f1
A table of pointers to functions that implement each
of the operators in the class.
Entries into this table take precedence over the superclass
operators.
A NULL entry implements the operators from the superclass.
The function table must begin with a \f2destroy\fP
operator and \f2init\fP must be the second operator.
.H 4 "RETURNED VALUE"
.P
CLASS_ID
.br
NULL indicates the new class could not be created.
.H 4 "SEE ALSO"
.P
New_Obj

.H 4 "NAME"
.P
Get_Class \- Returns the setting of the specified attribute.
.IX "Get_Class"
.tm .CE U 3 "Get_Class" \n(PN
.H 4 "SYNOPSIS"
.P
\f3Get_Class\f2(class, attr)\f1
.br
CLASS class;
.br
CLASS_attr attr;
.H 4 "DESCRIPTION"
.P
Returns the setting of a class attribute.
.P
\f2class\f1
Specifies the class for which the attribute setting is returned.
.P
\f2attr\f1
Specifies the attribute to be returned.
.H 4 "RETURNED VALUE"
.P
Attribute Setting
.H 4 "SEE ALSO"
.P

.H 4 "NAME"
.P
NewType_Class \- Defines a new device type for existing
class.
.IX "NewType_Class"
.tm .CE U 3 "NewType_Class" \n(PN
.H 4 "SYNOPSIS"
.P
\f3NewType_Class\f2(newtype, supertype, defn, n)\f1
.br
CLASS_TYPE newtype;
.br
CLASS_TYPE supertype;
.br
int * defn
.br
int n;
.br
.H 4 "DESCRIPTION"
.P
Defines a new type for all classes based on existing
class implementations.
New types accommodate slightly different
behavior for a class that has the same
basic functionality as the supertype.
For example, you could create new types of raster classes
to provide different implementations for framebuffers
and graphics accelerators.
.P
\f2newtype\f1
Specifies the new type to be created,
as defined in sh_scr_dev.h.
.P
\f2supertype\f1
Specifies the existing type on which the new type will
be based.
The operators and attributes of classes of the new type
may be inherited from the supertype.
.P
\f2defn\f1
Defines the operators to be changed and provides a pointer
to the location of the definition.
This array contains the number of
elements specified by \f2n\fP.
.P
The following is the format of CLASS_DEF structure:
.PC
   struct
     {
      CLASS_ID   super;	  /* class ID of superclass */
      CLASS_OPER *opers;  /* operator table */
     } CLASS_DEF;
.ft1
.SF
.P
The \f2defn\fP argument is a table of CLASS_DEF structures.
The entries must be in order of classid's
(see table under Call_Class for order).
The first entry should always have super == 0 and opers == NULL;
this is the class for generic data objects and must
not be overridden.
.P
Each entry in \f2defn\fP describes how a particular
class is implemented for this class type.
The argument need not be as large as the maximum number of classids;
it need only contain entries for those classes you wish to override.
There can't be any ``holes'', however.
If you want to override the RASTER object implementation,
but not the SCREEN object,
you must still supply an entry for SCREEN because its
class id precedes that for RASTER.
.P
\f3Interpretation of CLASS_DEF entries\fP
.P
The \f2super\fP field gives the class ID of the super class
(class from which this class inherits its implementation).
The \f2opers\fP field is a table of pointers to functions
that implement individual operators for the new class.
These entries must be in the order of the operators for the class
(see table under Call_Class for operator order of built-in
Shapes classes).
NULL entries in this table will inherit the implementation
of that operator from the superclass.
Non-NULL entries will use the function referenced as
an implementation of the operator.
.P
The inheritance of a specified class
(type and ID) depends on both \f2super\f1 and \f2opers\fP
of the current \f2defn\fP entry as well as the \f2supertype\f1
as follows:
.TB "Inheritance"
.TS
box tab(/);
cf4I | cf4I | cf4I
l | l | l.
Super/Opers/Inheritance
=
0/NULL/Use same implementation as corresponding
ID/NULL/Class in the supertype
0/OPS/Inherit from corresponding class in supertype
ID/OPS/Inherit from class ID in new type (not supertype)
.TE
.TT
.P
Each \f2defn\f1 entry will cause a new class to be created
(doing the equivalent of Create_Class for this type).
If there are fewer \f2defn\fP entries than there are
class IDs defined in the system
(and this includes classes the user has made with Create_Class
as well as built-in Shapes classes),
new versions of these classes are also created
for the new class type.
.P
If the class was originally created as CLASS_GENERIC
(\f2super\f1 argument to Create_Class),
the class will be implemented the same across all class types.
If the class was created as CLASS_VARIABLE,
the new implementation it will inherit from the supertype.
The same rules as above apply:\ \&
if the class was created as a subclass,
it inherits from the superclass of the new type;
otherwise, it inherits from the corresponding class
in the supertype.
.P
Shapes attempts to share class definitions whenever possible.
If two classes share the same implementation,
they will also share the same class descriptor.
You are encourage to create classes as CLASS_GENERIC
whenever possible (if they are not device-dependent).
It is also good to use ``defn'' entries of {0,
NULL} whenever possible,
as these will share the class descriptor in the
supertype.
.P
\f2n\f1
The number of classes to be redefined.
If \f2n\fP is less than the number of existing classes,
the remaining classes inherit from the supertype.
.H 4 "EXAMPLE"
.SS
	CLASS_DEF sh_class_cg2[CLASS_LAST] = {
	{ 0, vgr },
	{ 0, vgr },			/* SCREEN */
	{ CLASS_SRAS, ops_ras_cg2 },	/* RASTER */
	{ 0, ops_cmap_cg2 },		/* CMAP */

	NewType_Class(SCR_DEV_CG2, SCR_DEV_MEM8, sh_class_cg2, 4)
.ft1
.SE
.H 4 "RETURNED VALUE"
.P
CLASS_ID
.H 4 "SEE ALSO"

.H 4 "NAME"
.P
Set_Class \- Sets the specified attribute of the class.
.IX "Set_Class"
.tm .CE U 3 "Set_Class" \n(PN
.H 4 "SYNOPSIS"
.P
\f3Set_Class\f2(class, attr, setting)\f1
.br
CLASS class;
.br
CLASS_attr attr;
.br
<attribute type> setting;
.H 4 "DESCRIPTION"
.P
Returns the setting of a class attribute.
.P
\f2class\f1
Specifies the class of the attribute to be set.
.P
\f2attr\f1
Specifies the attribute to be set.
.P
\f2setting\f1
Specifies the setting for the attribute.
.H 4 "RETURNED VALUE"
.P
[None]
.H 4 "SEE ALSO"
.P

.H 2 "Class Attributes"
.H 4 "NAME"
.P
CLASS_OPERS
.IX "CLASS_OPERS"
.tm .CE U 3 "CLASS_OPERS" \n(PN
.H 4 "DESCRIPTION"
.P
Pointer to class operator function dispatch table.
The class operator defines are offsets into the dispatch
table that locate the operator function table.
.P
You can only get the attribute.
To set it, use Create_Class and NewType_Class.
.P
CLASS_OPERS is established when the class is created
by either Create_Class or NewType_Class.
CLASS_OPERS never changes;
it cannot be updated.
When the class is created,
the NULL entries in the class function table inherit
the implementations from the superclass.
Non-NULL entries are not changed.
The resulting function table is CLASS_OPERS.
.P
If the class is not a subclass,
CLASS_OPERS references the initial table passed to Create_Class.
If a class implementation is the same across one or more class types,
CLASS_OPERS way reference the same dispatch tables for these classes.
.H 4 "RETURNED VALUE"
.P
CLASS_OPER *
.H 4 "SEE ALSO"
.P
.br
Create_Class
.br
NewType_Class
.br
GETOper_Obj


.H 4 "NAME"
.P
CLASS_NUMOPERS
.IX "CLASS_NUMOPERS"
.tm .CE U 3 "CLASS_NUMOPERS" \n(PN
.H 4 "DESCRIPTION"
.P
Number of operators in this class.
All classes with the same ID have the same CLASS_NUMOPS,
even if they are of different class types.
.H 4 "RETURNED VALUE"
.P
Integer
.H 4 "SEE ALSO"

.H 4 "NAME"
.P
CLASS_SIZE
.IX "CLASS_SIZE"
.tm .CE U 3 "CLASS_SIZE" \n(PN
.H 4 "DESCRIPTION"
.P
Defines the default byte size of the data area of an
object of the class when it is created by New_Obj.
.H 4 "RETURNED VALUE"
.P
Integer
.H 4 "SEE ALSO"
.P
New_Obj
.br
OBJ_SIZE

.H 4 "NAME"
.P
CLASS_SUPER
.IX "CLASS_SUPER"
.tm .CE U 3 "CLASS_SUPER" \n(PN
.H 4 "DESCRIPTION"
.P
Superclass of a class.
Specifies the type and ID of the superclass.
When a class inherits from another class type,
the class type of the CLASS_SUPER is the class type that is inherited.
The ID of the CLASS_SUPER is typically the same for all class types.
.H 4 "RETURNED VALUE"
.P
CLASS_ID
.H 4 "SEE ALSO"

.br \}
.\"  ENDIF SHAPES------------------------------------------------
