		Implementation Notes
		       on the
		    Xgopher client


These notes describe Xgopher version 1.2, completed in November 1992.
The implementor and author of these notes can be contacted at:

	Allan Tuchman
	Computing and Communications Services Office (CCSO)
	University of Illinois at Urbana-Champaign
	1304 W. Springfield Ave.
	Urbana, Illinois   61801
	USA

	(217) 244-0048
	a-tuchman@uiuc.edu


Source Organization
-------------------
The xgopher source files are organized by function.  They are:

    xgopher.c - main program, initialize X, set up initial request.
    item.c    - manage the data fields for gopher items
    itemList.c- create and manage the data structures for gopher items
    dir.c     - manage the data fields for gopher directories
    dirList.c - create and manage the data structures for gopher directories
    markList.c- create and manage the bookmark list of gopher items
    util.c    - does gopher processing, get and process gopher requests
    ioutil.c  - copying files and other Input/Output utilities
    misc.c    - misc things like time functions that may be host dependent
    net.c     - open, read, and write from a network connection
    help.c    - manage help file data.
    bkmkfile.c- manage bookmark file load and save
    itemInfo.c- obtain info about a gopher item or directory

   ------  No file above here has any connection to the X window system -----

    gui.c     - interface between the previous files and X functions
    resources.c- retrieve application resources
    cso.c     - create, manage, and process requests for CSO name servers
    index.c   - create and manage panel to get keywords for index searches
    panel.c   - create and manage the main xgopher panel
    error.c   - create and manage the error pop up
    save.c    - create and manage the file save pop up and functions
    options.c - create and manage the pop up for changing run-time options
    single.c  - create and manage the pop up for entering a special item
    text.c    - create and manage the text display pop ups
    version.c - create and manage the version information pop up
    KeyWSink.c- subclass of AsciiSink widget that can highlight
		selected keywords

The include files are used to provide functions definitions, 
configuration options, data structure declarations, share data,
and define bitmaps.  They are:

    conf.h       - configuration parameters
    gopher.h     - data structure definitions for items and directories
    resources.h  - the definition of the application resources structure
    appres.h     - the global definition of the app. resources structure
    globals.h    - a couple of variables, symbolic constants, and macros
    oneLine.h    - text widget translations to enable single line edit mode
    osdep.h      - attempt to isolate some OS dependencies for include files.
    version.h    - Xgopher version info and display text
    xglobals.h   - shared values defined in the X files
    listP.h      - resources used only in {mark,dir)List.c (from resources.c)
    prefixP.h    - resources used only in util.c (provided by options.c)
    pandl.h      - public header file and macros for panel.c
    compatR4.h   - X11R4 compatibility macros
    KeyWSink.h   - public header file for KeyWSink widget
    KeyWSinkP.h  - private header file for KeyWSink widget
    bitmaps/*    - contains bitmaps and icons.

    item.h, itemList.c, dir.h, dirList.h, markList.h,
    gui.h, misc.h,  net.h,  util.h, help.h,  cso.h, index.h, error.h,
    bkmkfile.h, itemInfo.h, options.h, single.h, ioutil.h
                 - function declaration headers

Other files:

    Imakefile      - used to generate a Makefile
    Makefile.NoNo  - A LAST RESORT sample Makefile for those without Imake
    README         - documentation file - SHOULD READ BEFORE INSTALLATION
    RELEASE_NOTES  - documentation file - describes changes/features of this
		     version of Xgopher.
    IMPL_NOTES     - documentation file interesting to the programmer
    xgopher.help   - a sample help file
    xgopher.man    - a Unix manual page for xgopher
    Xgopher.ad     - the applications defaults file.  It MUST be used!
    Xgopher-color.ad - applications color resources file.
    Xgopher-complete.ad - combination of the above two files.
    OW3-site.def   - a configuration file used for compiling with Sun's
		     OpenWindows, release 3.
    OW3-xmkmf.patch- an optional fix to Sun's OpenWindows xmkmf program.


I have tried to keep major operating system dependencies all in the
file misc.c and osdep.h. Different versions of Unix may have slightly
different programming requirements.  These slight variations are handled
through preprocessor directives in the appropriate source files.


Resource Usage
--------------

I have made considerable effort to maintain and reuse every resource
allocated.  Memory for major data structures is never freed back to the
system, but structures that are no longer in use are maintained and reused
again later.  The idea is that it is expensive to get and build
things, but cheap to reuse them.  This philosophy applies to
  . gopher items (the lines you see on the screen and their selector
    information).
  . gopher directories
  . X window text popups
  . Other popups, panels, and help data.
  . Lists created and used to display the X directory and bookmark
    contents lists.


Positioning Popup Windows
-------------------------

Everyone has there own preferences as to where popups should appear.
There are good arguments for having them 1) near the cursor, 2) a
constant position on the main application window, and 3) a constant
location on the screen.

If you want to change popup positions, here's how to do it in the
source program.  Future versions of Xgopher may allow such
preferences in the application defaults file.

Text (and help) displays are not transient windows, and I leave their
placement to the window manager and the user's window manager preferences.
For all transient windows I place them with a single, pretty general
function call.  The call 

    positionPopup(w, from, fromWidget, x, y, hJust, vJust);

is used just before poping-up widget w.  If one wants to change
the pop-up location or policy for a specific widget, one need
only change the parameters to this procedure.  The rest or the
parameters are:

    from  takes it value from the set of symbolic constants:
	  { POS_none, POS_pointer, POS_appPanel, POS_screen }, which
	  do respectively,  no positioning, position at the pointer
	  location, position relative to an application window, or 
	  position relative to the screen.
    
    fromWidget
	  For from=POS_appPanel, this is the widget (window) to position on.
    
    x, y  provide a location in percent across the application window
	  or screen (depending on from).  For example, x=50, y=50
	  represents the center of either the window or the screen.
	
    hJust, vJust
	  are horizontal and vertical justification requirements.  For
	  hJust = 0 the left edge of the popup is positioned at x;
	  hJust = 1 the center of the popup is positioned at x;
	  hJust = 2 the right edge of the popup is positioned at x.
	  The same is true for vJust, using top, middle, and bottom
	  against y.

	  These justifications do not take into account the size of
	  the window manager decorations, but they're close enough
	  anyway to be pretty useful.

After positioning, positionPopup forces the complete popup to lie
on screen by "shoving" it, if necessary, just enough to get it fully
on the display.


Hacker's Corner
---------------

Using the "Enter Gopher Item" menu item and selecting a directory
but using type=0 (text file), you can capture a raw gopher directory
response into a text file.  I find this useful for debugging and
for documentation.  You can also set type=9 to copy any file in
binary mode.


Differences from Previous Versions of Xgopher
---------------------------------------------

The earliest released versions of Xgopher (Xgopher 1.0, 1.1, and 1.1a)
maintained a notion of a dynamic n-ary tree that the user traversed
through gopher space.  Along with this tree, was the notion of a bookmark
being a "place", and internal node in this tree.  The main gopher data
structures were maintained by the routines in the file list.c.

For better or worse, the Unix curses client defined peoples expectations 
of bookmark behavior, and indeed, the way gopher space was presented.
As such, the entire basic data structure has been changed at Xgopher 1.2.
The n-ary tree has been replaced with a directory stack.  Most important,
bookmarks are no longer places (directories), but things (items).  Of
course, an item may be a directory.  The file list.c has been replaced
with 5 smaller files (item.c, itemList.c, dir.c, dirList.c, markList.c).


Gopher Directory Data Structure
-------------------------------

=== This section is totally changed for Xgopher 1.2 ===

The gopher directories are maintained in a stack.  The stack is
implemented as modified last-in-first-out (LIFO) data structure.
The modification is that a "pop" operation decrements the top-of-stack
pointer as usual, but the previous top-of-stack item is not yet freed
or removed from the stack.  This occurs when the next "push" operation
occurs.  This allows the stack to be traversed backward, then forward
again (even though the forward traversal is not normal stack behavior).
Strange? Perhaps; but it doesn't cost anything to do it this way, and
it allows one to recover easily from a mistaken "go-back" type of command.
It is also cheaper for the user, since the contents of the directories
are maintained (not refetched) as long as they are maintained in the
stack.

The stack, then, may look like this:

 firstDir                              currentDir--+
   |                                               |
   |                                               V
   |  +-----+------+           +-----+------+   +-----+------+   +-----+------+
   +->| dir | next+|--> ... -->| dir | next+|-->| dir | next+|-->| dir | NULL |
      |  1  |      |           | N-2 |      |   | N-1 |      |   |  N  |      |
      +-----+------+           +-----+------+   +-----+------+   +-----+------+

currentDir normally would point as the last directory in the list.
In the diagram above, the user has selected the "previous directory"
function to return one level back.

If the user now selects anything except "move forward" (NOT A FUNCTION
DEFINED BY DEFAULT), then this new selection will replace directory N
and all of its successors.  Each directory from N on is released.

Once a directory is released, the directory data structure
is removed from the stack and moved back to a "free list".

Gopher items are saved (cached) with the directory until either the
directory is released or they become stale.  A time field in the directory
structure identifies the time that the directory contents were
last fetched.  Whenever the contents are needed, the time is
checked, and if some user-specified threshold of elapsed time
is exceeded, then the directory contents are freed and re-requested
from the server.


	Directory Node structure (gopherDir)

                                   gopherItem
        			        .
        			       / \
        			        |
        			        |
        	   +----------+--------------+------+
      gopherDir <--|+previous | selectorItem | next+|----> gopherDir
        	   +----------+--------------+------+
        	   | created  | contents            |
        	   +----------+---------------------+
        	                        |
        	                        |
        			       \ /                
        			        .
                                 gopherItemList


A gopherItemList is simply a first/last pointer structure:

	  +--------+
	  | first +|---> gopherItem
	  +--------+
	  | last  +|---> gopherItem
	  +--------+

And the gopherItem structure is:

	  +------+------+------+------+
	  | type | name | path | next+|--->
	  +------+------+------+------+
	  | host | port | plus        |
	  +------+------+-------------+


Button Sensitivity
------------------

The buttons are set sensitive according to the following conditions

 . Fetch:	if ANYTHING selected
 . Copy:	if ANYTHING selected
 . Previous:	if previousDir != NULL
 . RemoveMark:	if ANY MARK selected
 . RemoveAllMarks:	if markListLen != 0
 . LoadMarks:	if BookmarkFile != NULL and != empty string
 . SaveMarks:	if BookmarkFile != NULL and != empty string and
                   allowBookmarkSave and markListLen != 0
 . Info:	if ANYTHING selected ==> label = "info on item"
                else if currentDir exists ==> label = "info on directory"
 . Mark:	if ANY NON-MARK selected ==> label = "mark item"
                else if currentDir exists ==> label = "mark directory"


Widget Tree
-----------

If you want to better customize some of the widgets or perhaps modify
Xgopher, a widget tree is helpful.  This one isn't beautiful, but
it was up to date as of the release of Xgopher 1.2.
Each line contains first the widget class, then the instance name.
Indentation shows the parent-child relationships.


Xgopher  xgopher
	Paned  gopherPanel
		Form  statusForm
			Command  quit
			MenuButton  other
				SimpleMenu  otherActionsMenu
					SmeBSB  copy
					SmeBSB  unmarkAll
					SmeBSB  loadMarks
					SmeBSB  saveMarks
					SmeBSB  options
					SmeBSB  oneItem
					SmeBSB  version
					SmeBSB  restart
			Command  help
			Label  status
		Form  directoryForm
			Label  directoryTitle
			Viewport  directoryView
				Core  clip
				Scrollbar  vertical
				List  directory
		Box  goBox
			Command  fetch
			Command  info
			Command  up
			Simple  spacer
			Command  mark
			Command  unmark
		Form  bookmarkForm
			Label  bookmarkTitle
			Viewport  bookmarkView
				Core  clip
				Scrollbar  vertical
				List  bookmark
		Grip  grip
		Grip  grip
	TransientShell  errorDialogShell
		Dialog  errorDialog
			Label  icon
			Label  label
			Command  ok
	TransientShell  optionsPanel
		Form  optionsForm
			Box  buttonBox
				Command  done
				Command  cancel
				Command  help
			Form  itemsForm
				Box  showAllBox
					Toggle  showAll
					Label  showAllLabel
				Box  appendBkBox
					Toggle  appendBk
					Label  appendBkLabel
				Box  loadBkBox
					Toggle  loadBk
					Label  loadBkLabel
				Box  resetBox
					Toggle  reset
					Label  resetLabel
				Form  bkSaveForm
					Label  bkSaveLabel
					Text  bkSave
				Form  printCmdForm
					Label  printCmdLabel
					Text  printCmd
				Form  imageCmdForm
					Label  imageCmdLabel
					Text  imageCmd
				Form  telCmdForm
					Label  telCmdLabel
					Text  telCmd
				Form  t3270CmdForm
					Label  t3270CmdLabel
					Text  t3270Cmd
	TransientShell  singlePanel
		Form  singleForm
			Box  buttonBox
				Command  done
				Command  cancel
				Command  mark
				Command  help
			Form  itemsForm
				Form  giTypeForm
					Label  giTypeLabel
					Text  giType
				Form  giNameForm
					Label  giNameLabel
					Text  giName
				Form  giPathForm
					Label  giPathLabel
					Text  giPath
				Form  giHostForm
					Label  giHostLabel
					Text  giHost
				Form  giPortForm
					Label  giPortLabel
					Text  giPort
	TransientShell  infoDialogShell
		Dialog  infoDialog
			Label  icon
			Label  label
			Command  ok
	TopLevelShell  csoShell
		Form  csoForm
			Label  nameServer
			Command  csoDone
			Command  csoHelp
			SimpleMenu  csoFieldsMenu
				SmeBSB  Default
				SmeBSB  Lookup
				SmeBSB  Indexed
				SmeBSB  Public
			MenuButton  csoFields
			Label  csoQueryLabel
			Text  csoQueryText
			Command  csoDoQuery
			Command  csoClearQuery
			Command  csoClearText
			Text  csoText
	TopLevelShell  indexShell
		Form  indexForm
			Label  indexLabel
			Command  indexDoIndex
			Command  indexCancel
			Command  indexHelp
			Text  indexQueryText
	TransientShell  saveDialogShell
		Dialog  saveDialog
			Label  label
			Text  value
			Command  ok
			Command  cancel

Special thanks
------------------

I want to thank everyone who took the time to send me comments, suggestions,
and constructive criticism on previous versions of Xgopher.
Much of the Xgopher 1.2 change was motivated by this feedback.

I especially want to thank Dawn Endico for finding the Sun
OpenWindows patches.  And a big thanks to Prentiss Riddle and
Richard A. Schafer of Rice University for commenting on an early
version of Xgopher 1.2.  Once again, John Franks of Northwestern
University has done a great job of testing - thanks, John!

I also borrowed some of the bookmark saving code from the
Unix curses client, written by Paul Lindner (I think) at UMN.

Of course, the present author assumes responsibility for any
problems introduced.
