Further enhancments to XFM Copyright (C) 1997 by T. Straumann, 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 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 / 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 or 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\ Return: set() notify() unset()\n\ Linefeed: set() notify() unset()\n\ Xfm*button box*cancel.accelerators:#override\n\ 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\ Return: set() notify() unset()\n\ Linefeed: set() notify() unset()\n\ Xfm*button box*replace.accelerators:#override\n\ Return: set() notify() unset()\n\ 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 :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 and 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 and 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 and 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\ : do-something()\n\ : 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: 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.