.ds f. conclusion.sec
.sp 2
.NH 1 "NOTES ON THE PS FILE"
.XS
\s12\*(SN  NOTES ON THE PS FILE\s0
.XE
.sp
.PP
As the Program Specification file is described in Chapter 5 of the Khoros
Programmer's Manual, we will not repeat it all here.  However, a few extra
notes may help the reader.  The following notes deal with those segments of
the PS file that deal with C programming;  descriptions of all the different
segments of the PS file may be found in Chapter 5 of the Khoros Programmer's
Manual.  Note that it is NOT required for you to program in the 
PS file;  it is for this very reason that \fBghostreader\fP is provided -
so that the *.c, *.h, l*.c, *.1, and *.3 files may be modified directly,
and then \fBghostreader\fP executed, to update the PS file.  However, 
sometimes (especially when updating man pages) it is more convenient 
to modify the PS file, and run \fBghostwriter\fP to update the 
abovementioned files.  Therefore, selected segments of the PS file are 
explained in detail below.  Again, if you have not already read Chapter
5 of the Khoros Programming Manual as of yet, we urge you to do so now.
.sp
.IP -USAGE_ADDITIONS 
\fBGhostwriter\fP will place this code in the *.c file, in the \fIgw_usage()\fP
routine.  \fBGhostreader\fP will take this code from the *.c file, 
from between the \fI/* -usage_additions */\fP and 
\fI/* -usage_additions_end */\fP keys.
This field may or may not be filled in. It is used when
the programmer wishes to add more comments to the usage
statement. For example, \fIvbandcomb\fP uses this field to describe which
integer maps to which color space model. If the USAGE_ADDITIONS
field had not been used, the usage statement generated by \fBghostwriter\fP 
would not contain any information as to the legal values for the option that
specifies the resulting color space model. If it is not clear as
to what to add, it can always be added later.  The usage addition statements 
MUST be in C \fIfprintf\fP statements because these additions will be added 
directly to the main *.c file.  After the code is compiled, the programmer 
can take a look at the usage statement, and modify it if necessary.
.sp
.IP -INCLUDE_INCLUDES 
\fBGhostwriter\fP will place this code in the *.h file.  
\fBGhostreader\fP will take this code from the *.h file,
from between the \fI/* -include_include */\fP and
\fI/* -include_include_end */\fP keys.
This field will contain other #include statements that need to appear
in the *.h file that are not automatically generated.  Note that 
"unmcopyright.h" and "vinclude.h" are automatically included for 
vroutines; "unmcopyright.h" and "xvinclude.h" are automatically 
included for xvroutines (remember that when you are writing an xvroutine,
you must provide the [-xprog 1] flag!  If you forget, "vinclude.h"
will be included incorrectly, and you will not be able to compile your
program.
.sp
.IP -INCLUDE_ADDITIONS 
\fBGhostwriter\fP will place this code in the *.h file.  
\fBGhostreader\fP will take this code from the *.h file,
from between the \fI/* -include_additions */\fP and
\fI/* -include_additions_end */\fP keys.
This field will contain any additional statements that the programmer may want
to insert in the include file. Any #defines, global declarations, structure
definitions, etc. should be inserted here.
.sp
.IP -INCLUDE_MACROS 
\fBGhostwriter\fP will place this code in the *.h file.  
\fBGhostreader\fP will take this code from the *.h file,
from between the \fI/* -include_macros */\fP and
\fI/* -include_macros_end */\fP keys.
All code inside this field will be within #define statements. 
In many vroutines, the first step is to read in the input image. 
To do this it is necessary to use the function called \fIreadimage()\fP 
whose synopsis is :
\f(CW
.sp
struct xvimage *readimage(filename)
.br
char   *filename;
.sp
\fP
\fIfilename\fP is the name of the file;  in general, it corresponds to a [-i]
flag for the new program, as specified in the UIS file by a [-I] UIS line. 
\fIreadimage()\fP will return a pointer to the address where the image is 
located upon success, or NULL upon failure. Therefore, the pertinent error 
checking must be performed by the user.  Whenever the program exits, it should
do so with an appropriate comment.  Thus, calls to \fIreadimage()\fP
are a good subject for a macro to be included in the PS file under
-INCLUDE_MACROS.  For example:
.sp
.DS L
.ps 9
.vs 11
\f(CW
#define READINPUT(image) \\
image = readimage(vroutine->i_file); \\
if (image == NULL) { \\
  (void) fprintf(stderr, "vroutine: cannot read input image"); \\
  (void) fprintf(stderr, " %s\\n", vroutine->i_file); \\
  exit(1) \\
} 
\fP
.DE
.ps 11
.vs 13
.sp
If there is more than one input image, then each input image
should have its own corresponding READINPUT #define statement.
.sp
Other error checking can be also performed via macros.  Many
error checking routines are provided in the \fIverror\fP library (the
user is encouraged to read the online manual pages for \fIverror\fP!).  
For example, the data type of the image can be tested to see if it is 
one of the supported by the program. A check for the  type of encode 
scheme may also be needed to make sure that the program will work properly. 
Whenever two images are read, often the size of both images should 
match. As an example, in the following macro, the image is be checked 
to make sure that it has a data storage type of float, only one image 
is contained in the file, that the image contains 3 data bands and that
the map enable is optional.
.sp
.DS L
.ps 9
.vs 11
\f(CW
\#define CHECKINPUT(program, img1) \\
    propertype(program,img1,VFF_TYP_FLOAT,TRUE); \\
    proper_num_images(program,img1,1,TRUE); \\
    proper_num_bands(program,img1,3,TRUE); \\
    proper_map_enable(program,img1,VFF_MAP_OPTIONAL,TRUE); 
\fP
.DE
.ps 11
.vs 13
.br
.sp
All image error checking should be performed in this manner. 
As many #defines may be included as necessary. 
.IP -MAIN_VARIABLE_LIST 
\fBGhostwriter\fP will place this code in the *.c file, at the
beginning of the main() program.  \fBGhostreader\fP will take this code 
from the *.c file, from between the \fI/* -main_variable_list */\fP and
\fI/* -main_variable_list_end */\fP keys.
This field will contain the variable declarations used by the main program.
In vroutines that deal with image processing, for example, one necessary 
declaration is for all images used in the routine.  An example declaration 
might look like:
.sp
\f(CW
struct xvimage *image;
\fP
.sp
The xvimage structure is explained elsewhere in this document (it is the
internal representation of a VIFF file). Any other variables that will 
be used in the main() must also be defined in this field.
.sp
.IP -MAIN_BEFORE_LIB_CALL 
\fBGhostwriter\fP will place this code in the *.c file, in the
main() program, after the variable list, but before the library call.  
\fBGhostreader\fP will take this code from the *.c file, from between the 
\fI/* -main_before_lib_call */\fP and \fI/* -main_before_lib_call_end */\fP 
keys.  This field should contain the C code to get the all necessary input for
the program.  In addition, any other code that the programmer wishes to 
appear in the main before the call to the library routine.  All vroutines
must include a call to \fIcheck_args()\fP here.  The call to \fIcheck_args()\fP 
should have the following syntax.
.sp
\f(CW
if (check_args()) exit(1);
\fP
.sp
The \fIcheck_args()\fP function exists in the \fIvgparm\fP library. Its purpose
is to make sure the command line did not contain any invalid 
arguments. If the command line did contain some invalid arguments, 
\fIcheck_args()\fP will print them out and your program will exit.
REMEMBER: xvroutines MUST NOT make this call!
.sp
.IP -MAIN_LIBRARY_CALL 
\fBGhostwriter\fP will place this code in the *.c file, in the
main() program. \fBGhostreader\fP will take this code from the *.c file, 
from between the \fI/* -main_library_call */\fP and 
\fI/* -main_library_call_end */\fP keys.  This field should contain the 
C code to get the all necessary input for
It is necessary to pass all the appropriate information to the l*.c file; 
for example, in a vroutine that was also an image processing routine, it will
probably be necessary to pass the pointer of the original image as well as
any other parameters that the library might need in order to process the 
image. In situations where it is not necessary to preserve the input image, 
one need not pass to the library a new pointer for the resulting image, since
the resulting image will be returned through the same pointer as the 
input image was passed in with. In this scenario, the original image will 
be lost.  The library will return the resulting image of same data type 
that was originally specified by the user.  
.IP
If the input image needs to be preserved, a pointer to the resulting image 
is necessary. Thus, according to the type of problem the user is trying to 
solve, it will be necessary to build the data structure of a new image.
This task should be done prior to making the library call, and then the 
library routine should be sent the pointer of the new image with all the 
header information set.  To create a new image, see the man page on 
\fIvutils\fP.  An example follows:
.sp
\f(CW
if(! lvroutine(image, vroutine->w_int, vroutine->h_int))
{
   (void) fprintf(stderr, "lvroutine failed");
   exit(1);
}
\fP
.IP
When writing xvroutines, the call to the "library" routine will vary
somewhat (see Chapter 6 of the Khoros Programmer's Manual).  The main 
driver that is generated by \fBconductor\fP is what actually becomes the
l*.c file (ie, the user moves the code generated in "form_drv.c" into
the l*.c file). Thus, the library call for an xvroutine might look more like:
.sp
\f(CW
if (!(lxvroutine(argv, argc, program, xvroutine->i1, xvroutine->i2)))
   exit(1);
\fP
.IP
Note the lack of \fIfprintf()\fP statement when the library routine fails.
This is because there is really no need for such a statement in an xvroutine -
the appropriate error statement should already have been printed out by this
point.
.sp
.IP -MAIN_AFTER_LIB_CALL 
\fBGhostwriter\fP will place this code in the *.c file, in the
main() program, after the library call. \fBGhostreader\fP will take this 
code from the *.c file, from between the \fI/* -main_after_lib_call */\fP 
and \fI/* -main_after_lib_call_end */\fP keys.  This field should contain the 
With reference to image processing vroutines: now that all the data 
processing has been performed, the resulting image needs to be written 
to the specified file.  The function \fIwriteimage()\fP will perform this 
task. Its synopsis is:
\f(CW
.sp
writeimage(filename, imageptr)
.br
struct xvimage *imageptr;
.br
char *filename;
.sp
\fP
where \fIfilename\fP is the full pathname of the VIFF file, and \fIimageptr\fP
is a pointer to the structure xvimage of the image.
.sp
.IP -LIBRARY_DEF
\fBGhostwriter\fP will place this code in the l*.c file;
\fBGhostreader\fP will take this code from the l*.c file, from between the 
\fI/* -library_def */\fP and \fI/* -library_def_end */\fP keys.
it is the definition of your library routine. Depending on whether you are
writing a vroutine or an xvroutine, this segment will vary.  
In either case, you will need to include all the pertinent information that
was gathered from the command line.  A vroutine library definition might look
like:
.sp
\f(CW
int lvroutine(image, type)
.br
struct  xvimage *image;
.br
int  type;
\fP
.sp
.IP
On the other hand, the library definition for an xvroutine will look more like:
.sp
\f(CW
int lxvroutine(argc, argv, program, type)
.br
int argc;
.br
char *argv[];
.br
char *program;
.br
int type;
\fP
.sp
.IP -LIBRARY_INPUT
\fBGhostwriter\fP will place this code in the header of the l*.c file, and
in the *.3 file.
This field should contain a short description of each input to the library
routine, with types included. This field may be formatted for nroff.
Remember that library inputs should ALWAYS be documented in either 
the PS file or the *.3 file!  If you document library modifications 
directly into the l*.c file, they will be LOST the next time you 
run \fBghostwriter\fP.
.sp
.IP -LIBRARY_OUTPUT
\fBGhostwriter\fP will place this code in the header of the l*.c file, and
in the *.3 file.
This field should contain a short description of each output from the library
routine, with types included. This field may be formatted for nroff.
Remember that library outputs should ALWAYS be documented in either 
the PS file or the *.3 file!  If you document library modifications 
directly into the l*.c file, they will be LOST the next time you 
run \fBghostwriter\fP.
.sp
.IP -LIBRARY_MODS 
\fBGhostwriter\fP will place this code in the header of the l*.c file.
This field should contain a short description of each new modification
to the library routine in the form: name(date) - change.  This field may
be formatted for nroff.  When using the \fIvi\fP editor, it is often 
convenient to use !!date to include the current date.  Remember that 
library modifications should ALWAYS be documented in either the PS file
or the *.3 file!  If you document library modifications directly into
the l*.c file, they will be LOST the next time you run \fBghostwriter\fP.
.sp
.IP -LIBRARY_INCLUDES 
\fBGhostwriter\fP will place this code at the very top of the l*.c file.
\fBGhostreader\fP will take this code from the l*.c file, from between the 
\fI/* -library_includes */\fP and \fI/* -library_includes_end */\fP keys.
This field should contain any #include statements that need to be included
in the l*.c file that are not already included by \fIvinclude.h\fP (for
vroutines) or \fIxvinclude.h\fP (for xvroutines).
.sp
.IP -LIBRARY_CODE 
\fBGhostwriter\fP will place this code in the body of the l*.c file.
\fBGhostreader\fP will take this code from the l*.c file, from between the 
\fI/* -library_code */\fP and \fI/* -library_code_end */\fP keys.
This segment contains all the C code for the library routine.  
If you are like most programmers, and prefer to modify code directly in
the lvroutine.c file, then \fBghostreader\fP should be used to pick out 
the code from the l*.c file and place it in the PS (*.prog) file, after you
have finished editing the library code.
.sp 3
.NH 1 "INTEGRATING THE NEW PROGRAM INTO CANTATA"
.XS
\s12\*(SN  INTEGRATING THE NEW PROGRAM INTO CANTATA\s0
.XE
.sp
.PP
The final task that remains after installing the new program is to 
incorporate the program into \fBcantata\fP.  Prior to doing this, the
new program should be tested from both the command line and from the 
GUI.  Simply running the new program from the command line using each
option will test the functionality of the program.  To examine the 
GUI for the new program, start up \fBcantata\fP and use the 'Workspace' 
pulldown menu to bring up the 'File Attributes' pane.  On the 'File Attributes'
pane, enter the name of your *.pane file in the "UIS Filename" parameter box.
Once the UIS file is read in, a glyph representing your program will be 
created you may then be connected up with other glyphs for testing of 
your routine.
.PP
Now, you must add a reference to your new program in the UIS file describing
the \fBcantata\fP subform on which you want your new program to be accessible
from.  First, look through the existing directories that may be found in
\f(CWKHOROS_CONTRIB/repos/cantata/subforms\fP and decide which one is most
appropriate for your program (if desired, you may create a new subform -
see Chapter 2 for more details).   Move the program's UIS file (*.pane file) 
to the directory that you have chosen in 
\f(CWKHOROS_CONTRIB/repos/cantata/subforms\fP.  
.PP
You must then modify the UIS file in that directory that defines the 
subform for the main category to which you will be adding your program;  
there will be only one of these files per directory, and it will be 
named *.sub, where "*" is the name of the main category of the programs on
that subform.  To actually incorporate your program into cantata, 
you must add two lines to this *.sub file;  one (-g) UIS line to put a button
on the subform that will bring up the pane associated with your program, and
one matching (-p) line that will include your *.pane file within the subform
definition specified in the *.sub file.  Adding these 
two lines to the *.sub file will cause \fBcantata\fP to include your 
installed and compiled program.  
Chapter 3 provides a complete discussion on the specific
requirements for pane files to be included into \fBcantata\fP.
.PP
Following is an example of the modifications
that would be made to \f(CWanalysis.sub\fP to add the routine \fBdostuff\fP.
In particular, look at the (-g) and (-p) lines that reference the program,
"DoStuff".  
.sp
.DS L
.ps 9
.vs 11
\f(CW
-F 4.2 1 0 170x7+10+20 +35+1 'CANTATA Visual Programming Environment for the KHOROS System' cantata
-M 1 0 100x40+10+20 +23+1 'Data Analysis' analysis
-G 1 20x38+1+2 +2+0 'Choose Selection'
-g 1 1 18x1+1+1 'Remove Interlace'
-g 1 0 18x1+1+2 'Ring Intergral'
-g 1 0 18x1+1+3 'Total Harmonic Distortion'
-g 1 0 18x1+1+4 'Row and Col Sums'
-g 1 0 18x1+1+5 'Boundary Fill'
-g 1 0 18x1+1+6 'Usound Class'
-g 1 0 18x1+1+7 'Do Stuff'
-H 1  18x2+1+14 'HELP' 'guide help' KHOROS_CONTRIB/doc/cantata/subforms/analysis/help
-Q 1 0 18x2+1+16 'QUIT'
-E
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vblurlace.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vringint.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vthd.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vrcsum.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vfill.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/vuclass.pane
-p KHOROS_CONTRIB/repos/cantata/subforms/analysis/dostuff.pane
-E
-E
\fP
.DE
.ps 11
.vs 13
.sp
.PP
Notice the seventh (-g) line, specifying a new guide button called "Do Stuff",
and the seventh (-p) line, referencing the new "dostuff.pane" UIS file.  These
are the two lines that must be added to the  \f(CWanalysis.sub\fP UIS file
in order to make \fBcantata\fP include the new \fBdostuff\fP program.
Once the (-g) and (-p) lines referencing the new routine 
have been added to the appropriate subform, \fBcantata\fP can now access
the new routine.  It is imperative that you add the
(-g) line and the (-p) lines consistently;  that is, if you add a 7th (-g) line
to the subform definition, you take care to add your (-p) line as
the 7th (-p) line in the subform definition, and \fInot\fP the 6th or 5th.  
This is because the \fIxvforms\fP library determines which subform button 
will map which pane \fIstrictly by order of appearance\fP.  Furthermore,
make sure that your (-g) line has a geometry string that is NOT identical 
to any of the others.  Geometry strings that are identical cause subform 
buttons to be mapped directly on top of each other, and in this case your 
subform button will not appear on the \fBcantata\fP subform; even though
it will exist, it will be underneath another button, and therefore invisible. 
.PP
The above procedure is the simplest way to add new programs to \fBcantata\fP.
As you become more familiar with the tools in Khoros, you will discover that
it is not that difficult to completely reconfigure \fBcantata\fP for
different application areas.
.sp 3
.NH 1 "MAINTENANCE OF NEW PROGRAMS"
.XS
\s12\*(SN  MAINTENANCE OF NEW PROGRAMS\s0
.XE
.sp
.PP
To fix bugs in new and existing programs, it is wise to create a work
directory where bug fixes may be performed.  A tool called \fBkdinstall\fP
is available to help copy all the files associated with a routine to your 
work directory.  The \fBkdinstall\fP routine does not remove files from
the source tree directories, it just copies them to your work directory.
The way to use \fBkdinstall\fP is to change directories to the location
of the current config file for the routine to de-install, and execute the
\fBkdinstall\fP program.  The syntax for the \fBkdinstall\fP program is
as follows:
.sp
\f(CW
% kdinstall -name xxxx -dest yyyy [-mach zzzz] [-force t]
\fP
.sp
where,
.IP xxxx
is the name of the routine to de-install.
.br
.IP yyyy
is the destination path for the files.  This is typically a directory
in your work area.  Note that if the directory does not exist, then the
program will prompt you to create the directory.
.br
.IP zzzz
is the path and filename of the mach file that is being used for the
current de-install.  The default mach file will be used if none is
provided.
.br
.IP t
is a boolean that specifies whether to use the force option which bypasses
the overwrite prompts and edit sessions.  The default is FALSE, which does
not bypass the overwrite prompts and edit sessions.  Note that the force
option of TRUE is not allowed if the vroutine has never been installed, or
has been removed from the system.
.br
.sp
.PP
All bug fixes in new and existing programs can be performed using either the
source code (*.c) files or the program specification (*.prog) file.  If 
modifications are made to the source code files, then \fBghostreader\fP
should be run to incorporate the changes into the program specification
file.  On the other hand, if changes are made to the program specification
file, then \fBghostwriter\fP should be run to generate new source code
files.  If you are unsure which of the ghost routines to run, simply
run \fBghostcheck\fP to provide you with some assistance.  Remember to
copy the library source and manual pages to the appropriate directories
if you did not use the "-config" option of \fBghostwriter\fP.
.PP
Once the bug fixes have been made, you must then re-install the program.
This is most easily accomplished by running the \fBkinstall\fP program,
which will correctly install the bug fixed routine over the existing
routine in source and recompile the routine.  If multiple architectures
are supported, then it will rsh to the other machines and recompile for
that architecture.  To run \fBkinstall\fP refer to the instructions
given in Section B.4.2 of this chapter.
.sp 3
