.\"##
.\" $XConsortium: api.pg,v 5.7 94/04/17 20:05:46 hersh Exp $
.\"##
.\"## 
$XMCOPY
.\"## Copyright (c) 1990, 1991 by Sun Microsystems, Inc. 
.\"## 
.\"##                         All Rights Reserved
.\"## 
.\"## Permission to use, copy, modify, and distribute this software and its 
.\"## documentation for any purpose and without fee is hereby granted, 
.\"## provided that the above copyright notice appear in all copies and that
.\"## both that copyright notice and this permission notice appear in 
.\"## supporting documentation, and that the name of Sun Microsystems,
.\"## not be used in advertising or publicity 
.\"## pertaining to distribution of the software without specific, written 
.\"## prior permission.  
.\"## 
.\"## SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
.\"## INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
.\"## EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
.\"## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
.\"## USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
.\"## OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\"## PERFORMANCE OF THIS SOFTWARE.
.H C "Porting the PEX-API"
.H 2 "General Porting Concerns"
.BP
The routine \fIsocketpair()\fR , used in \fL\s-1mit/extensions/lib/PEX/cp/cp_ccom.c\fR\s+1
is not available on all System V systems.
.BP
A combination of \fIsocket()\fR, \fIbind()\fR, \fIlisten()\fR, \fIconnext()\fR,
and \fIaccept()\fR may be used to provide the equivalent of \fIsocketpair()\fR.
.LP
.H 2 "Customizing"
.H 3 "Using UNIX Sockets or Shared Memory"
.LP
The compiler symbol \s-1PEX_API_SOCKET_IPC\s+1 controls how the client process
communicates with the \s-1PM\s+1.  If the symbol is defined when the \s-1API\s+1
is built, \s-1UNIX\s+1 sockets are used.  If the symbol is not defined,
System V shared memory is used.  The symbol can be defined in
the \fI.cf\fR file (for example, \fL\s-1sun.cf\s+1\fR) found in the
\s-1X\s+1 source tree \fL\s-1config\fR\s+1 directory.
.H 3 "Changing Implementation-Dependent Parameters" 
.LP
.IX "PEXGetEnumeratedTypeInfo" "" "\s-1PEXGetEnumeratedTypeInfo\s+1"
.IX "PEXGetImpDepConstants" "" "\s-1ImpDepConstants\s+1"
Most of the implementation-dependent parameters depend on the capabilities
of the server.  The \s-1PEX\s+1 inquiries \s-1PEXGetEnumeratedTypeInfo\s+1 and
\s-1PEXGetImpDepConstants\s+1 are used to ``get'' these capabilities.
The Workstation Description Table (\s-1WDT\s+1) manual page describes how each of
the implementation-dependent parameters are determined.
.H 3 "Workstation Capabilities"
.LP
Workstation \s-1DC\s+1 limits correspond to the window size of the
window used by the \s-1PHIGS\s+1 workstation.
The units are drawable coordinates.
When the \s-1API\s+1 responds to a window resize event, more or less of the window 
will be exposed; the \s-1PHIGS\s+1 output will not be scaled.
.LP
The application accesses the \s-1API\s0-defined \s-1WDT\s+1
information using the functions \fIphigs_ws_type_set()\fR and
\fIphigs_ws_type_get()\fR.
New workstation types can be created with the function
\fIphigs_ws_type_create()\fR and destroyed with the function
\fIphigs_ws_type_destroy()\fR.
See the \fIPEX-SI Graphics Library Manual Pages\fR for a full description of these functions.
.KS
.H 4 "Opening Workstations"
.IX "Workstations" "opening"
.IX "Workstation Functions" "popen_ws"
.IX "Functions" "popen_ws"
.LP
Workstations are opened with the following function:
.ta 0.5i 1.5i 3.0i
.nf
(void)popen_ws(ws_id, conn_id, ws_type)
	Pint	ws_id;	/*workstation identifier */
	char	*conn_id;	/* connection identifier */
	Pint	ws_type;	/* workstation type */
.fi
.KE
.LP
\fIws_id\fR is the application-chosen identifier of the workstation.
\fIws_type\fR is the workstation type to open.
For tool workstation types, \fIconn_id\fR is either \s-1NULL\s+1
or contains the name of the display to open the workstation on.
For drawable workstation types,
\fIconn_id\fR is a pointer to a structure containing the display pointer and
drawable identifier of the drawable to use for the \s-1PHIGS\s+1 workstation.
.LP
.IX "Workstations" "generic, API"
.IX "generic workstations, API"
The \s-1API\s+1 provides two generic workstation types:\ \ 
\fIphigs_ws_type_x_tool\fR and \fIphigs_ws_type_x_drawable\fR.
The \s-1PHIGS\s+1 function, \s-1OPEN WORKSTATION\s+1 will create a new 
\s-1X\s+1 window for the \fItool\fP type.  Use of the \fIdrawable\fP type 
requires that the application also pass a drawable identifier as part of the 
connection id parameter to the \s-1PHIGS\s+1 function \s-1OPEN WORKSTATION\s+1.
This drawable is used as the output drawable of the \s-1PHIGS\s+1 workstation.
.LP
.IX "PEXGetEnumeratedTypeInfo" "" "\s-1PEXGetEnumeratedTypeInfo\s+1"
.IX "PEXGetImpDepConstants" "" "\s-1PEXGetImpDepConstants\s+1"
.IX "PEXGetTableInfo" "" "\s-1PEXGetTableInfo\s+1"
The \s-1API\s+1 uses the \s-1PEX\s+1 inquiries \s-1PEXGetEnumeratedTypeInfo\s+1, 
\s-1PEXGetImpDepConstants\s+1, \s-1PEXGetTableInfo\s+1, etc., to determine
\s-1PEX\s+1 capabilities, using the root window of the display as the 
drawable id parameter to these requests.
.H 4 "Workstation Type Creation and Modification"
.IX "Workstations" "creation"
.IX "Workstations" "modification"
.LP
New generic workstation types can be created with \fIphigs_ws_type_create()\fR
and existing ones can be modified with \fIphigs_ws_type_set()\fR.
.H 4 "Modifying a WDT to Correspond to a Particular Display"
.LP
Two \s-1WDT\s+1 attributes are defined to assist in building 
workstation types for specific displays:\ \  
\s-1PHIGS_X_DISPLAY\s+1 and \s-1PHIGS_X_DISPLAY_NAME\s+1.
These attributes can be specified in the \fIattributes\fR parameter of the
functions \fIphigs_ws_type_create()\fR and \fIphigs_ws_type_set()\fR, and will
cause all the fields in the augmented \s-1WDT\s+1 to be modified to correspond 
to the capabilities of the specified display (specified either by a display
pointer or display name), assuming that display can be opened and contains a
\s-1PEX\s+1 extension.  The display name will be stored in the \s-1WDT\s+1.
.RE
.H 2 "Areas for Optimization"
.LP
If you are interested in optimizing \s-1PEX-API\s+1, you should consider
the following areas.
.H 3 "Structure Storage"
.LP
In \s-1PHIGS\s+1 the Central Structure Store (\s-1CSS\s+1) appears to the application as
one database located somewhere within the \s-1PHIGS\s+1 implementation.  The \s-1CSS\s+1
is independent of any \s-1PHIGS\s+1 workstations so it exists regardless of whether or
not any \s-1PHIGS\s+1 workstations are open.  When a \s-1PHIGS\s+1 structure is created
there is no indication of which, if any, workstations will eventually
display the structure.  The application can create many structures that
all appear on many different workstations,
each of which may exist on a different display,
or it can be selective and have
each structure appear on only one workstation or just a few workstations.
.LP
The \s-1API\s+1 keeps one full copy of the \s-1CSS\s+1 on some server and keeps full
copies on all servers with open workstations.
All \s-1CSS\s+1 operations requested by the application are
broadcast to all servers holding a copy of the \s-1CSS\s+1.
One of those servers
is designated the main \s-1CSS\s+1 server and it holds the \s-1CSS\s+1 even when there
are no workstations open on that server.
.LP
The \s-1API\s+1 selects the main \s-1CSS\s+1 server when \s-1OPEN PHIGS\s+1 is called.
The application can specify the server that will hold the
\s-1CSS\s+1 for the duration of the \s-1PHIGS\s+1 session if it opens \s-1PHIGS\s+1 with the
\s-1OPEN XPHIGS\s+1 function.
The default is the server indicated by the \s-1DISPLAY\s+1 environment variable.
The \s-1CSS\s+1 is copied to other servers when workstations are first opened on
them, and each copy is destroyed when the last workstation on the server
is closed.
.H 3 "Dealing with Partial PEX Support"
.LP
\s-1PEX\s+1 defines three levels of support that a server can provide:\ \  the
Immediate Rendering Only Subset, the \s-1PHIGS\s+1 Workstation Only subset and
Full \s-1PEX\s+1, which provides both the subsets.
Both subsets provide the needed support for a \s-1PHIGS\s+1 client.
.LP
The \s-1API\s+1 is capable of utilizing either of these subsets, automatically
and without any direction from the user.
When it connects to a server, either during \s-1OPEN PHIGS\s+1,
\s-1OPEN XPHIGS\s+1 or \s-1OPEN WORKSTATION\s+1, the \s-1API\s+1 inquires
what level of \s-1PEX\s+1 is supported.
If Full \s-1PEX\s+1 or the Workstation Only subset is supported the \s-1API\s+1 will use
\s-1PHIGS\s+1 workstation resources and server structure storage on that server.
If only the Immediate Rendering subset is supported
the \s-1API\s+1 will use its own
implementation of \s-1PHIGS\s+1 workstations and will maintain a copy of the \s-1CSS\s+1
itself.
This copy is used for all workstations on that server and any other server
that supports only the Immediate Rendering subset.
.LP
If the main \s-1CSS\s+1 server only supports the Immediate Rendering subset, then
the main copy of the \s-1CSS\s+1 will reside in the \s-1API\s+1.  This main \s-1CSS\s+1 is
treated similarly to a server-based main \s-1CSS\s+1, except that it does not exist in a
server.  \s-1CSS\s+1 copies are still made on the server when workstations are
opened on servers that support \s-1PEX\s+1 structure storage, but the \s-1CSS\s+1 in the
\s-1API\s+1 remains the main \s-1CSS\s+1.
.LP
Maintaining a main \s-1CSS\s+1 in the \s-1API\s+1 is called client-side structure
storage.
The \s-1API\s+1 allows applications to force client-side structure storage even
though \s-1PEX\s+1 structure storage is available, but this is only a
feature useful for testing that configuration.  Using client-side structure
storage is too slow to be preferable when server structure storage is
available.
.H 3 "Display Connections"
.LP
The \s-1API\s+1 does not always use the display connection\**
.FS
A ``display connection'' in this paper means the display pointer
returned by \s-1XOpenDisplay\s+1.
.FE
specified when a workstation is opened.
To avoid synchronization problems the \s-1API\s+1 maintains only one connection
to any server.
This ensures that \s-1PEX\s+1 \s-1CSS\s+1, \s-1PEX\s+1 workstation and Xlib requests
issued by the \s-1API\s+1 are processed by
the server in the right order. (Recall that the single \s-1CSS\s+1 on a server
will serve all the workstations on that server.)
.LP
When a workstation is opened the \s-1API\s+1 first checks to see if it already
has a connection to the specified server.
If it does then it uses that connection even if a different connection was
specified by the application in the \s-1OPEN WORKSTATION\s+1 call.
If it does not, then the \s-1API\s+1 uses the specified connection to the new
server for all subsequent requests to that server.
This requires some cooperation on the application's part:\ \  the
application cannot close that connection until the \s-1API\s+1 is done using it.
The \s-1API\s+1 is done using a connection when all workstations on that server
are closed, except when the server is the main \s-1CSS\s+1 server.
If the application does not specify a connection, but only specifies a
server name, and the \s-1API\s+1 does not already have a connection to the
named server, the \s-1API\s+1 creates a new connection and uses it for all
subsequent requests to that server.
All server connections the \s-1API\s+1 opens are closed when no
more workstations exist on that server,
unless that server is the main \s-1CSS\s+1 server.
.LP
In all cases the server specified by the application must support some
subset of the \s-1PEX\s+1 extension.  The \s-1API\s+1 will not open workstations on
servers that do not support \s-1PEX\s+1.
.LP
The application can specify the display connection for the main \s-1CSS\s+1 server
when \s-1PHIGS\s+1 is opened.
It does this by calling the \s-1API\s+1's alternative \s-1OPEN PHIGS\s+1 function,
\s-1OPEN XPHIGS\s+1.
\s-1OPEN XPHIGS\s+1 accepts a variety of X-related information that helps the
\s-1API\s+1 ``do the right thing'' in the X environment.
\s-1OPEN XPHIGS\s+1 also performs the same operations as \s-1OPEN PHIGS\s+1.
.LP
If the application wants the \s-1API\s+1 to share the application's connection
for workstations that will subsequently be opened on the
main \s-1CSS\s+1 server, it must specify that connection to \s-1OPEN XPHIGS\s+1.
Otherwise the \s-1API\s+1 will create its
own connection to the main \s-1CSS\s+1 server when \s-1PHIGS\s+1 is opened, and will use
that connection for all workstations opened on that server, regardless of
connections to that server specified in the \s-1OPEN WORKSTATION\s+1 call.
.LP
If the specified main \s-1CSS\s+1 server does not support \s-1PEX\s+1 structure storage,
the \s-1API\s+1 does not maintain a connection to it after \s-1PHIGS\s+1 is opened.
Structure storage is in the client in this case so there is no need for a
server connection for \s-1CSS\s+1 storage.
.LP
.H 3 "The \fLmit/extensions/lib/PEX\fP Subdirectories\fR"
There are eleven subdirectories that contain code and one that contains
run-time files.
.IP \fL\s-1archive\s+1\fR 14
Contains the code for reading and writing archive files.
.IP \fL\s-1c_binding\s+1\fR 14
Contains the C binding code.
All the public entry points are in this code.
.IP \fL\s-1cp\s+1\fR 14
Contains the \s-1CP\s+1 and PHIGS state list code (see below).
There are different sets of code used for client-side structure storage
and server-side structure storage.
Some of the code used in the client is also different from the code used in
the \s-1PM\s+1.
The function and file prefixes indicate the code usage:
.DS
.ta +.5i
cpa_	Code for server-side structure storage
cpb_	Code for client-side structure storage
cpx_	Top level \s-1CP\s+1 code used in both the client and the \s-1PM\s+1
cpm_	\s-1CP\s+1 code used only in the \s-1PM\s+1
psl_	PHIGS state list code
.DE
There are also four files prefixed only with cp_:
.DS
.ta +1i
cp_ccom.c	Code used only in client for communicating with the \s-1PM\s+1
cp_rcom.c	Code used only in \s-1PM\s+1 for communicating with the client
cp_com.c	Communication code used by both the client and the \s-1PM\s+1
cp_util.c	Utility code potentially used in both the client and the \s-1PM\s+1
.DE
.IP
The \s-1PM\s+1 program is also in this directory in the file \fL\s-1phigsmon.c\fR\s+1.
.IP \fL\s-1css\s+1\fR 14
Contains the central structure store code for client-side structure
storage.
.IP \s-1\fLerror\s+1\fR 14
Contains the error handling code.
This code is invoked by potentially all of the modules.
.IP \s-1\fLinclude\s+1\fR 14
The \s-1API\s+1's header files.
.IP \fL\s-1input\s+1\fR 14
Contains the input device code.
.IP \fL\s-1lib\s+1\fR 14
Contains the run-time files.
.IP \fL\s-1pex\s+1\fR 14
Contains the \s-1PEX\s+1 protocol library used to build and send \s-1PEX\s+1 requests.
.IP \fL\s-1util\s+1\fR 14
Contains general purpose utility functions.
.IP \fL\s-1ws\s+1\fR 14
Contains the workstation code.
There are different sets of code used for client-side structure storage
and server-side structure storage.
Some of the code used in the client is also different from the code used in
the \s-1PM\s+1.
The function and file prefixes indicate the code usage:
.DS
.ta +.5i
wsa_	Code used only for server-side structure storage
wsb_	Code used only for client-side structure storage
wsx_	Utility code potentially used by all workstation functions
.DE
If a function or file also has the sequence \fIpm\fR in its name then it
contains code used only in the \s-1PM\s+1.
There are also two files with only a ``\fIws_\fR'' prefix:\ \ 
\s-1\fLws_inp.c\s+1\fR and \fL\s-1ws_pm.c\s+1\fR.
\fL\s-1ws_inp.c\s+1\fR contains the workstation input device control code.
It is used only in the \s-1PM\s+1.
\fL\s-1ws_pm.c\s+1\fR contains code specific to the \s-1PM\s+1.
.IP \fL\s-1ws_type\s+1\fR 14
Contains the code for building and modifying workstation description
tables.
.H 3 "The Importance of Keeping the Code Organization"
.LP
The code is carefully partitioned among the files in a way that prevents
the client from having to link with X toolkit or Athena Widget set code.
The files that reference toolkit code are kept separate and are only
included by a reference from the \s-1PM\s+1 main program in \fL\s-1cp/phigsmon.c\fR\s+1.
Files with \fIpm\fR in their name are only included in the \s-1PM\s+1, not the client.
When adding code you must be careful not to add any references to these
files from code that will run in the client.
If this does happen then the linker will complain of unresolved references
to \fIXt\fR or \fIXaw\fR symbols when attempting to link a PHIGS application program.
.H 3 "Important Modules and Data Structures"
.H 4 "The CP"
.LP
The \s-1CP\s+1 module is the heart of the \s-1API\s+1.
It is responsible for coordinating the other modules.
The binding functions call the \s-1CP\s+1, the \s-1CP\s+1 then calls other modules to
execute their part of the \s-1PHIGS\s+1 function.
All the \s-1CP\s+1 code is in the \fL\s-1cp\fR\s+1 subdirectory.
.LP
The data structure for the \s-1CP\s+1 is \fICp_struct\fR (see \fL\s-1cp.h\fR\s+1).
It contains state and control info and a function vector.
One \s-1CP\s+1 is maintained in the client and one in the \s-1PM\s+1.
The function vector is loaded with pointers to \s-1CP\s+1 functions when \s-1PHIGS\s+1 is
opened.
The function vector for the \s-1CP\s+1 in the client and the \s-1CP\s+1 in the \s-1PM\s+1 are
loaded differently.
.LP
The \s-1CP\s+1 functions call \fIcss_srvr\fR functions (see below),
or in a few cases just do the work or gather the inquiry information
themselves.
The \s-1CP\s+1 functions are in the files in the \fL\s-1cp\fR\s+1 subdirectory
with the \fIcpx\fR prefix.
.H 4 "CSS Servers"
.LP
\s-1CSS\s+1 servers maintain a structure store for all workstations that use it.
There is a \fIcss_srvr\fR for every copy of the CSS maintained.
The list of \fIcss_srvr\fR structures is attached to the \s-1CP\s+1 structure.
.LP
The \fICpx_css_srvr\fR (see \fL\s-1cpx.h\fR\s+1) data structure contains state information
and a function vector.
The function vector is loaded differently for client-side structure storage
and server-side structure storage.
These functions are called by the \fIcpx\fR functions of the \s-1CP\s+1.
.LP
Some \fIcss_srvr\fR functions are carried out in the \s-1PM\s+1 if the \s-1PM\s+1 is being used.
The \fIcss_srvr\fR functions for these cases send the \s-1PM\s+1 a function code and any
data needed and the \s-1PM\s+1 performs the function and sends back any return data.
For server side structure storage there are only a few of these functions.
For client-side structure storage almost all \fIcss_srvr\fR functions are
executed in the \s-1PM\s+1.
(For more information see Section
.XR @NumberOf(paths).)
.LP
\fIcss_srvr\fR structures are maintained in both the client and the \s-1PM\s+1
when the \s-1PM\s+1 is used.
For client-side structure storage the \fIcss_srvr\fR in the client is loaded with
functions that send the information to the \s-1PM\s+1.
The functions in the \fIcss_srvr\fR in the \s-1PM\s+1 carry out the work.
For server-side structure storage the \fIcss_srvr\fR in the \s-1PM\s+1 is only partially
loaded with the functions that are executed in the \s-1PM\s+1.
.LP
If the \s-1PM\s+1 is not used, there is no client-side structure storage.
.H 4 Workstations
.LP
The workstation structure (\fIWs\fR in \fL\s-1ws.h\s+1\fR) maintains workstations.
There is a workstation structure for each open workstation.
This structure contains workstation state and a function vector.
The function vector is loaded differently for client-side and server-side
structure storage.
.LP
All access to the workstation function vector is through its parent \fIcss_srvr\fR.
.LP
Workstation operations are executed in the \s-1PM\s+1 when the \s-1PM\s+1 and client-side
structure storage are being used, otherwise workstation operations are
carried out in the client.
Workstation structures are maintained in both the client and the \s-1PM\s+1 in the
former case, but not all the state is maintained in the client version.
.H 4 "Workstation Description Table"
.LP
The \fIWst\fR structure (see \fL\s-1ws_type.h\s+1\fR) contains
the workstation description table
and some other information for each workstation type.
Duplicate copies of a workstation's specific description table are kept in
both the client and the \s-1PM\s+1 when the \s-1PM\s+1 is being used.
.H 3 "Paths Through the Code" paths
.LP
\s-1PHIGS\s+1 functions can take many paths through the code.
The path is determined by the structure storage used and whether the \s-1PM\s+1 is
running.
The major paths are listed below.
In all cases the binding calls one of the client-side \s-1CP\s+1 functions.
The \s-1CP\s+1 function then calls the appropriate entry in the \fIcss_srvr\fR function vector.
For CSS functions the \s-1CP\s+1 calls this entry in all \fIcss_srvr\fRs.
For \s-1PHIGS\s+1 workstation functions the \s-1CP\s+1 calls only the
\fIcss_srvr\fR associated with the workstation.
.LP
The function vector of each \fIcss_srvr\fR is loaded according to the
structure storage and \s-1PM\s+1 configuration in effect.
Each function in the vector knows what it is to do for the given
configuration.
.IP "\fIServer-side structure storage, \s-1PM\s+1 is running\fR"
The binding calls the client-side \s-1CP\s+1 function.
The \s-1CP\s+1 function calls the appropriate \fIcss_srvr\fR function.
The \fIcss_srvr\fR function sends the needed \s-1PEX\s+1 request to the server.
If the \s-1PHIGS\s+1 function is related to \s-1PHIGS\s+1 input, \s-1MESSAGE\s+1
or the \s-1REDRAW REGIONS\s+1 escape the \fIcss_srvr\fR does not issue
a \s-1PEX\s+1 request from the client but instead sends a command to the \s-1PM\s+1.
The \s-1PM\s+1 executes the function, which may require sending a \s-1PEX\s+1 request to
the server.
.IP "\fIServer-side structure storage, \s-1PM\s+1 is not running\fR"
Same as the non-\s-1PM\s+1 case except that a command is not sent to the \s-1PM\s+1.
\s-1PHIGS\s+1 input and \s-1MESSAGE\s+1 are not available and
the \s-1REDRAW REGIONS\s+1 escape is serviced in the client.
.IP "\fIClient-side structure storage, \s-1PM\s+1 is running\fR"
The binding calls the client-side \s-1CP\s+1 function.
The \s-1CP\s+1 function calls the appropriate \fIcss_srvr\fR function.
The \fIcss_srvr\fR function sends the appropriate command to the \s-1PM\s+1.
The \s-1PM\s+1 executes the function, which may require sending a \s-1PEX\s+1 request to
the server.
.IP "\fIClient-side structure storage, \s-1PM\s+1 is not running\fR"
The binding calls the client-side \s-1CP\s+1 function.
The \s-1CP\s+1 function calls the appropriate \fIcss_srvr\fR function.
The \fIcss_srvr\fR function performs the requested action, which may require
sending a \s-1PEX\s+1 request to the server.
\s-1PHIGS\s+1 input and \s-1MESSAGE\s+1 are not available and
the \s-1REDRAW REGIONS\s+1 escape is serviced in the client.
.IP "\fIThe path in the PM\fR"
The \s-1PM\s+1 has a \s-1CP\s+1 just as the client does.
The \s-1PM\s+1 communication code gets commands from the client and calls the
appropriate \s-1CP\s+1 function (just like the binding in the client calls the \s-1CP\s+1
in the client).
The \s-1CP\s+1 then calls the \fIcss_srvr\fRs involved.
.IP "\fIWorkstation operations\fR"
In the server-side structure storage case most workstation operations are
performed in the \fIcss_srvr\fR functions in \fL\s-1cpa_ws.c\s+1\fR.
In the other case, however, workstation operations are performed by the
functions in the workstation's function vector.
These functions are called by the \fIcss_srvr\fR.
.IP "\fINon-css_srvr functions\fR"
The \s-1PHIGS\s+1 functions \s-1AWAIT EVENT\s+1, \s-1FLUSH DEVICE\s+1,
\s-1INQUIRE INPUT QUEUE OVERFLOW\s+1 and \s-1INQUIRE MORE SIMULTANEOUS EVENTS\s+1
do not go through a \fIcss_srvr\fR.
They go directly to the \s-1PM\s+1 if the \s-1PM\s+1 is running.
The \s-1CP\s+1 calls the communication routines that send the command and data to
the \s-1PM\s+1.
The \s-1CP\s+1 in the \s-1PM\s+1 then executes them directly.
.H 3 "Adding Operations"
.LP
Adding a new operation generally requires that function vector entries
and functions be added for each of the above paths through the code.
The steps involved are listed here.
.IP "\fIExtend the Binding\fR"
Add a binding function for the user to call.
This can be either a new function or it can be an escape.
Escapes should be used whenever possible.
Adding new functions may violate \s-1PHIGS\s+1 conformance.
.IP
Escapes are added by defining an escape code and the escape input and
output data structures in \fL\s-1phigs.h\fR\s+1, and adding an escape function to the
others in \fL\s-1c_binding/cb_esc.c\fR\s+1.
.IP
All data is passed from the binding to the \s-1CP\s+1 via the \fIPhg_args\fR structure.
All data is passed back from the \s-1CP\s+1 to the binding via the \fIPhg_ret\fR structure.
If the new operation involves data then \fIPhg_args\fR may need to be expanded to
handle it.
\fIPhg_args\fR is defined in \fL\s-1include/phgargs.h\fR\s+1.
It contains data fields for each existing \s-1PHIGS\s+1 operation.
Many of the existing operations use the generic \fIidata\fR and \fIfdata\fR fields.
If the new operation returns data then \fIPhg_ret\fR may also need expansion.
\fIPhg_ret\fR is defined in \fL\s-1include/phgretdata.h\fR\s+1.
.IP
It is important to keep these data structures small.
The whole \fIPhg_args\fR data structure is copied beteween the client and the \s-1PM\s+1
when the operation is sent to the \s-1PM\s+1.
A large \fIPhg_args\fR structure will slow down all operations that use the \s-1PM\s+1.
The size is kept relatively small by using indirection.
The client-to-\s-1PM\s+1 communication code knows how to copy indirect data to the
\s-1PM\s+1 after it sends the \fIPhg_args\fR structure.
.IP "\fIExtend the CP\fR"
Add a new \fIop\fR code to \fL\s-1include/cp_ops.h\fR\s+1.
.IP
Add a new \s-1CP\s+1 function to the appropriate \fL\s-1cp/cpx_*\fR\s+1 file,
either \fL\s-1cpx_css.c\s+1\fR, \fL\s-1cpx_ws.c\s+1\fR, \fL\s-1cpx_ar.c\s+1\fR or \fL\s-1cpx_misc.c\s+1\fR.
This function will dispatch to the \fIcss_srvr\fR's.
It will be used in both the client and the \s-1PM\s+1.
If the client-side function must be different from the \s-1PM\s+1 function then put
the client-side function in \fL\s-1cpx_clnt.c\s+1\fR and the \s-1PM\s+1 function in \fL\s-1cpx_pm.c\s+1\fR.
Declare the added function or functions extern in \fL\s-1cpx.h\fR\s+1.
.IP
Load the new \s-1CP\s+1 function vector entry in the function \fIcpx_load_funcs()\fR
in \fL\s-1cpx_clnt.c\s+1\fR.
The function to assign the new entry is the \fIcpx_\fR function added in the
previous step.
There is a section at the bottom of the function for entries that must be
loaded differently depending on whether or not the \s-1PM\s+1 is running.
.IP
Load the new \s-1CP\s+1 function vector entry in the function \fIcpm_load_funcs()\fR
in \fL\s-1cpx_pm.c\s+1\fR.
In most cases the function vector entry will be assigned the same function
it was assigned in \fL\s-1cpx_clnt.c\s+1\fR.
.IP "\fIExtend the css_srvr\fR"
Add a new function vector entry to the \fICpx_css_srvr\fR structure (see \fL\s-1cpx.h\fR\s+1).
.IP
Add new \fIcss_srvr\fR functions to the appropriate \fL\s-1cp/cpa_\fR\s+1
and \fL\s-1cp/cpb_\fR\s+1 files, either \fL\s-1cpa_css.c\s+1\fR or \fL\s-1cpa_ws.c\s+1\fR,
and \fL\s-1cpb_css.c\s+1\fR or \fL\s-1cpb_ws.c\s+1\fR.
These functions will service the \s-1PHIGS\s+1 function for their respective
structure storage configuration.
They will be used in both the client and the \s-1PM\s+1.
If a client-side function must be different from the \s-1PM\s+1 function then put
the client-side function in \fL\s-1cp{a,b}_clnt.c\s+1\fR and the \s-1PM\s+1 function in
\fL\s-1cp{a,b}_pm.c\s+1\fR.
Declare the added functions extern in \fL\s-1cpa.h\fR\s+1 and \fL\s-1cpb.h\fR\s+1.
.IP
Load the new \fIcss_srvr\fR function vector entry in the \fIload_funcs()\fR functions
in the files \fL\s-1cpa_clnt.c\s+1\fR, \fL\s-1cpa_pm.c\s+1\fR, \fL\s-1cpb_clnt.c\s+1\fR and \fL\s-1cpb_pm.c\s+1\fR.
There is a section at the bottom of \fIcpa_load_funcs()\fR in \fL\s-1cpa_clnt.c\s+1\fR
for loading the vector differently depending on whether or not the \s-1PM\s+1 is running.
In \fL\s-1cpb_clnt.c\s+1\fR this is done with a separate function for each case.
When the \s-1PM\s+1 is running, almost all \fIcpb css_srvr\fR functions are sent to
the \s-1PM\s+1 for execution, so the function vector is loaded almost entirely with
the client-to-\s-1PM\s+1 communication routines.
When the \s-1PM\s+1 is not running the \fIcpb\fR function vector is loaded directly with
\fIcpb\fR functions.
The \fIcpa\fR function vector varies little for the \s-1PM\s+1/no-\s-1PM\s+1 cases.
Most \fIcpa\fR functions are executed in the client even when the \s-1PM\s+1 is running.
.IP
To determine the client-to-\s-1PM\s+1 communication routine to use look at their
definition in \fL\s-1cp_ccom.c\s+1\fR.
There are seven of them, each for a different combination of sending and
receiving data between the client and the \s-1PM\s+1.
They are named \fIphg_cpc_class_{\s-1B,C,D,E,CD,CE,SPECIAL\s+1}\fR.
If the operation involves variable length data or otherwise requires 
indirection in the \fIPhg_args\fR of \fIPhg_ret\fR structures then the data copying
functions in \fL\s-1cp_ccom.c\s+1\fR and \fL\s-1cp_rcom.c\s+1\fR must be extended.
The functions to extend are \fIcpc_send_pre_data()\fR (\fL\s-1cp_ccom.c\s+1\fR) and
\fIcpr_get_pre_data()\fR (\fL\s-1cp_rcom.c\s+1\fR) for \fIPhg_args\fR data,
and \fIcpr_send_post_data()\fR (\fL\s-1cp_rcom.c\s+1\fR)
and \fIcpc_get_post_data\fR (\fL\s-1cp_ccom.c\s+1\fR) for \fIPhg_ret\fR.
.IP
Load the \fIcss_srvr\fR function vector entries in the \fIload_funcs()\fR functions in
\fL\s-1cpa_pm.c\s+1\fR and \fL\s-1cpb_pm.c\s+1\fR.
This may not be necessary for the \fIcpa\fR case, and is only required for
\fIcpa\fR operations that will execute in the \s-1PM\s+1, such as input operations.
It is almost always necessary for the \fIcpb\fR case, since almost all operations
are executed in the \s-1PM\s+1 when client-side structure store is used.
.IP "\fIExtend the Workstation\fR"
If the new operation is a workstation operation then add a new function
vector entry to the workstation function vector in \fL\s-1ws.h\fR\s+1.
.IP
Load the new workstation function vector entry in the \fIload_funcs()\fR function
in \fL\s-1wsa.c\s+1\fR and \fL\s-1wsb.c\s+1\fR.
Loading it in \fL\s-1wsa.c\s+1\fR is not necessary if the \fIcss_srvr\fR function in \fL\s-1cpa_ws.c\s+1\fR
does all the work.
Some workstation functions only work in the \s-1PM\s+1, and their entry is \s-1NULL\s+1 in
the client.
.H 3 "Using Different Toolkits"
.LP
All code that uses or references toolkits is confined to the
files \fL\s-1cp/phigsmon.c\fR\s+1, \fL\s-1cp/cpm_tlkt.c\fR\s+1, \fL\s-1input/sin_cho.c\fR\s+1, \fL\s-1input/sin_val.c\fR\s+1, \fL\s-1input/sin_strg.c\fR\s+1 and \fL\s-1ws/ws_pm.c\fR\s+1 (for the \s-1MESSAGE\s+1 function).
References to toolkit functions is kept in \s-1PM\s+1 code and out of client code
by the use of function vectors and confining all input and event processing
to the \s-1PM\s+1.
Only the \s-1PHIGS\s+1 choice, valuator and string devices use a toolkit.
Locator, stroke and pick devices use raw X input.
.LP
Changing the toolkit involves modifying the toolkit initialization code in
\fL\s-1cp/cpm_tlkt.c\fR\s+1, the device realization code
in \fL\s-1input/sin_{cho,val,strg}.c\fR\s+1,
the event dispatching code in \fL\s-1phigsmon.c\s+1\fR, and the message window code in
\fL\s-1ws/ws_pm.c\fR\s+1.
No other code should have to change.
The input device state is maintained in a way that is independent of the
actual device realization.
.H 3 "Adding Input Devices"
.LP
The steps to add additional input devices are:
.NP 
Extend the input device counts and descriptions in the workstation
desription table (function \fIinit_input_ws_dt()\fR in \fL\s-1ws_type/wstx_ini.c\fR\s+1).
.NP
Add the device realization to the \fL\s-1input\fR\s+1 directory.
.NP
Ensure that the event dispatching code in \fL\s-1phigsmon.c\s+1\fR is adequate for the
new device.
.NP
If the device is realized with a toolkit then add any required
initialization or default settings to \fL\s-1cpm_tlkt.c\s+1\fR.
.LP
Most of the code is table driven from the workstation description table.
For example, to add 2 more valuator devices of the same kind as the one
provided it is only required to change the number of valuator devices in
\fIinit_input_ws_st()\fR to 3.
Adding other realizations of the devices will be more involved than this,
but in general it is only necessary to add the device realization and
update the workstation description table.
Be careful not to exceed the maximum number of device allowed for in the
input device state arrays.
This value can be changed in \fL\s-1include/ws_type.h\fR\s+1.
.H C "Porting InsPEX"
.H 2 "Portability Goals and Non-Goals"
.LP
Ins\s-1PEX\s+1 is intended to work with 8-bit pseudocolor framebuffers.
We assume Unix, and have the goal of working under both System V and \s-1BSD\s+1
systems.
We also intend Ins\s-1PEX\s+1 to work on any 32-bit machine architecture.
We do not have the goal of working on non-Unix systems or different frame buffer depths.  
.LP
While support for other frame buffer depths is not built into Ins\s-1PEX\s+1,
some provisions were made for porting to other depths.
In the definition of the file format for saved images,
found in the comment for \fIi_save_image()\fR
in \fL\s-1mit/extensions/test/InsPEX/tools/pexint/pixutils.c\fR\s+1,
the first byte is intended to identify the type of file.
The only supported type is \s-1PSEUDOCOLOR\s+1, but other types could
be defined and added.
Their structure after the description string, width, and height fields
would be different, and this first byte would be used to differentiate
how the files were created and should be handled.
.H 2 "Porting Tests and the Interpreter"
.LP
Some portable data types are declared in \fL\s-1portable.h\fR\s+1
in \s-1\fLINSPEXHOME/tools/pexint\fR\s+1, for use in the interpreter and other tests.  
.LP
We have tried to use system calls that are common to both
System V and \s-1BSD\s+1 Unix.
Some System V incompatibilities reported
by an alert sponsor have been fixed, though they require
a \s-1SYSV\s+1 variable to be defined during compilation
(see the description of \s-1I_CFLAGS\s+1 in the \fIRelease Notes\fR
or \fL\s-1inspex.sh\fR\s+1, for a method to set this if it is not set by the compiler).
.H 2 "Porting the Inspector"
.LP
The chief portability issue for the Inspector is the choice
of Graphical User Interface toolkit.  The current implementation
uses the XView toolkit, which is available from \s-1MIT\s+1 and from Sun Microsystems.  
.LP
To facilitate porting, however, all toolkit-specific code is
isolated into two files, \fL\s-1toolkit.c\fR\s+1 and \fL\s-1toolkit.h\fR\s+1.
Through typedefs and function definitions, these files create a separate
interface layer on top of the toolkit being used.
While this interface looks like a toolkit itself, it has no pretense of being
a general-purpose toolkit \(em it was designed strictly to
make this particular application easily portable.
The interface types and functions should be implementable using any toolkit.
A port to Athena Widgets is also included.
.LP
Notification, or call-back, procedures are attached to the buttons
of the control panel; since we cannot be sure of of what arguments
a given toolkit may supply to these procedures, they
are expected to be defined without any arguments.
The negative side to this solution is that it forces greater use of global
variables.
.LP
The scrolling list could be implemented as a menu or other
control item.  Selecting the file name in the list could
be used to control loading of files, rather than the current
method of selecting and then hitting "load".
