Further enhancments to XFM

    Copyright (C) 1997 by T. Straumann, <strauman@sun6hft.ee.tu-berlin.de>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


1. Introduction
===============

Xfm is a cool tool. I found, however, that several features were missing; that's
why I'd like to present an enhanced version of XFM. This version provides the
following improvements:

 - path history; a menu offering the paths already visited.
 - modification & display of _all_ file modes (up to now suid was not
   even displayed);
 - translations were moved to resource files, so the user can modify them.
 - after updating the file window it is attempted to scroll the window to its
   previous position. (For me it was _very_ annoying to be thrown back to the
   start of the view every single time after touching something in the directory.) 
 - New widgets for the Icon- and Text-  view modes. This is many, MANY times
   faster than the old version. Ok, still the whole directory has to be 'stat'ed,
   but creation of all the Toggle widgets in a big directory (ever visited
   ghostscript's source dir for example?) took en eternity and I don't want
   to have coffee every time I do a chdir.
   The new widgets provide also a 'notify()' action and a callback resource.
   This allows XFM to provide additional functionability. Currently this feature
   is used to let the user delete/move/link/copy/select etc. the items with
   the keyboard.
 - More info fields in the 'text view' mode (device type, group info etc). An
   'options' menu was added to switch individual fields on and of.

Besides this there are some minor changes:
 - some bugs fixed;
 - XFM starts up in the cwd and not always in HOME. (It's easy to move home
   anyway and often I need an XFM in the cwd of some shell).
 - If you give a shell path in the app_res file, it will be _really_ the shell
   used by XFM. XFM will try the shell given in the 'shellCommand' resource.
   If no executable is found the environment variable
   SHELL is examinated and finally "/bin/sh". This scheme gives the user more
   freedom than the old one when SHELL was always used.
   The meaning of the 'BourneShells' resource as a hint for XFM about
   the calling semantics remains the same however.
   Personally I want to use 'csh' when I'm working in a 'xterm' but I want XFM
   to use 'bash'. This can now simply achieved by a modification of the
   resource file; before I always had to set SHELL or to use a script.
 - The cursor is set to the 'noentry cursor' if you try to drag something to the
   file window of a non-writable directory.
 - The 'folder' menu provides two additional entries to 'close' or 'clone' the
   actual file window.
 - Accelerators are installed in dialog boxes and the 'confirm' popup.
   By the 'accelerators' resource eg. the <Return> key can be mapped
   to emulate clicking the 'ok' button.
 - A 'TextField' widget is provided as a replacement for the 'Text' widget
   offering 3D look in dialog boxes. Scrolling without need of scrollbars
   is supported by this widget (useful for long input when editing application
   properties in the application manager.)
 - Some servers can't handle big cursors. My MIT Xsun (X11R6) server isn't
   capable of dealing with cursors bigger than 32x32. That's why I use a
   smaller cursor for the 'noentry' cursor (32x32, like all other special
   cursors; I don't know why this one 's so big anyway).
   New code queries the server for the cursor size and uses extra small
   cursors (16x16, every server should be able to handle this) if the
   server denies using 32x32.
 - A simple ICCM has been implemented; it is possible to paste the paths
   of the selected file items (as strings) to other applications using
   the XA_PRIMARY selection.
 - A logging window has been added to show output of child processes sent
   to stdout / stderr. If any output is generated by children of XFM
   (eg. applications started by the am) the log window pops up.
 - The new 3dicons contributed by Albert Graef look very nice -- they
   are quite hungry however and eat up an 8-bit colormap quickly. Xpm
   however is capable of dealing with such situations, allocating close
   colors instead of exact matching colors. In most cases this doesn't 
   really matter and you won't see the difference but the colormap is
   used in a much more economical way.
   A new resource 'colorCloseness' has been added which can be set to
   specify the matching tolerance (the old XFM asked always for an
   _exact_ match :-( ).


2. Configurable Enhancements
============================

All the enhancements except the support for the new 'iconFileList' and 
'textFileList' widgets can be configured by defining preprocessor flags
in the file 'Imake.options'. These flags will now be described in detail.

-DENHANCE_TXT_FIELD
-------------------

This flag substitutes the Athena 'Text' widget for my 'TextField' widget.
This Widget is an input area for single line text strings providing
3D look. If not the whole string can be displayed, small scroll marks
appear where the text gets obscured. Clicking on these scroll marks
moves the text cursor, which can also be moved by the <Left>/<Right> keys.
Many actions are provided in order to insert, delete text, to move the
cursor etc.
Communication with other clients is possible using standard selections
(Primary, Secondary or Clipboard).
A readOnly mode disables string modification while still supporting 
selection and scrolling.
Further Information is given in the header file 'TextField.h' (This
widget was not specifically designed for XFM but as an all purpose
single line input area.)

Together with the 'TextField' widget comes the 'FocusForm' widget.
The 'FocusForm' is a subclass of Form which is capable of managing
Keyboard Traversal provided the Translations of its children are
set up accordingly.

The FocusForm allows you to type text into the child (eg. TextField)
which has the Keyboard focus with the pointer anywhere in the FocusForm.
The focus can be changed by clicking into another field or using the
<Tab> or <Shift><Tab> keys.

-DENHANCE_POP_ACCEL
-------------------

Install accelerators on the text and form widgets of dialog boxes. Accelerators
are also installed on the form widget of the 'confirm popup'. This allows
to emulate clicking buttons by keys. An appropriate entry in the resource file
is necessary:

 Xfm*button box*ok.accelerators:#override\n\
	<Key>Return: set() notify() unset()\n\
	<Key>Linefeed: set() notify() unset()\n\

 Xfm*button box*cancel.accelerators:#override\n\
	<Key>Escape: set() notify() unset()\n\

Likewise, if you want to use the accelerators in the 'edit' popup
of the application manager and the 'select' popup entries in
the resource database are required:

 Xfm*button box*install.accelerators:#override\n\
	<Key>Return: set() notify() unset()\n\
	<Key>Linefeed: set() notify() unset()\n\

 Xfm*button box*replace.accelerators:#override\n\
	<Key>Return: set() notify() unset()\n\
	<Key>Linefeed: set() notify() unset()\n\

-DENHANCE_BUGFIX
----------------

Fix some bugs (see comments in the source)

-DENHANCE_HISTORY
-----------------

Provide a history of the visited paths. A menu can be popped up providing
an mru ordered list of paths. The module 'FmHistory.c' provides procedures
to create, destroy or chop a history list menu to a determined length.
Paths can be deleted from the list or inserted on top. (see 'FmHistory.h')
The module adds an action 'FmUpdateHistory()' to the application.

Currently only one history that is common to all file windows is used (although
the module supports more than one).

Default translations pop the history up if the mouse button 3 is pressed
on the label widget showing the actual path on top of the file window.
(The default translation can of course be changed)

As an additional feature the history can be popped up on the text input
field in dialog boxes in order to paste a path there (only supported if
-DENHANCE_TXT_FIELD). This is very practical when moving or copying files.

An application resource 'historyMaxN' has been added to specify the
maximal number of paths remembered (defaults to 30). A value of 0 lets
the list grow without limit.

-DENHANCE_USERINFO
------------------
Some modifications regarding the 'userinfo' structure:

 - The filemanager is not started in $HOME, but in the cwd. I'm often
   working somewhere with xterm and want an XFM to startup where I am.
 
 - The shell to be used by XFM is first read from the app_resource
   'shellCommand', then from $SHELL and if neither works,
   "/bin/sh" is used (see above).

-DENHANCE_MENU
--------------
Small modification of the Folder-menu (see above)

-DENHANCE_TRANSLATIONS
----------------------
The translations were moved to a resource file (as 'baseTranslations').
That way the user can modify them in a personal resource file.  User
configurability is why Xt is cool, so why restrict him/her?
No fallback resources are set for the translations. By means of a new
application resource 'appDefsVersion' (set to version number XFMVERSION
in the app-defaults file) a check is made, if the right app_defaults file was found.
In case of failure an error popup is shown and the program is terminated.

The new subclasses of the fileList widget allow the user to map (e.g. key-)
events to callbacks which are registered with arbitrary menu entries of
the file window. See 'fileListCb()' below.

-DENHANCE_PERMS
---------------
I was shocked, when I realized that XFM does not even _display_ all the
permissions (especially suid). If you configure -DENHANCE_PERMS the
permissions string shown in the 'text view' looks like what 'ls -l'
yields. Suid etc. can now also be set by the 'permissions' popup.
There were four bitmaps added for this purpose:

  lib/bitmaps/xfm_suid.xbm
  lib/bitmaps/xfm_Suid.xbm
  lib/bitmaps/xfm_sticky.xbm
  lib/bitmaps/xfm_Sticky.xbm

You should be aware that XFM updates its display only if the directory's
inode was changed since the last timeout event. If a file's modes are
changed or if a file pointed to by a symbolic link is deleted the directory's
inode will remain unaffected and hence no update occurs. That's why an
additional application resource was added, called

  hardUpdateTicks

If this resource is not zero, every 'hardUpdateTicks'*'updateInterval'
(eg. hardUpdateTicks=3, updateInterval=10000 -> every 30 secs) the changes
will be determined the hard way ie. by 'stat()'ing the whole directory.

-DENHANCE_SCROLL
----------------
When you delete a file or if you use, for example, an editor that creates a
scratch file when opening an existing file, the directory shown by XFM changes.
XFM will update its display, ie. it destroys the old view and creates a new one.
This means that your actual position of the scrollbars is lost. The new position
will be the top of the scrolled window. This behavior is VERY annoying. ;-(
With -DENHANCE_SCROLL XFM tries to restore the position of the scrollbars after
updating (same directory, same viewing mode). Of course there's no way of 
figuring out the new position if you just deleted, renamed or added a big
number of files at once. In the normal case however this enhancement is
a very nice feature.

-DENHANCE_CURSOR
----------------
A 32x32 bit cursor will be used for the 'noentry' cursor which appears
if the user tries to drop something on a directory without write access.
(The old version used 48x48 bit, which some servers cannot handle).

Code was added to query the server for the allowed cursor size. If
32x32 is still too big, 16x16 cursors will be used.

New bitmap files were added:

 lib/bitmaps/xfm_noentry32.xbm		the 32x32 noentry cursor
 lib/bitmaps/xfm_noentrymsk32.xbm

 lib/bitmaps/xfm_noentry_s.xbm		small 16x16 cursors
 lib/bitmaps/xfm_noentrymsk_s.xbm
 lib/bitmaps/xfm_file_s.xbm
 lib/bitmaps/xfm_filemsk_s.xbm
 lib/bitmaps/xfm_files_s.xbm
 lib/bitmaps/xfm_filesmsk_s.xbm
 lib/bitmaps/xfm_dir_s.xbm
 lib/bitmaps/xfm_dirmsk_s.xbm
 lib/bitmaps/xfm_exec_s.xbm
 lib/bitmaps/xfm_execmsk_s.xbm

-DENHANCE_SELECTION
-------------------
This enhancement provides support for a simple inter client communication.
A string containing the paths of the selected file items can be requested
by other applications using the selection mechanism (PRIMARY selection). 

To provide visual feedback, the file window that owns the selection paints
its status line using the 'highlightColor' (new app. resource which also
defines the color used to highlight selected items).

Another app. resource, 'selectionPathsSeparator', allows for an arbitrary
string to be used as a separator between the individual paths. (Defaults to
a space character).

A new menu entry in the 'file' menu was created which allows for requesting
the ownership of the PRIMARY selection. This is useful if some files had
been selected before but the ownership of the X-selection was lost and the
user later wants to get the ownership back.

-DENHANCE_LOG
-------------
This enhancement adds a logging window feature. Stdout and stderr are
redirected to a new fd which is monitored by Xt. A callback is registered
which stores the redirected data to a text widget. The text is popped up
automatically as soon as new data is pending.
A new entry has been added to the 'view' menu to request popup of the
log window.

The logging feature should maybe not be enabled under an OS which does no
blocking IO (since XFM is only useful under younix anyway, this should be
no problem).

Depending on the state of a toggle widget the log-window is automatically
popped up as soon as new data is logged.

-DENHANCE_CMAP
--------------
A new application Resource, 'colorCloseness' allows you to specify how
close you want the colors to be to the original values. Loading an icon
Xpm tries to use a slightly different color if a corresponding entry in
the colormap exists already. The higher the value, the greater is the
tolerance. A value of 40000 (default) is recommended by the designers of Xpm
and it looks pretty good on my Sun which has 256 colors only and many, 
many slots can be saved.
If XFM is still incapable to load the icons it will try to switch to its
private colormap.

-DVIEWPORT_HACK
---------------
The viewport widget contains several bugs (see the patch file for 'Viewport.c').
If VIEWPORT_HACK is defined workarounds for the known bugs will be activated.

3. New Widgets for the File Window
==================================

3.1 Description of the New Widgets
----------------------------------

3.1.1 The Common Superclass 'FileListWidget'
- - - - - - - - - - - - - - - - - - - - - - 

Traditionally XFM created a toggle widget for each and every file shown
in the file window. When displaying a big directory (eg. ghostscript's source
directory) the time required to create all the widgets becomes prohibitively
long. I would not use XFM anymore only for this reason. That's why I wrote
new widgets implementing the 'icon view' and the 'text view'. Using these
widgets, creating the file display is a LOT faster: on my pentium 133 there's
no perceivable delay anymore (except for stat()'ing the directory of course) 
when creating the file window for the ghostscript directory mentioned above.
The old version took up to several minutes though.

The widgets add several new features and resources that will described below.
Since I didn't want to rewrite XFM from scratch, I had to sacrifice some elegance
of concept. Ideally a new widget should not be aware of the outside world, and
everything should be encapsulated into its module (or some superclass). 

The 'FileListWidgetClass' however imports the definition of the fundamental
data structure FileRec and calls some procedures of the outside world.
 
The FileListWidget (FLW) implements a higher layer of abstraction and is
not used directly. Instead it is subclassed by either the TextFileListWidget (TLW)
or the IconFileListWidget (ILW), which implement the details of either
viewing mode.

The FileListWidget gets its FileList as a resource when it is created.
The FileList can not be changed.

The FLW maintains GCs for drawing and offers the resources

  fileList		Pointer to the FileList; must be set on creation
  nFiles		number of files in the list; must be set on creation
  font	 		Font to draw file names and info
  highlightColor	color used to highlight selected or highlighted files
			the TLW uses this color to draw the file name
  foreground		normal foreground color
  borderWidth		width of the border around selected files.
  userData		pointer to arbitrary user data
  callback		callbacks on this list are invoked by the 'notify(arg)'
			action. A pointer to the argument string is passed in
			the 'call data' parameter.
  dragTimeout		After receiving a ButtonPress event the FLW suppresses
			propagation of Motion events for 'dragTimeout' millisecs.
			in order to distinguish between intended drags and 
			small movements while clicking. This resource defaults
			to 200ms.

For sake of simplicity most of these resources can only be set at creation.

Note that the core resource 'borderWidth' is overlayed. The FLW itself has no
border at all.

When a FLW is created the file type is set using 'fileType()'. There are
default Types defined in 'FmBitmaps.c'. Note again that the principle of
perfect encapsulation is violated for sake of simplicity (use existing
procedures if possible).

Because I wanted also to use the existing actions, the FLW implements its own
action 'dispatchDirExeFile()' which takes at least four arguments.
The old version of XFM used a different widget for every file displayed
in the file window. Hence it was possible to define different translations
for different files. This is not possible with the new FLW. However FLW
determines the file class for which the action dispatchDirExeFile() was invoked
(directory, executable or normal file) and invokes different action procedures
according to the file class. The names of these actions are given as arguments
to dispatchDirExeFile().  The action name given as the fourth argument specifies
a routine to be invoked if the event that triggered 'dispatchDirExeFile()'
ocurred on the background of the FLW, ie. on no specific file item.

It is possible to give more than four arguments to this action.
The exceeding arguments are passed on to the action invoked by dispatchDirExeFile().
As an example consider the translation

 <Button1Up>:dispatchDirExeFile( foo, boo, gnu, blah, arg)

If Button1 is released on a FileListWidget it looks first for the file that
is listed at the event position. If this file is a directory, the action
'foo(arg)' is invoked. If the file is executable 'boo(arg)' is called else
(normal file) 'gnu(arg)'. If the button was released on no item at all,
'blah(arg)' will be called.
Note that there is second version of dispatchDirExeFile(), called
dispatchExeDirFilePopup(). The only difference between the two versions
consists in the latter being registered as a Grab Action. This is necessary
to dispatch actions that popup menus.

The FLW provides a 'notify(arg)' action which calls the callback on its
'callback' list (resource 'XtNcallback'). A pointer to the argument string
is passed in the 'call data' parameter.

The FLW provides public procedures to map a pointer position to a file list
entry and vice versa. These are implemented using methods supplied by the
subclasses of FLW. (The 'text view' provides a different method to compute
the list entry from a pointer position than the 'icon view' but the superclass
FLW does not have to know about these details).
Another public procedure 'FileListRefreshItem()' allows for redrawing one
item in the FLW. The whole visible part can be redrawn by

  XClearArea(display,XtWindow(fileListWidget),0,0,0,0,True).

The old XFM needs <Enter> and <Leave> events in its translation tables of the
widgets of each individual file. Because in the new FLW not every file entry
has its own window anymore, the FLW fakes <Enter> and <Leave> events. It tracks
the pointer motion and generates 'SendEvents' when the pointer moves from
one file entry to another. That way the same actions and translations can
be used as with the old XFM (although the actions have to be dispatched by
dispatchDirExeFile()).

Note that <Enter> and <Leave> events of the FLW itself are eaten up and can not
be used in translation tables. Since in XFM a FLW is usually created as a child
of a viewport widget, these events can be selected eg. on the viewport's clipping
window:

  Xfm*viewport.clip.translations: #override \n\
	<Enter>: do-something()\n\
	<Leave>: do-something-else()\n

3.1.2 The IconFileListWidget
- - - - - - - - - - - - - - -

The IconFileListWidget (ILW) is a subclass of FLW and implements the 'icon view'
mode of the file window. It adds the following resources

  topSep	space between the top/bottom edge of the ILW and the
		first/last row of file icons.
  leftSep	space between the left/right edge of the ILW and the
		first/last column of file icons.
  entrySep	horizontal and vertical space around file entries.
  labelSep	space between the file icons and the file name strings.
  nHoriz	number of columns of file icons. If this number equals to
		zero the number is chosen to fill the available space
		(default).
  minIconWidth  minimal icon width. An icon is never drawn narrower than this.
  minIconHeight minimal icon height. An icon is never drawn smaller than this.

The last two resources are currently set to the application resources
fileIconWidth and fileIconHeight by the procedure that creates the ILW
(backward compatibility to old XFM, see FmFw.c). This does not happen in
the widget code however, I mention this here so nobody should wonder that
resource file settings don't work.

The ILW provides two actions, highlight() and unhighlight() which allow for
highlighting one item (used by XFM to indentify possible drop targets).
Note that the ILW, unlike the old XFM, is only able to highlight _one_ item at
once. (The old XFM however did not highlight more than one item either,
although this would theoretically be possible.)

3.1.3 The TextFileListWidget
- - - - - - - - - - - - - - -
The TextFileListWidget (TLW) is a subclass of FLW and implements the 'text view'
mode of the file window. It adds the following resources

 topSep		 space between the top/bottom edge of the TLW and the
		 first/last row of file icons.
 leftSep	 space between the left/right edge of the TLW and the
		 first/last column of file icons.
 entrySep	 horizontal and vertical space around file entries.
 tabSep		 horizontal space between individual info fields of one
		 file entry.
 showInode	 show the inode nr.
 showType	 show the device type: sym (l)ink, (d)irectory,
		 (c)haracter special, (b)lock special, (p)ipe or (s)ocket.
 showLinks	 show the nr. of links.
 showPermissions show the permissions string.
 showOwner	 show the owner.
 showGroup	 show the group.
 showLength	 show the size of the file.
 showDate	 show the modification time.

Some of the names of these resources were chosen to be compatible with the
old XFM application resources. Additional fields have been added.

The TLW provides two actions, highlight() and unhighlight() which allow for
highlighting one item (used by XFM to indentify possible drop targets).
Note that the TLW, unlike the old XFM, is only able to highlight _one_ item at
once. (The old XFM however did not highlight more than one item either,
although this would theoretically be possible.)

In XFM a TLW is created as a child of a viewport widget. Note that there's a
bug in the viewport GeometryManager that causes the geometry layout of the
child to be calculated wrong if it requests a change of width or height only.
Only if both sizes are changed at the same time the calculation is done better 
(there are still other bugs, alas).
A resize request is issued by TLW when adding or removing information
fields since the width changes. If this happens more than once, 
a horizontal scrollbar will appear although it is not needed.
In case you don't want to patch the Viewport, there has been implemented a
workaround in the TLW which can be activated by compiling the TLW with 
-DVIEWPORT_HACK.

3.2 Mayor Changes to XFM
------------------------
Upon incorporating the new widgets ILW and TLW into XFM some changes had to
be made. The most important changes are stated here. Note that the changes
can NOT be configured by defining preprocessor symbols. The main modifications
are given here:

FmVersion.h:
- a new file containing only the version string XFMVERSION which was
  increased to 1.4.0

Fm.h:
- Added two fields to 'TypeRec', 'bm_width' and 'bm_height'. These are needed
  in order to draw the file pixmaps and not to have to query the server for
  its dimensions.
- Added one field 'option_items' to 'FileWindowRec' (see below).
- Made the procedures 'fileType()' public. (To be used by FLW, arrrgh)
- Added fields for the state of info fields shown by the 'text view' mode.
  This state is preserved when updating or cloning the file window.
- Added public declaration of 'showTxtOptsCb()' (see below).
- Added public declaration of 'destroyTxtOptsCb()' (see below).
- Added public declaration of 'updateTxtOpts()' (see below).
- Added public declaration of 'trackCursor()' (see below).
- Added public default types 'TypeRec builtin_types[]' and symbols as 
  indices into this table.
- Changed the declaration of 'readIcon()' (added function args to read back
  the icon width and height, see below).
- Application resources 'showInode', 'showType', 'showLinks' and
  'showGroup' added. 

FmAw.c, FmAwActions.c, FmAwCb.c: 
- new call args to 'readIcon()' added. These are NULL because the application
  manager does not need pixmap width/height information.

FmBitmaps.c:
- definition of a new public variable 'TypeRec builtin_types[]'. Files whose
  type cannot resolved by fileType() are assigned one of these default types
  in FLW's Initialize method. The default types are 

	DIR_T 	 	(directory)
	UPDIR_T  	('..' dir)
	FILE_T   	('normal' file, default)
	EXEC_T   	(executable)
	SYMLNK_T 	(symlink to file)
	DIRLNK_T 	(symlink to dir)
	EXECLNK_T	(symlink to executable)
	BLACKHOLE_T	(symlink to nothing)

- Default type information is obtained by inspecting the file's stat modes.
  (see FileList.c). The default types are initialized in 'readBitmaps()'.
  In order for this initialization to work correctly the order of the default
  bitmaps DIR_BM .. BLACKHOLE_BM must not be changed.
- 'readIcon(char *name, unsigned int *width, unsigned int *height)': added
  the 'width' and 'height' arguments in order to read the pixmap width and
  height into the new 'TypeRec' fields 'bm_width' and 'bm_height'. These are
  needed to draw the pixmaps by ILW. These pointers can be NULL to indicate
  that the information is not needed (eg. by the application manager).

FmPopup.c:
- 'selectReplaceCb()', 'selectAddCb()', 'selectRemoveCb()': These callback
  procedures among other things set the colors of selected toggle widgets.
  A test was inserted to see whether the widget is a subclass of FLW.
  In this case the color change is omitted, but a redraw of the FLW is
  issued (XClearArea() or FileListRefreshItem if only few items are
  concerned).

FmMain.c:
- The application resources 'showInode', 'showType', 'showGroup' and
  'showLinks' were added. They control the initial settings of fields shown
  by the 'text view'.

FmFwCb.c:
- 'fileSelectAllCb()', 'fileDeselectCb()': see 'FmPopup.c'.
- A public callback procedure 'showTxtOptsCb()' is added. This callback is
  intended to be registered by menu entries of a text view 'options' menu.
  This menu allows for switching individual info fields (eg. 'owner', 'group')
  to be switched on and off interactively.
  The callback propagates changes of the state of 'toggle' type menu entries
  to the corresponding TLW resource settings.
- The list of 'option_items' (new field of FileWindowRec) is released in
  'fileCloseCb()'.

FmFwActions.c:
- Added an 'ev' argument to 
 
   'static int findWidget(Widget w, FileWindowRec **fw_ret, XEvent *ev)'

  The event position is needed by findWidget to be able to retrieve the
  file list entry nr. in a FLW subclass widget. If 'w' is a subclass of
  FLW, findWidget() calls 'FileListFindEntry(w,ev)'.

- All procedures calling findWidget() are modified in order to supply the
  new argument.

- 'drag()' needed some modification, because it contains its own
  event loop. Therefore an argument 'event_return' was added to

   'static Widget drag(Widget w, int button, FileWindowRec *fw,
			Boolean *on_root_return, XEvent *event_return)'

  in order to report back the last event processed by drag() to its calling
  routine (which might call findWidget()).

- The action routines 'fileToggle()' and 'fileSelect()' were modified as
  described above (see FmPopup.c).

- The action procedures 'fileHighlight()', 'fileMaybeHighlight()', 'resetCursor()'
  were modified and a new action, 'trackCursor()' was added.
  The modifications were made to support setting the cursor to 'noentry' when the
  user tries to drag something to the file window ('background') of a directory where
  he/she has no write access.
  The new action 'trackCursor()' is used to set the cursor when entering/leaving the
  file window.

FmFw.c:
- 'trackCursor()' is added to the action table.

- In routine 'readFileBitmaps()', where the default icon pixmap is set,
  the new fields of 'TypeRec', 'bm_width' and 'bm_height' are set
  to the width and height of the default pixmap.

- The routine 'fileType()' has been made public, so it can be used by the
  FLW.

- In 'createFileWindow()' a new menu called 'options' is created.
  The menu allows individual info fields of the 'text view' to be switched on
  and off (eg. permissions, inode nr. etc).
  The menu registers the callback 'showTxtOptsCb()'. Note that the ordering
  of the menu entries is critical and can not be changed without adapting
  the callback routine and 'updateTxtOpts()'.

- Eight boolean fields of 'FileWindowRec' reflect the state of the info fields
  shown by the 'text view'. This state is preserved when the file window is
  updated or cloned. The initial state is read from the application resources
  'showInode', 'showPermissions' etc. The routine 

    'void updateTxtOpts(FileWindowRec *fw)'

  reads the state variables from the FileWindowRec 'fw' and updates the TLW
  and the text options menu accordingly.

- added a callback procedure 'fileListCb(widget,clientdata,calldata)' which
  parses the first string passed in 'calldata' using 'XtNameToWidget' to
  find the specified widget-descendant of '((FileWindowRec*)clientdata)->shell'
  ie. a file window. If the named widget, which is supposed to be a
  menu entry, is found, the procedures on it's callback list will be called.
  This permits the user to map events to the fileList's 'notify()' action 
  by means of translations. 'notify()' calls fileListCb in turn and passes
  its argument string. If this string can be resolved to the name of a menu
  item that menu item's callbacks are invoked.
  If a fileList widget contains e.g. the following translation:

    <Key>d : notify(*file*delete)

  and if there is a menu entry called 'delete' which is a descendant of
  the menu called 'file', the callback registered with the 'delete' menu item
  is invoked when the user presses 'd'. You might have to look up the widget
  names in the source (mainly 'FmFw.c') or by using 'editres'. Consult the
  docs of 'XtNameToWidget()' on how the argument string to 'notify()' is parsed.

- 'createFileIcons()' has been rewritten; an ILW is now used.
  If the number of columns of icons is not fixed by the user
  (ie. resource 'nHoriz' of the ILW is zero) the 'Viewport' parent 
  is not allowed to have a horizontal scrollbar. If it is resized,
  it will resize the ILW which displays as many columns as there is
  space for.
  'fileListCb()' is registered on ILW's callback list (to be invoked
  by the 'notify()' action. That way selected files can be deleted,
  copied and so on by keystrokes (given the appropriate translations).


- 'createTextDisplay()' has been rewritten; a TLW is now used.
  A callback procedure 'unmanageTxtOptsCb()' is registered which unmaps
  the options menu when the TLW is destroyed (change of view mode).
  The 'Viewport' parent of the TLW is allowed to have a horizontal bar if
  necessary. Consider the comments about a bug in the viewport widget above.
  The 'options' menu is mapped.
  'fileListCb()' is registered on TLW's callback list (to be invoked
  by the 'notify()' action. That way selected files can be deleted,
  copied and so on by keystrokes (given the appropriate translations).

- A new private callback procedure, 'unmanageTxtOptsCb()', is added.

- A workaround for another bug in 'Viewport.c' has been added. (Under certain
  circumstances scrollbars are wrongly placed and obscured.) The workaround
  is activated by compiling 'FmFw.c' with -DVIEWPORT_HACK. A patch for
  'Viewport.c' is also provided.

4. Other Modifications
======================

4.1 Adapted Imakefiles and Application Defaults
-----------------------------------------------

In order to be able to easily build XFM 'Imakefile', 'src/Imakefile' and
'Imake.options' were modified. New symbols were added to 'Imake.options'
which control configuration of the different enhancements.

The application defaults file 'Xfm.ad' is built depending on the different
'Imake.options' settings. The version string is extracted from 'FmVersion.h'
and inserted into the application defaults. XFM uses this information to
check for the correct version of the app. defaults.

4.2 A Patch File for the Viewport Widget
----------------------------------------

A patch for the viewport widget is provided to fix some bugs (see the
comments in the file). Change dir to the Xaw or Xaw3d source directory
and issue

  patch -p0 < 'path'/viewport-patch

to apply the patch. Then you have to rebuild the Xaw/Xaw3d library. 
If you link XFM with the patched library, the line defining the symbol
'USE_VP_HACK' should be commented out in 'Imake.options' before
building XFM. If you plan to use the buggy library, it is recommended
not to comment out the definition of 'USE_VP_HACK' thereby activating
workarounds for the bugs.

5. Building the Enhanced XFM
============================

Edit the file 'Imake.options' to your needs and/or desires. By default
all the enhancements and the viewport hack will be compiled.

Then build and install xfm by issuing 'xmkmf -a', 'make all' and 'make install'.

Note that the application resource file 'Xfm'  _MUST_ be installed at a
place where xfm can find it. Be aware that xfm-1.4 can not be run without the
resources because many important things are not hardcoded -- but user
configurable :-). If the proper resource file can not be found (XFM checks
also for the version of the resource file), a message is displayed and XFM
aborts.

Preferably 'Xfm' should be installed in a directory contained in
the XFILESEARCHPATH (should default to /usr/X11R6/lib/X11/app-defaults/%N).
Every user can then still modify some of the resources to his/her personal
needs and put them into an additional 'Xfm' file located in a directory
contained in the XUSERFILESEARCHPATH (should default to $HOME/%N, as long
as the XAPPLRESDIR is not set). The user defined resources override the
system wide resources; consult the Xt-docs for further (important) 
information on this subject.

6. TODO
=======

To further improve the speed/response time of XFM the procedure of how directories are read could be changed. Since files are mostly listed alphabetically, the directory should first be read and sorted. Only the
currently visible files should then be stat()'ed, deferring the time
consuming stats for invisible files for a later time.

If ever XFM is rewritten, the whole file window stuff should be moved
to widget code (ie. FLW). The file list should be maintained and updated
when XFM manipulates it. Re-reading the directory and stat'ing everything
is then only needed at 'updateIntervals' to track for 'external'
modifications.

A feature to successively select files by keystrokes could be added.
(Typing a 'regexpr' on the file window would select the corresponding
 files)

Consult the file TODO for further suggestions.
