		Extended Types for Xgopher

Extended types allow the user of Xgopher to add new gopher types to 
Xgopher.  They can also be used to override the standard processing
of the built-in types.  This is all done through application resources
and does not depend on any changes to the source code.  It is very
easy to add new type support and prototype new ideas using Xgopher.

A new type added to Xgopher is not treated as a "step-child", but
as a full-fledged gopher item.  This powerful mechanism literally adds
a new type designator to Xgopher's list of supported types.

A built-in Xgopher data type may be changed using extended types
to redefine it.  This is true for all types except directory and
index search types (types '1' and '7').  In fact, to test the
validity of this approach, Xgopher has been tested with every
built-in non-directory type redefined by an external type.  In
other words, Xgopher only needs to be able to process directories
and extended types!  However, there is still an advantage to using
built-in types for commonly used items: Xgopher has more control
of the user interface and providing proper feedback to the user.
They may also be implemented more efficiently since Xgopher knows
very specific requirements for internal types.

There are two variants on extended types.  First, a new type
designator (a single character) may be added as an alias for an
existing type.  All of the internal processing of the existing
type will be applicable to the new type.  An aliased type may
have three attributes different from its model type, the prefix used
to display the item in the main menu listing,  a short description used
by the "info" display, and whether its data is to be fetched in
binary or ascii mode.

A second variant allows you to specify different processing.  You
provide a command to be executed (e.g., an image display program,
PostScript previewer, etc.) and optionally a few hints on how you
would like the command to be executed.  Any data file will be fetched
by Xgopher and passed to this command.

Extended types must all be named at once on a resource of the form:

	Xgopher.extendedTypes:	g4P

This tells Xgopher that there will be 3 new types ('g', '4', and 'P').
Other resources use the name "type_" to describe the attributes of each
type, where the final '_' is replaced by the type letter.  In this example,
we will define type 'g' as a gif image file (similar to type 'I'); type
4 as a Mac binhex file (a standard gopher type that Xgopher has no
internal processing for); and type 'P' as a PostScript file.  The first
type of extended type is described by "sameAs" resource.  For example:

	Xgopher.typeg.sameAs:	I

and optionally any of the following:

	Xgopher.typeg.prefix:		<gif>
	Xgopher.typeg.description:	gif image file
	Xgopher.typeg.dataType:		binary

The second form of extended type may use the above three resources,
plus one more required:

	Xgopher.typeP.execCommand:	ghostview %f

(The "%f" syntax is described below.)

If the sameAs resource defines an extended type in terms of another
extended type, then the execCommand may also be used to modify a
sameAs alias.

If the dataType is "none" then no data is read from the network
to initiate the command.  An example of this is a telnet session,
for which all the needed information is contained in the gopher item
itself, and no additional data is supplied by the server.  If the 
dataType is some other value, then the data is normally copied to
a temporary file (in either ascii or binary mode), and this file
name is passed as a parameter to the execCommand.  If the first
character of execCommand is a '|' (the Unix pipe character), then
instead of opening the temporary file, a socket connection is opened
to receive the data and this socket is piped to the execCommand
through its stdin file descriptor.  (The '|' is removed before the
command is executed.)  The pipe character inhibits creation of a
temporary file.  Note that only binary data can be used properly in
this way since Xgopher does not get a chance to interpret the data
and convert end-of-lines properly.

In the examples below, note that the resource "extendedTypes" must
include all extended types at once, in a single string of characters.
So, to use two or more of these examples, you must combine the
extendedTypes resources from each.

Caution:  Extended types are new in Xgopher.1.3.  There is one known
	  deficiency in the implementation.  Without re-implementing
	  a large part of the Unix shell (e.g., sh or csh) it is
	  difficult to properly manage child processes.  I have tried
	  to handle processes reasonable, but I am open to suggestions
	  for improvement.  This support tries to deal properly recognize
	  the termination of forked processes (e.g., xloadimage,
	  sounds, etc.); but as each of these commands may fork
	  additional processes, there are times when the logic for
	  "wait" may be defeated.  There are also times when
	  "<defunct>" (zombie) processes may be left around (shown by
	  a "ps -aux" command).

	  Also note that because many processes fork other children
	  it is not possible to implement a type and restrict Xgopher
	  to only one concurrent instance of that type.  This is 
	  implemented for the internal support for sounds, but is
	  not undefeatable.  


======================================================================
Aliases for types
======================================================================
Examples of how to use type aliases with extended types.

1. If you find .gif (image) files in gopherspace having both type
   'I' and type 'g' designations, you can alias type 'g' to the 
   built-in type 'I':

     Xgopher.extendedTypes:	g
     Xgopher.typeg.sameAs:	I

  Processing of type 'g' will be identical to type 'I'.  However, you
  can have them identified with a different prefix in the menu list
  by adding, for example:

    Xgopher.typeg.prefix:	<gif>

2. Extended types may be aliased to previously defined extended types.
   The order of definition is uniquely defined by the "extendedTypes"
   resource:

     Xgopher.extendedTypes:	gG
     Xgopher.typeg.sameAs:	I
     Xgopher.typeG.sameAs:	g
     Xgopher.typeg.prefix:	<gif>


======================================================================
New types
======================================================================
Examples of how to define new types to Xgopher with behavior different
from an existing type.

1. MacIntosh BinHex files are a standard Gopher type not previously
   supported by Xgopher.  This type is now supported using extended types.
   The following are defined in the distributed version of the Xgopher
    resources file as an extended type as follows.  Note that type '9'
     is the built-in type 'binary file'.

     Xgopher.extendedTypes:	4
     Xgopher.type4.sameAs:	9
     Xgopher.type4.dataType:	ascii
     Xgopher.type4.prefix:	<Mac>
     Xgopher.type4.description:	MacIntosh BinHex file

2. If you store PostScript documents as type 'P' and have the
   ghostScript and/or ghostView programs installed on your system:

     Xgopher.extendedTypes:	P
     Xgopher.typeP.execCommand:	ghostview %f
     Xgopher.typeP.dataType:	ascii

   The "%f" syntax is described below.

At the University of Illinois, we have tried two experimental types
successfully.

3. Files of kanji text (e.g., from the Japanese newsgroups) can be
   stored in the gopher server as type 'j', then Xgopher can use
   the widely available X client kterm (kanji-xterm) to display them:

     Xgopher.typej.prefix:           <kan>
     Xgopher.typej.description:      Kanji text file
     Xgopher.typej.dataType:         ascii
     Xgopher.typej.execCommand:      kterm -sb -e more %f /dev/tty
     ! or, use the following if the files will fit the scroll buffer of kterm:
     !    Xgopher.typej.execCommand:    kterm -sb -e cat -u %f -

4. Our campus NovaNET system (previously PLATO) has a nice program
   already available to show community bus routes, schedules, and maps.
   It would be difficult for us to duplicate this program or data.  The
   program "portal" is an X-window system gateway to the NovaNet system.
   The signon information that leaps directly to this program is given
   in the gopher item's selector string.

     Xgopher.typeM.prefix:           <MTD>
     Xgopher.typeM.description:      MTD bus schedule program
     Xgopher.typeM.dataType:         None
     Xgopher.typeM.execCommand:      /home/tuchman/src/xp/portal %s


======================================================================
Override default type processing
======================================================================
Examples of how you may want to override the default processing
of Gopher types using extended types to customize Xgopher:

1. For text files, you can use your favorite text editor to display
   and read the file rather than the built-in text window:

     Xgopher.extendedTypes:	0
     Xgopher.type0.execCommand:	xterm -e vi %f

2. For binary files: if you retrieve primarily Unix .tar.Z files,
   you can have them uncompressed and untarred during the fetch:

     Xgopher.extendedTypes:	9
     Xgopher.type9.execCommand:	zcat %f | tar -xf -

   Of course, you should be careful to note which directory you
   are untarring to.

3. A PostScript file described as a type 'I' (image) may not be properly
   fetched by Xgopher.  This is because images are fetched in binary
   mode, whereas PostScript files are ascii.  This usually doesn't
   cause problems across similar (Unix) platforms.  But, non-ascii
   or non-Unix systems may mess up the end-of-line characters.  If this
   is the case, you can override processing for all type 'I' files in 
   a couple of ways:

     Xgopher.extendedTypes:	I
     Xgopher.dataType:		ascii
     Xgopher.execCommand:	imagescript %f

   Another way is to use a temporary "dummy" type.  The advantage of 
   this method is that it totally preserves the internal handling
   of the image type.

     Xgopher.extendedTypes:	xI
     Xgopher.typex.sameAs:	I
     Xgopher.typex.dataType:	ascii
     Xgopher.typeI.sameAs:	x


======================================================================
Description of resources (similar to man page entry)
======================================================================
These are the description of the extended type attributes taken
from the Xgopher man page.

extendedTypes (class extendedTypes)
       A list of individual characters which represent additional gopher
       types to be processed by Xgopher.  All internal types can be
       overridden by an extended type except directories and index
       directories (types 1 and 7).  The types are processed and
       introduced to Xgopher in the order they are listed in this string.
       The supplied default is none.  The following are sub-resources,
       each qualified by a name composed of the new extended type
       character.  If X is an extended type, then each of the following
       resources is fully qualified as Xgopher.typeX._____.

sameAs (class SameAs)
       The letter identifier of an internal type or previously defined
       external type.  This provides an alias saying that this new type is
       the same as some other type.  However, the description, prefix,
       servers, and dataType may be different for this type.  The supplied
       default is none.

description (class Description)
       A short string used in the info popup and status messages
       describing the type of this item.  Typical names are "image file",
       "index search", etc.  The supplied default is "type X item", where
       X is the extended type letter.

prefix (class Prefix)
       A menu display prefix string for items of this type.  The
       supplied default is "< X >", where X is the extended type letter.

servers (class Servers)
       The gopher servers that can supply this item type.  See
       "textServers" in the man page for more information.  The supplied
       default is none.

dataType (class DataType)
       The type of data the gopher server will provide for this type.
       The values are None, Ascii, or Binary.  None says that no
       additional data is provided, the execCommand is usually sufficient
       (an example is the telnet item type).  Ascii or Binary determine
       the translations of the data received.  Text type files should be
       specified as Ascii, image, sound, and similar data should be Binary.
       The supplied default is None.

execCommand (class ExecCommand)
       The command to execute for processing this gopher item.
       Substitutions are made in this string in a manner similar to a
       C printf call.  A percent sign signals the start of a replacement.
       The values used are taken verbatim from the gopher item.  The
       following replacements are performed:

           %h        hostname string
           %p        port number
           %s        selector (path) string
           %n        name (menu name) string
           %f        filename of the temp file string
           %P        if port number is 0 or 23, then blank, otherwise
		     the port number.  A hack for telnet sessions.
           %%        percent sign

	If any other character follows the percent, then no special
	substitution is performed.  The supplied default is None.

wait (class Wait)
       If true, then the entire Xgopher application will await the
       completion of this process before continuing.  If the execCommand
       itself forks another process, the wait may be easily deceived.
       The supplied default is True.


======================================================================
Implementing the standard gopher types using extended types
======================================================================

The following resources will redefine the standard behavior of all
the types defined in the gopher protocol except the directory and
index directory type.  Each is defined with a reasonable behavior
similar to its default behavior.  This is not the recommended way
to run Xgopher, but serves to illustrate and test the capabilities
of extended types.

    !  --- define list of extended types.  Note that '9' must come
    !      early in the list, since many others are defined in terms
    !      of this file type.
    Xgopher.extendedTypes:	9024568sTIg

    !  --- use the vi editor in an xterm to view text files
    Xgopher.type0.prefix:	/txt/
    Xgopher.type0.description:	text file
    Xgopher.type0.dataType:	Ascii
    Xgopher.type0.execCommand:	xterm -n "%n" -T "%n" -e vi %f

    !  --- Binary data is just copied to a file.  It is hard to
    !      ensure a valid file name, so just use the temp file
    !      name, but in our home directory.
    !      To really do this right, we would create a shell script
    !      which prompted for the new file name, and invoke the
    !      script via execCommand.  But the following will suffice
    !      for illustration.
    Xgopher.type9.prefix:	/bin/
    Xgopher.type9.description:	binary file
    Xgopher.type9.dataType:	binary
    Xgopher.type9.execCommand:	cat %f > ~/`basename %f`

    !  --- use the CSO ph client program to do CSO name server requests
    Xgopher.type2.prefix:	/cso/
    Xgopher.type2.description:	CSO name server
    Xgopher.type2.dataType:	None
    Xgopher.type2.execCommand:	xterm -e ph -s %h -p %p

    !  --- Mac binhex is like a type 9 (binary), except ascii
    Xgopher.type4.sameAs:	9
    Xgopher.type4.prefix:	/mac/
    Xgopher.type4.description:	MacIntosh BinHex file
    Xgopher.type4.dataType:	Ascii

    !  --- DOS binary is like a type 9 (binary)
    Xgopher.type5.sameAs:	9
    Xgopher.type5.prefix:	/dos/
    Xgopher.type5.description:	DOS binary file

    !  --- Unix uuencoded is like a type 9 (binary)
    Xgopher.type6.sameAs:	9
    Xgopher.type6.prefix:	/uu /
    Xgopher.type6.description:	Unix uuencoded file

    !  --- invoke telnet
    Xgopher.type8.prefix:	/tel/
    Xgopher.type8.description:	telnet session
    Xgopher.type8.dataType:	None
    Xgopher.type8.execCommand:	xterm -n "telnet" -title "%h" -e telnet %h %P &

    !  --- invoke tn3270 in an Xterm
    Xgopher.typeT.prefix:	/tn3/
    Xgopher.typeT.description:	tn3270 session
    Xgopher.typeT.dataType:	None
    Xgopher.typeT.execCommand:	xterm -n "tn3270" -title "%h" -e tn3270 %h %P &

    !  --- use xloadimage to view an image file
    Xgopher.typeI.prefix:	/img/
    Xgopher.typeI.description:	image file
    Xgopher.typeI.execCommand:	xloadimage -quiet %f

    !  --- define type 'g' (gif file) the same as type 'I' since xloadimage
    !      works fine for gif files.
    Xgopher.typeg.sameAs:	I
    Xgopher.typeg.prefix:	/gif/
    Xgopher.typeg.description:	gif image file

    !  --- Sound files go to /dev/audio on a Sun Sparc.  They're big, so
    !      use a pipe directly from the network instead of a temp file.
    Xgopher.types.prefix:	/snd/
    Xgopher.types.description:	sound file
    Xgopher.types.execCommand:	|cat > /dev/audio


======================================================================
Acknowledgement
======================================================================

The notion of extended types was first proposed by Claude Lecommandeur
(lecom@sic.epfl.ch) of Ecole Polytechnique Federale de Lausanne.
He submitted an "unofficial patch" to Xgopher including an implementation
of extended types.  His work was used as a prototype for this code.

