.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 "USING THE DEBUGGER ON THE NEW PROGRAM"
.XS
\s12\*(SN  USING THE DEBUGGER ON THE NEW PROGRAM\s0
.XE
.sp
.PP
Using a debugger is always highly recommended when developing and debugging
code.  Here at UNM we use \fBdbx, xdbx\fP, and \fBsaber\fP to debug Khoros
programs.  Note that when preparing to use a debugger, one modifies the 
appropriate fields in the Imakefile in order to compile properly.
.sp 2
.NH 2 "USE OF DBX AND XDBX"
.XS
      \*(SN  USE OF DBX AND XDBX
.XE
.sp
.PP
The first step is to compile any libraries you have created for use with the
debugger. Skip this step if there is not a specific library in your toolbox 
that is used by the new program. In your library Imakefile, you will see this 
line near the end:
.br
\f(CW/* LIBCDEBUGFLAGS = */\fP
.br
Change it to:
.br
\f(CWLIBCDEBUGFLAGS = -g\fP
.PP
If you are using a special include directory in your toolbox needed
by your library, you must also specify that include directory.  Relative 
paths may be used.  You must use the syntax, "-I{path}" with no
spaces btwn "I" and "path".  Specify as many directories as are
applicable. For example, if you want to look for *.h files in ../../include 
as well as in . and in $KHOROS_HOME/include, you would edit the Imakefile
like this:
.br
\f(CW/* STD_INCLUDES = */\fP
.br
Change it to:
.br
\f(CWSTD_INCLUDES = -I. -I../../include\fP
.PP
Now, use makemake to recreate your library Makefile:
.br
\f(CW% makemake\fP
.PP
Next, if the library was previously compiled without the debugging flag, you 
must remove all library *.o files that were not compiled for the debugger:
.br
\f(CW% make clean\fP
.PP
And recreate all *.o's & the *.a for use with the debugger:
.br
\f(CW% make install\fP
.sp
.PP
The second step is to compile your program for the debugger. 
In your program Imakefile, you will see this line near the end:
.br
\f(CW/* CDEBUGFLAGS = */\fP
.br
Change it to:
.br
\f(CWCDEBUGFLAGS = -g\fP
.PP
Again, if you are using a special include directory in your program,
you must also specify that include directory.
.br
\f(CW/* INCLUDES = */\fP
.br
Change it to point to the directory you need to include, for example:
.br
\f(CWINCLUDES = -I. -I../include\fP
.PP
Now, use makemake to recreate your Makefile:
.br
\f(CW% makemake\fP
.PP
Next, you must remove all *.o files that were not compiled for the debugger:
.br
\f(CW% make clean
.PP
And recreate all *.o's & the executable for use with the debugger:
.br
\f(CW% make\fP
.PP
Finally, use the debugger:
.br
\f(CW% dbx {\fIprogram_name\fP}
.br
or
.br
\f(CW% xdbx {\fIprogram_name\fP}
.PP
For more information on \fBdbx\fP or \fBxdbx\fP, use the system \fBman\fP 
command, as in:
.br
\f(CW% man dbx\fP.
.sp 2
.NH 2 "USE OF SABER"
.XS
      \*(SN  USE OF SABER
.XE
.sp
.PP
If you have the \fBsaber-C\fP debugging tool, we highly recommend using it.  
Where \fBdbx\fP may be more efficient for finding a specific core dump, for 
example, \fBsaber\fP can be used to look for unused variables, mismatched 
parameters, memory over-writes, de-allocation of memory, and so on.  To use 
\fBsaber\fP, type:
.br
\f(CW% saber\fP
.ce 2
Saber-C - Version 3.0.1
Copyright (C) 1986, 1990 by Saber Software, Inc.
.sp
Saber-C licensed for: University of New Mexico
.br
For customer service, call 277-0803 or use the 'email' command.
.sp
Attaching: /lib/libc.a
.br
1 -> make saber_{\fIprogram_name\fP}
.sp 
.PP
See your \fBsaber\fP manuals for more information on use of \fBsaber-C\fP.
.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.  Running the new program from the command line or from within
\fBcomposer\fP 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 connect it with other glyphs for testing of 
your routine.  This above method of bringing your new program into 
\fBcantata\fP does not put the program name into the \fBcantata\fP
menu.  The next paragraph explains how that is done.
.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(CW{toolbox_home}/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).   \fBKinstall\fP will help you do most
of the work needed to edit the subform file. \fBKinstall\fP moves
the program's 
UIS file (*.pane file) to the directory that you have chosen and prompts
you to edit the proper subform file in
\f(CW{toolbox_home}/repos/cantata/subforms\fP.  
.PP
There should only be one of subform file 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.
The \fBcantata\fP UIS form in \f(CW{toolbox_home}/repos/cantata\fP needs
to reference the subform file.  To execute \fBcantata\fP
using your form and not the default form, use the command:
.PP
\f(CW % cantata -form {toolbox_home}/repos/cantata/example.form\fP.  
.LP
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 Integral'
-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' $TOOLBOX_NAME/doc/cantata/subforms/analysis/help
-Q 1 0 18x2+1+16 'QUIT'
-E
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vblurlace.pane
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vringint.pane
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vthd.pane
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vrcsum.pane
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vfill.pane
-p $TOOLBOX_NAME/repos/cantata/subforms/analysis/vuclass.pane
-p $TOOLBOX_NAME/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.
.LP
IMPORTANT NOTE: the  \f(CW$TOOLBOX_NAME\fP is not a shell environment
variable.  YOU SHOULD NOT USE THE SETENV COMMAND TO SET THE TOOLBOX NAME.
Instead, this variable is determined for you via expansion of the information 
contained in your Toolbox File located in the file pointed to by
\(CW$KHOROS_TOOLBOX\fP.  You are still welcome to
use any environment variable you
wish in specifying a file path.  If you are extending Khoros \fIwithout\fP
conforming to toolbox convention, the use of environment variables can
help you organize your development.
.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 aaa -dest bbb -toolbox ccc [-force d]
\fP
.sp
where,
.IP aaa
is the name of the routine to de-install.
.br
.IP bbb
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 ccc
is the name of the toolbox from which you are de-installing the routine.
.br
.IP d
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 \fBrsh\fP to the other machines and recompile for
that architecture.  To run \fBkinstall\fP refer to the instructions
given in Section C.4.2 of this chapter.
.sp 3
.NH 1 "USE OF TOOLBOXES"
.XS
\s12\*(SN  USE OF TOOLBOXES\s0
.XE
.sp
.NH 2 "INTRODUCTION TO TOOLBOXES"
.XS
      \*(SN  INTRODUCTION TO TOOLBOXES
.XE
.sp
.PP
All routines that you develop to extend the Khoros system 
should be installed and 
maintained in a \fItoolbox\fP.  A toolbox must exist before you can run
\fBkinstall\fP.  A toolbox consists of a specific set of
files that make up the toolbox source tree and specify the operation
of \fBImake\fP. 
The toolbox directory structure
mimics the $KHOROS_HOME directory structure, but can 
be created in the location of your choice.  
.PP
Why are toolboxes a good idea?   The programmer can by pass all of the
tools in the Khoros system and just create UIS pane files so that 
\fBcantata\fP can access their programs.  If they choose to
use this method of extending
Khoros, they minimizes their initial effort, but the result will be
programs that are not as maintainable or reusable.  Thus, the purpose
of using \fBkraftsman\fP, \fBkinstall\fP, and \fBImake\fP is
to create programs that can more easily be maintained and exchanged.
Toolboxes also
give the developer a framework in which to easily exchange
and or contribute (or sell) their work.
.PP
The toolbox top or home directory is similar to
the $KHOROS_HOME directory:
.sp
\(bu bin\  - where all executables will be installed 
.br
\(bu data\ - if desired, for data files that did not come with the Khoros system
.br
\(bu doc\  - online documentation for programs
.br
\(bu include\ - for include files that are used by more than one program
.br
\(bu lib\ - for libraries that you may create to be used by your programs
.br
\(bu man\ - for manpages about programs
.br
\(bu repos\ - containing configuration files, UIS files, etc.
.br
\(bu src\  - containing one subdirectory for each program, may be further divided into application areas if desired.
.sp
For more details on the contents of each of these directories, see the 
explanation in Chapter 9 on the contents of the $KHOROS_HOME directory.
For an example of a toolbox, see the "Example Toolbox" found in 
\f(CW$KHOROS_HOME/example_toolbox\fP.
.sp
.NH 2 "THE TOOLBOX FILE"
.XS
      \*(SN  THE TOOLBOX FILE
.XE
.PP
Toolboxes are managed through a Toolbox File, which specifies the toolboxes 
to be accessed by a user. If desired, you may create your 
own Toolbox File to provide you with access to your choice of available 
toolboxes.  You specify the location of
your own Toolbox File with the environment variable,
KHOROS_TOOLBOX.   Otherwise, the default Toolbox File is 
\(CW$KHOROS_HOME/repos/Toolboxes\fP:
.br
\f(CW% setenv KHOROS_TOOLBOX $KHOROS_HOME/repos/Toolboxes\fP
.br
The \fBkraftsman\fP program was written to provide a user with
an automated method of creating toolboxes and editing the toolbox
file.
The Toolbox File is made up of one entry for each toolbox;  each entry must 
be on one line, and has six fields  which are separated by a colon (:).  
There may be no blank lines in this file.  The toolbox entries are in the 
following format:
.sp
\f(CWNAME:PATH:TITLE:DESCRIPTION:AUTHOR:INFO_FILE\fP
.sp
.IP "NAME" 15
Toolbox name in upper case
.IP "PATH" 15
Path to toolbox location
.IP "TITLE" 15
Title of Toolbox for use by cantata at a later time
.IP "DESCRIPTION" 15
Short Description of Toolbox 
.IP "AUTHOR" 15
Author(s) of Toolbox
.IP "INFO_FILE" 15
Specifies a file which contains more extensive detail about contents 
and use of toolbox (optional).
.LP
An example of a toolbox entry is as follows (it is a single line):
.sp
.nf
\f(CWEXAMPLE_TOOLBOX:$KHOROS_HOME/example_toolbox:Example 
Toolbox:This is an example toolbox:Tom Sauer:$EXAMPLE_TOOLBOX/
repos/example.info\fP
.fi
.LP
IMPORTANT NOTE: \f(CWEXAMPLE_TOOLBOX\fP is \fBNOT\fP a shell
environment variable.  It is used internally by the tools - do not
make it an environment variable.
.sp
.NH 2 "CREATING A TOOLBOX"
.XS
      \*(SN  CREATING A TOOLBOX
.XE
.sp
.PP
The interactive Khoros program called \fBkraftsman\fP is designed to
create & manage toolboxes automatically.  A toolbox must be 
created before \fBkinstall\fP can be used.
.PP
The recipe that you choose to follow below depends 
on whether you want to completely create a toolbox
manually or use \fBkraftsman\fP to do it.  If you use \fBkraftsman\fP,
you are more likely to have a consistent and maintainable toolbox.
The later stages
of the toolbox creation process are the same whether you use \fBkraftsman\fP
or do it all manually.
If you decide not to use \fBkraftsman\fP, we have 
provided a generic toolbox tar file that can be untarred in the 
desired toolbox
location to get you started.  Follow these steps in creating your toolbox:
.LP
.sp
.ce
\fBCREATING A TOOLBOX USING KRAFTSMAN\fP
.IP "1."
Make a copy of \(CW$KHOROS_HOME/repos/Toolboxes\fP, preferably \fBnot\fP
into the toolbox directory that you are going to create later.  
Modify the environment variable that points to your new
Toolbox File.  The command
.br
\f(CW% setenv KHOROS_TOOLBOX {New Toolbox File}\fP
.br
will set the $KHOROS_TOOLBOX environment variable to your own Toolbox File.
Note:  you should also add this line to your ".khoros_env" file, so that you do
not have to remember to type this line every time you log in.
.IP "2."
Execute the \fBkraftsman\fP program, \f(CW% kraftsman\fP, and then fill out the
desired name for your new toolbox.  After entering the name, type
a carriage return and the rest of the Toolbox File fields will be
filled out.  Edit any of them that you want to change - at a minimum you
will want to change the directory path to the toolbox.  Then click on
the CREATE button.  You now have a toolbox framework in place.
.IP "3."
From now on, we will use "{toolbox_name}" to mean the name of your new toolbox,
and {toolbox_home} to mean the path to your toolbox.
At this time, go to the "Configuration" pane to modify the default
path names of the bin directory and lib directory.  You may also wish to
change library and include search paths, as well as, setting compiler 
defines and defining libraries that the toolbox will manage.  See the
\fBkraftsman\fP on-line help for more information.
.IP "4."
A source configuration file has been set up that will work for a
basic toolbox.    This file is located in
.br
\f(CW{toolbox_home}/repos/config/src_conf/{toolbox_name}_mf\fP. 
.br
If you wish to customize "{toolbox_name}_mf" by changing
khoros user, local src top, etc,  there are comments in the file to help you 
make these modifications.  We are assuming here that you are \fBnot\fP
supporting multiple architectures and multiple source trees - if you are, 
see Chapter 9 for special instructions.
.IP "5."
Continue below with the \fBGeneral Toolbox Installation and Maintenance
Instructions\fP.
.LP
.sp
.ce
\fBCREATING A TOOLBOX MANUALY\fP
.IP "1."
Decide on a location for the toolbox;  create a directory there with
the desired toolbox name in lower case. 
.IP "2." 
Make a copy of \(CW$KHOROS_HOME/repos/Toolboxes\fP, preferably \fBnot\fP
in the toolbox directory that you just created.  
Modify the Toolbox File and add an entry describing 
the new toolbox as detailed in the section above.  Use the command:
.br
\f(CW% setenv KHOROS_TOOLBOX {New Toolbox File}\fP
.br
to set the $KHOROS_TOOLBOX environment variable to the location of
your modified Toolbox File.
Note:  you should also add this line to your ".khoros_env" file, so that you do
not have to remember to type this line every time you log in.
.IP "3."
Go to the toolbox directory, and execute:
.br
\f(CW% tar -xvf $KHOROS_HOME/repos/config/toolbox/toolbox.tar\fP
.IP
This will create a template toolbox directory structure for you, with 
some template files that you will have to change to suit your particular
needs.
.IP "4."
From now on, we will use "{toolbox_name}" to mean the name of your new toolbox,
and {toolbox_home} to mean the path to your toolbox.
Next, go to \f(CW{toolbox_home}/repos/config/imake_conf\fP and move 
"template.def" to "{toolbox_name}.def".  Modify "{toolbox_name}.def" to specify the 
toolbox name, the locations of bin, lib, and include directories, and the 
libraries to link against.  There are comments in the file to help you make 
these modifications.
.IP "5."
Go to \f(CW{toolbox_home}/repos/config/src_conf\fP, and move 
"template_mf" to "{toolbox_name}_mf".   Modify "{toolbox_name}_mf" to specify the
khoros user, local src top, etc.  There are comments in the file to help you 
make these modifications.  We are assuming here that you are \fBnot\fP
supporting multiple architectures and multiple source trees -- if you are, 
see Chapter 9 for special instructions.
.IP "6."
Continue below with the \fBGeneral Toolbox Installation and Maintenance
Instructions\fP.
.LP
.ce
\fBGENERAL TOOLBOX INSTALLATION and MAINTENANCE INSTRUCTIONS\fP.
.LP
At this point, it is assumed that you have successfully created the basic 
toolbox source tree and configuration files.  Please continue:
.IP "1."
\fBkinstall\fP needs a directory(s) in which it can install a program.
In  \f(CW{toolbox_home}/src\fP, you will need to create
any directories that you might need - we suggest a \f(CWLib\fP directory if
you will be creating a new library for your new programs to call, and one
directory for each program, named for that program.  In the case that you 
plan to add programs in different application domains, we recommend that
you create a directory for each application domain, and then have the 
associated program directories located in the application domain directories.
.IP
It is assumed that you will use \fBkinstall\fP to install the new program
into your toolbox. \fBBEFORE you can use kinstall\fP
for the new toolbox, you will need to follow this example to set up the
toolbox source tree.
.sp
Suppose the "vfrog" program is the first program to be installed
into the new toolbox. And, you want "lvfrog.c" code to become part of a library.
The first thing to do is copy the "lvfrog.c" code into the library directory
in the source tree. Next you must create an Imakefile and Makefile. The
following commands will create the Imakefile and Makefile for you:
.sp
.RS
\f(CW% imkmf -name {library_name} -type lib -toolbox {toolbox_name}\fP
.br
\f(CW% makemake
.RE
.sp
Where {library_name} is the name of the library and {toolbox_name} is the name
of your toolbox. This must be done so that \fBkinstall\f does not fail during
the installation of the first routine.
.IP
The {toolbox_name}.def file must now be modified so that programs can link 
against this new library. So, modify 
{toolbox_home}/repos/config/imake_conf/{toolbox_name}.def and add the library
to the appropriate symbol. This file is fully commented, so just follow
the comments for adding the library definition.
.IP
Each vroutine has a *.conf file associated with it.  The directories
that specify where the subform help file (subhelpfile:)  and the pane 
file (panefile:) are to be located
must exist. If these directories do not exist, you must create them prior
to installing your new routine. Also, the directory that the pane file will 
be installed into must contain a subform file. For information on how to
create and customize a subform file, consult Section G of this chapter.
.IP "2."
Now, your toolbox is ready for use.  Remember that any time you use any
of the Khoros tools, such as \fBimkmf, kinstall, ghostwriter\fP etc, you 
\fIMUST\fP provide the name of your new toolbox.  To be on the safe side,
any time you use a Khoros utility, consult the usage statement by using the
[-U] argument.  If \fIany\fP utility lists [-toolbox] as an option - USE IT!
.IP "3."
Once you have created your toolbox source tree,  you must create Imakefiles
and Makefiles for the toolbox source tree.  This is done by
using \fBimkmf\fP.  In \f(CW{toolbox_home}/src\fP, and in any application
domain directories that you may have, execute:
.sp
\f(CW% imkmf -type dir -toolbox {toolbox_name}\fP
.sp
\f(CW% makemake\fP
.sp
Note, makemake may give you the following errors:
.br
\f(CWsh: syntax error at line 3: `;' unexpected\fP
.br
\f(CWmake: Fatal error: Command failed for target `depend'\fP
.sp
You can ignore this error for now. It is caused because makemake wants to
descend into all subdirectories, but no Imakefiles and Makefiles
have yet been created in the subdirectories.  As you add programs and
directories, this error will no longer appear.
.sp
The \f(CWimkmf\fP will update the Imakefile automatically for you. So,
if any files change or file names changes, than \f(CWimkmf\fP will
automatically update the Imakefile. The f(CWmakemake\fP command will
automatically generate a Makefile from the Imakefile. you should
never modify the Makefile since it is automatically generated.
.IP "4."
Develop your new programs in your work directory described in the former 
sections of this chapter.  Don't forget to use the [-toolbox] option 
to \fBghostwriter\fP.
.IP "5."
If you are writing a vroutine, use \fBkinstall\fP to install your new program 
in your toolbox.  Don't forget to  use the [-toolbox] option.  If you are
writing an xvroutine, you must install your new program by hand.  Instructions
for this were given earlier in this chapter. 
.IP "6."
Add the \f(CW{toolbox_home}/bin\fP directory to your path (either in your 
".cshrc" file or in your ".login" file) so that you can access your new routine.
.sp 2
.NH 2 "DON'T FORGET ..."
.XS
      \*(SN  DON'T FORGET  ...
.XE
.IP 1.
After setting up a toolbox and defining the bin directory location, add
this path to the toolbox bin directory to your path. Modify your ".cshrc"
or ".login" file and add the toolbox bin directory to your path.
.IP 2.
If any other libraries are created in the toolbox and programs need
to load against them, those libraries must be added to the 
\f(CW{toolbox_home}/repos/config/imake_conf/{toolbox_name}.def\fP file 
using \fBkraftsman\f. 
.IP 3.
Any time the \f(CW{toolbox_home}/repos/config/imake_conf/{toolbox_name}.def\fP
file is modified, you should do:
.br
\f(CW% make Makefile Makefiles\fP
.br
in the top level source directory of your toolbox to update all the 
Makefiles to take advantage of the changes.
.IP 4.
When using the any of the Khoros tools to manage a toolbox, the [-toolbox] 
option MUST be specified.
