ftp.nice.ch/pub/next/tools/emulators/vice.0.15.0.NeXT.sd.tgz#/vice-0.15.0/src/arch/unix/xaw/widgets/FileSel.c

This is FileSel.c in view mode; [Download] [Up]

/*****************************************************************************

	FileSelector.c

	This file contains the C code for the FileSelector widget, which
	is intended to be used as a hierarchical Unix file selector box.

******************************************************************************/

/*
 * Author:
 * 	Brian Totty
 * 	Department of Computer Science
 * 	University Of Illinois at Urbana-Champaign
 *	1304 West Springfield Avenue
 * 	Urbana, IL 61801
 *
 * 	totty@cs.uiuc.edu
 *
 * (Sep 5, 1995: bugfix by Bert Bos <bert@let.rug.nl>, search for [BB])
 *
 * Fixes, improvements and VICE adaptation by Ettore Perazzoli
 * <ettore@comm2000.it>; search for [EP].
 * Detailed list of changes in `../../../ChangeLog'.
 *
 */

#define VICE

#include "vice.h"
#include "config.h"		/* [EP] 04/07/97 */
#include "utils.h"		/* [AF] 26jun98 */

#include <stdio.h>
#include <stdlib.h>		/* [EP] 10/15/96 */
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/Intrinsic.h>
#include <X11/CompositeP.h>
#include <X11/Composite.h>
#include <X11/cursorfont.h>
#include <X11/Xaw/SimpleP.h>
#include <X11/Xaw/Simple.h>
#include <X11/Xaw/LabelP.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/CommandP.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/FormP.h>
#include <X11/Xaw/Form.h>

#ifndef ENABLE_TEXTFIELD		/* [EP] 11/14/96 */
#include <X11/Xaw/AsciiTextP.h>
#include <X11/Xaw/AsciiText.h>
#ifdef X11R3
#define asciiTextWidgetClass	asciiStringWidgetClass
#define	XawtextEdit		XttextEdit
#define	XtNtype			"type"
#define	XawAsciiString		NULL
#define	XtNautoFill		"autoFill"
typedef	char *			XtPointer;
#endif
#endif

#include "ScrListP.h"
#include "ScrList.h"
#include "FileSelP.h"
#include "FileSel.h"
#include "TextField.h"

#define	NO_BUSY_GRAB

/*---------------------------------------------------------------------------*

                       D E C L A R A T I O N S

 *---------------------------------------------------------------------------*/

#define	SUPERCLASS		(&compositeClassRec)

#ifndef abs
#define abs(a)			((a) < 0 ? -(a) : (a))
#endif

#define max(a,b)		((a) > (b) ? (a) : (b))
#define min(a,b)		((a) < (b) ? (a) : (b))
#define XtStrlen(s)		((s) ? strlen(s) : 0)

#define	StrCopy(s)		((char*)strcpy((char *)XtMalloc((strlen(s)+1)*\
					sizeof(char)),((char *)(s))))

#define FSFieldOffset(field)	XtOffset(XfwfFileSelectorWidget,	\
					 fileSelector.field)
#define CoreFieldOffset(field)	XtOffset(Widget,core.field)

/*---------------------------------------------------------------------------*

                   I N T E R N A L    R O U T I N E S

 *---------------------------------------------------------------------------*/

#if (!NeedFunctionPrototypes)

static void		Initialize();
static void		Realize();
static void		Destroy();
static void		Resize();
static Boolean		SetValues();
static XtGeometryResult	GeometryManager();
static void		ChildrenCreate();
static void		ChildrenRealize();
static void		ChildrenRecalculate();
static void		ChildrenUpdate();
static void		ButtonAutostart();
static void		ButtonContents();
static void		ButtonOk();
static void		ButtonCancel();
static void		ButtonGoto();
static void		ButtonSelect();
static char *		GetFileBoxText();
static void		ClickOnPathList();
static void		ClickOnFileList();
static void		SelectFileByIndex();
static Boolean		SelectFileByName();
static void		UnselectAll();
static void		NotifySelectionChange();
static void		ParentizeDirectory();
static void		GotoDeepestLegalDirectory();
static void		UpdateLists();
static void		UpdateTextLines();
static void		Chdir();
static void		DoBusyCursor();
static void		UndoBusyCursor();
static void		TextWidgetSetText();
/* [EP] 11/25/96 */
static void		TextWidgetSetKeyboardFocusAction();

#else

static void		Initialize(Widget request, Widget new);
static void		Realize(Widget gw, XtValueMask *valueMask,
				XSetWindowAttributes *attrs);
static void		Destroy(XfwfFileSelectorWidget fsw);
static void		Resize(Widget gw);
static Boolean		SetValues(Widget gcurrent, Widget grequest,
				Widget gnew);
static XtGeometryResult	GeometryManager(Widget w,
				XtWidgetGeometry *request,
				XtWidgetGeometry *reply);
static void		ChildrenCreate(XfwfFileSelectorWidget fsw);
static void		ChildrenRealize(XfwfFileSelectorWidget fsw);
static void		ChildrenRecalculate(XfwfFileSelectorWidget fsw);
static void		ChildrenUpdate(XfwfFileSelectorWidget fsw);
static void		ButtonAutostart(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ButtonContents(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ButtonOk(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ButtonCancel(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ButtonGoto(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ButtonSelect(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static char *		GetFileBoxText(XfwfFileSelectorWidget fsw);
static void		ClickOnPathList(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		ClickOnFileList(Widget w, XfwfFileSelectorWidget fsw,
				XtPointer call_data);
static void		SelectFileByIndex(XfwfFileSelectorWidget fsw,
				int strchr);
static Boolean		SelectFileByName(XfwfFileSelectorWidget fsw,
				char *name);
static void		UnselectAll(XfwfFileSelectorWidget fsw);
static void		NotifySelectionChange(XfwfFileSelectorWidget fsw);
static void		ParentizeDirectory(char *dir);
static void		GotoDeepestLegalDirectory(XfwfFileSelectorWidget fsw);
static void		UpdateLists(XfwfFileSelectorWidget fsw);
static void		UpdateTextLines(XfwfFileSelectorWidget fsw);
static void		Chdir(XfwfFileSelectorWidget fsw);
static void		DoBusyCursor(Widget w);
static void		UndoBusyCursor(Widget w);
static void		TextWidgetSetText(Widget tw, char *text);
/* [EP] 11/25/96 */
static void		TextWidgetSetKeyboardFocusAction(Widget w,
				XEvent *event, String *params,
				Cardinal *num_params);

#endif

/*---------------------------------------------------------------------------*

              R E S O U R C E    I N I T I A L I Z A T I O N

 *---------------------------------------------------------------------------*/

static XtResource resources[] =
{
	{XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
		CoreFieldOffset(width), XtRString, "500"},
	{XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
		CoreFieldOffset(height), XtRString, "250"},
	{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
		CoreFieldOffset(background_pixel), XtRString, "white"},

	{XtNokButtonCallback, XtCCallback, XtRCallback,
		sizeof(XtCallbackList), FSFieldOffset(ok_button_callbacks),
		XtRCallback, NULL},
	{XtNcancelButtonCallback, XtCCallback, XtRCallback,
		sizeof(XtCallbackList), FSFieldOffset(cancel_button_callbacks),
		XtRCallback, NULL},
	{XtNcontentsButtonCallback, XtCCallback, XtRCallback,
		sizeof(XtCallbackList), FSFieldOffset(contents_button_callbacks),
		XtRCallback, NULL},
	{XtNautostartButtonCallback, XtCCallback, XtRCallback,
		sizeof(XtCallbackList), FSFieldOffset(autostart_button_callbacks),
		XtRCallback, NULL},
	{XtNselectionChangeCallback, XtCCallback, XtRCallback,
		sizeof(XtCallbackList), FSFieldOffset(sel_change_callbacks),
		XtRCallback, NULL},

	{XtNshowOkButton, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(show_ok_button), XtRString, "True"},
	{XtNshowCancelButton, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(show_cancel_button), XtRString, "True"},
	{XtNshowContentsButton, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(show_contents_button), XtRString, "True"},
	{XtNshowAutostartButton, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(show_autostart_button), XtRString, "True"},

	{XtNflagLinks, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(flag_links), XtRString, "False"},
	{XtNcheckExistence, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(check_existence), XtRString, "True"},

	{XtNfileSelected, XtCBoolean, XtRBoolean, sizeof(Boolean),
		FSFieldOffset(file_selected), XtRString, "False"},

	{XtNcurrentDirectory, XtCPathname, XtRString, sizeof(String),
		FSFieldOffset(current_directory), XtRString, NULL},
	{XtNcurrentFile, XtCFilename, XtRString, sizeof(String),
		FSFieldOffset(current_file), XtRString, NULL},
	{XtNtitle, XtCLabel, XtRString, sizeof(String),
		FSFieldOffset(title), XtRString, "File Selector"},
	{XtNsortMode, XtCValue, XtRInt, sizeof(int),
		FSFieldOffset(sort_mode), XtRString, "2"},
	{XtNpattern, XtCFile, XtRString, sizeof(String),
		FSFieldOffset(pattern), XtRString, NULL},
};

#undef FSFieldOffset
#undef CoreFieldOffset


/*---------------------------------------------------------------------------*

        A C T I O N    A N D    T R A N S L A T I O N    T A B L E S

 *---------------------------------------------------------------------------*/


/* [EP] 11/25/96 */
static XtActionsRec actions[] =
{
	  {"set-keyboard-focus",(XtActionProc)TextWidgetSetKeyboardFocusAction},
	  {NULL,		(XtActionProc)NULL}
};


/*---------------------------------------------------------------------------*

                    C L A S S    A L L O C A T I O N

 *---------------------------------------------------------------------------*/

XfwfFileSelectorClassRec xfwfFileSelectorClassRec =
{
	{
		/* superclass		*/	(WidgetClass)SUPERCLASS,
		/* class_name		*/	"XfwfFileSelector",
		/* widget_size		*/	sizeof(XfwfFileSelectorRec),
		/* class_initialize	*/	NULL,
		/* class_part_initialize*/	NULL,
		/* class_inited		*/	FALSE,
		/* initialize		*/	(XtInitProc)Initialize,
		/* initialize_hook	*/	NULL,
		/* realize		*/	(XtRealizeProc)Realize,
		/* actions		*/	actions, /* [EP] 11/25/96 */
		/* num_actions		*/	XtNumber(actions),
		/* resources		*/	resources,
		/* resource_count	*/	XtNumber(resources),
		/* xrm_class		*/	NULLQUARK,
		/* compress_motion	*/	TRUE,
		/* compress_exposure	*/	TRUE,
		/* compress_enterleave	*/	TRUE,
		/* visible_interest	*/	FALSE,
		/* destroy		*/	(XtWidgetProc)Destroy,
		/* resize		*/	(XtWidgetProc)Resize,
		/* expose		*/	XtInheritExpose,
		/* set_values		*/	(XtSetValuesFunc)SetValues,
		/* set_values_hook	*/	NULL,
		/* set_values_almost	*/	XtInheritSetValuesAlmost,
		/* get_values_hook	*/	NULL,
		/* accept_focus		*/	NULL,
		/* version		*/	XtVersion,
		/* callback_private	*/	NULL,
		/* tm_table		*/	NULL,
		/* query_geometry       */	XtInheritQueryGeometry,
		/* display_accelerator  */	XtInheritDisplayAccelerator,
		/* extension            */	NULL
	}, /* Core Part */
	{
		/* geometry_manager     */	GeometryManager,
		/* change_managed       */	XtInheritChangeManaged,
		/* insert_child         */	XtInheritInsertChild,
		/* delete_child         */	XtInheritDeleteChild,
		/* extension            */	NULL
	}, /* Composite Part */
	{
		/* no extra class data  */	0
	}  /* FileSelector Part */
};

WidgetClass xfwfFileSelectorWidgetClass =
	(WidgetClass)&xfwfFileSelectorClassRec;

/*---------------------------------------------------------------------------*

                    E X P O R T E D    M E T H O D S

 *---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*

	Initialize()

	This procedure is called by the X toolkit to initialize
	the widget instance.  The hook to this routine is in the
	initialize part of the core part of the class.

 *---------------------------------------------------------------------------*/

/* ARGSUSED */
static void Initialize(request,new)
Widget request,new;
{
	int i;
	XfwfFileSelectorWidget fsw;
	char *str,*initial_file, *pathp /*, path[MAXPATHLEN + 2]*/;
	static char *star = "*";

	fsw = (XfwfFileSelectorWidget)new;
	FSHandCursor(fsw) = XCreateFontCursor(XtDisplay(fsw),XC_hand1);
	FSBusyCursor(fsw) = XCreateFontCursor(XtDisplay(fsw),XC_watch);

	for (i = 0; i < FS_NUM_CHILDREN; i++) FSNthWidget(fsw,i) = NULL;

	FSDirMgr(fsw) = NULL;
	FSPathList(fsw) = NULL;
	FSPathListCount(fsw) = 0;
	FSFileList(fsw) = NULL;
	FSFileListCount(fsw) = 0;

	str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
	if (FSCurrentDirectory(fsw) != NULL)	/* User Specified Path */
	{
		strcpy(str,FSCurrentDirectory(fsw));
	}
	    else
	{
#if 0
		getwd(path);
		strcpy(str,path);
#else
		pathp = getcwd (str, MAXPATHLEN);
#endif
	}
	FSCurrentDirectory(fsw) = str;

	str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
	initial_file = FSCurrentFile(fsw);
	FSCurrentFile(fsw) = str;

	if (FSPattern(fsw) == NULL) FSPattern(fsw) = star;
	FSPattern(fsw) = StrCopy(FSPattern(fsw));

	if (FSCorePart(request)->width <= 0) FSCorePart(new)->width = 500;
	if (FSCorePart(request)->height <= 0) FSCorePart(new)->height = 200;

	ChildrenCreate(fsw);
	GotoDeepestLegalDirectory(fsw);
	if (initial_file) SelectFileByName(fsw,initial_file);
} /* End Initialize */


/*---------------------------------------------------------------------------*

	Realize()

	This function is called to realize a FileSelector widget.

 *---------------------------------------------------------------------------*/

static void Realize(gw,valueMask,attrs)
Widget gw;
XtValueMask *valueMask;
XSetWindowAttributes *attrs;
{
	XfwfFileSelectorWidget fsw;

	fsw = (XfwfFileSelectorWidget)gw;
	XtCreateWindow(gw,InputOutput,(Visual *)CopyFromParent,
		*valueMask,attrs);

	ChildrenRealize(fsw);
	ChildrenUpdate(fsw);

	Resize(gw);

	NotifySelectionChange(fsw);
} /* End Realize */



/*---------------------------------------------------------------------------*

	Destroy()

	This function is called to destroy a fileSelector widget.

 *---------------------------------------------------------------------------*/

static void Destroy(fsw)
XfwfFileSelectorWidget fsw;
{
	int i;

	XtFree(FSCurrentDirectory(fsw));
	XtFree(FSCurrentFile(fsw));
	XtFree(FSPattern(fsw));

	if (FSPathList(fsw) != NULL)
	{
		for (i = 0; i < FSPathListCount(fsw); i++)
			free(FSPathList(fsw)[i]);
		free(FSPathList(fsw));
	}
	if (FSFileList(fsw) != NULL)
	{
		for (i = 0; i < FSFileListCount(fsw); i++)
			free(FSFileList(fsw)[i]);
		free(FSFileList(fsw));
	}
} /* End Destroy */



/*---------------------------------------------------------------------------*

	Resize()

	This function is called to resize a fileSelector widget.

 *---------------------------------------------------------------------------*/

static void Resize(gw)
Widget gw;
{
	XfwfFileSelectorWidget w;

	w = (XfwfFileSelectorWidget)gw;
	ChildrenUpdate(w);
} /* End Resize */


/*---------------------------------------------------------------------------*

	SetValues(gcurrent,grequest,gnew)

	This function is the external interface for setting resources.

 *---------------------------------------------------------------------------*/

/* ARGSUSED */
static Boolean SetValues(gcurrent,grequest,gnew)
Widget gcurrent,grequest,gnew;
{
	XfwfFileSelectorWidget current,new;

	current = (XfwfFileSelectorWidget)gcurrent;
	new = (XfwfFileSelectorWidget)gnew;

	if (FSPattern(current) != FSPattern(new))
	{
/*printf("new pattern: %s, (old=%s)\n",FSPattern(new), FSPattern(current));*/
/* interestingly the old value is here copied to the _new_ one! why?
		FSPattern(new) = StrCopy(FSPattern(current));
 * replaced this with the following line, using the new value AF 23jun98 */
		FSPattern(new) = StrCopy(FSPattern(new));
		Chdir(new);
		/* XtFree() call moved -- EP 06/12/97. */
		XtFree(FSPattern(current));
	}
	if (FSSortMode(current) != FSSortMode(new))
	{
		FSSortMode(new) = FSSortMode(current);
	}
	if (FSTitle(current) != FSTitle(new))
	{
		XtWarning("Title Change Not Supported");
		FSTitle(new) = FSTitle(current);
	}
	if (FSFileSelected(current) != FSFileSelected(new))
	{
		XtWarning("Can't Change XtNfileSelected Resource");
		FSFileSelected(new) = FSFileSelected(current);
	}
	if (FSCheckExistence(current) != FSCheckExistence(new))
	{
		if (!FSCheckExistence(new))
		{
			XtSetSensitive(FSNthWidget(new,FS_I_OK_BUTTON),True);
			XtSetSensitive(FSNthWidget(new,FS_I_CONTENTS_BUTTON),
				       True);
			XtSetSensitive(FSNthWidget(new,FS_I_AUTOSTART_BUTTON),
				       True);
		}
		    else
		{
			Chdir(new);
		}
	}
	if (FSShowOkButton(current) != FSShowOkButton(new))
	{
		if (FSShowOkButton(new) == True)
			XtManageChild(FSNthWidget(new,FS_I_OK_BUTTON));
		    else
			XtUnmanageChild(FSNthWidget(new,FS_I_OK_BUTTON));
	}
	if (FSShowCancelButton(current) != FSShowCancelButton(new))
	{
		if (FSShowCancelButton(new) == True)
			XtManageChild(FSNthWidget(new,FS_I_CANCEL_BUTTON));
		    else
			XtUnmanageChild(FSNthWidget(new,FS_I_CANCEL_BUTTON));
	}
	if (FSShowContentsButton(current) != FSShowContentsButton(new))
	{
		if (FSShowContentsButton(new) == True)
			XtManageChild(FSNthWidget(new,FS_I_CONTENTS_BUTTON));
		    else
			XtUnmanageChild(FSNthWidget(new,FS_I_CONTENTS_BUTTON));
	}
	if (FSShowAutostartButton(current) != FSShowAutostartButton(new))
	{
		if (FSShowAutostartButton(new) == True)
			XtManageChild(FSNthWidget(new, FS_I_AUTOSTART_BUTTON));
		    else
			XtUnmanageChild(FSNthWidget(new, FS_I_AUTOSTART_BUTTON));
	}
	if (FSCurrentDirectory(current) != FSCurrentDirectory(new))
	{
		strcpy(FSCurrentDirectory(current),FSCurrentDirectory(new));
		FSCurrentDirectory(new) = FSCurrentDirectory(current);
		Chdir(new);
	}
	if (FSCurrentFile(current) != FSCurrentFile(new))
	{
		char *new_name;

		new_name = FSCurrentFile(new);
		FSCurrentFile(new) = FSCurrentFile(current);
		SelectFileByName(new,new_name);
	}
	return(False);
} /* End SetValues */



/*---------------------------------------------------------------------------*

	GeometryManager(w,request,reply)

	This routine acts as the geometry_manager method for the
	FileSelector widget.  It is called when a child wants to
	resize/reposition itself.

	Currently, we allow all requests.

 *---------------------------------------------------------------------------*/

/* ARGSUSED */
static XtGeometryResult GeometryManager(w,request,reply)
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *reply;
{
	return(XtGeometryYes);
} /* End GeometryManager */



/*---------------------------------------------------------------------------*

                     L O C A L    R O U T I N E S

 *---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*

	ChildrenCreate(fsw)

	This routine creates the initial child widgets for the
	file selector widget and places them in the widget fsw.
	No placement or resizing is done.  That is done by
	ChildrenUpdate().

 *---------------------------------------------------------------------------*/

static void ChildrenCreate(fsw)
XfwfFileSelectorWidget fsw;
{
	Arg args[10];
	static char *dummy_string_list[] = { NULL };
/* [EP] 11/25/96 */
#ifndef ENABLE_TEXTFIELD
	static char *text_box_translations = "#override\n<Key>Return: no-op()";
#else
	static char *text_box_translations = "<Btn1Down>: select-start() set-keyboard-focus()";
#endif

#ifndef VICE

		/* (here was the) Title
		   I have removed this since we need a small window
		   (the emulation window can be quite small itself).
		   [EP] 8/25/96 */

	XtSetArg(args[0],XtNlabel,FSTitle(fsw));
	XtSetArg(args[1],XtNborderWidth,0);
	XtSetArg(args[2],XtNresizable,True);
	FSNthWidget(fsw,FS_I_TITLE) = XtCreateManagedWidget("title",
		labelWidgetClass,(Widget)fsw,args,3);
#else
 	FSNthWidget(fsw,FS_I_TITLE) = NULL;
#endif

		/* Current Directory Line */

#ifndef ENABLE_TEXTFIELD
	XtSetArg(args[0],XtNtype,XawAsciiString);
	XtSetArg(args[1],XtNeditType,XawtextEdit);
	XtSetArg(args[2],XtNstring,"");
	FSNthWidget(fsw,FS_I_CUR_DIR_TEXT) =
		XtCreateManagedWidget("cur_dir_text",
				      asciiTextWidgetClass,(Widget)fsw,args,3);
#else  /* [EP] 11/14/96 */
	FSNthWidget(fsw,FS_I_CUR_DIR_TEXT) =
	        XtVaCreateManagedWidget("cur_dir_text",textfieldWidgetClass,(Widget)fsw,NULL);
	XtAddCallback(FSNthWidget(fsw,FS_I_CUR_DIR_TEXT),
		      XtNactivateCallback,(XtCallbackProc)ButtonGoto,(XtPointer)fsw);
#endif
	XtOverrideTranslations(FSNthWidget(fsw,FS_I_CUR_DIR_TEXT),
			       XtParseTranslationTable(text_box_translations));

		/* Current File Line */

#ifndef ENABLE_TEXTFIELD
	XtSetArg(args[0],XtNtype,XawAsciiString);
	XtSetArg(args[1],XtNeditType,XawtextEdit);
	XtSetArg(args[2],XtNstring,"");
	/* [EP] 11/25/96 */
	FSNthWidget(fsw,FS_I_CUR_FILE_TEXT) =
		XtCreateManagedWidget("cur_file_text",
				      asciiTextWidgetClass,(Widget)fsw,args,3);
#else
	FSNthWidget(fsw,FS_I_CUR_FILE_TEXT) =
		XtVaCreateManagedWidget("cur_file_text",textfieldWidgetClass,(Widget)fsw,NULL);
	XtOverrideTranslations(FSNthWidget(fsw,FS_I_CUR_FILE_TEXT),
			       XtParseTranslationTable(text_box_translations));
	XtAddCallback(FSNthWidget(fsw,FS_I_CUR_FILE_TEXT),
		      XtNactivateCallback,(XtCallbackProc)ButtonSelect,(XtPointer)fsw);
#endif
	XtOverrideTranslations(FSNthWidget(fsw,FS_I_CUR_DIR_TEXT),
			       XtParseTranslationTable(text_box_translations));

		/* Path From Root Title */

	XtSetArg(args[0],XtNlabel,"Path From Root");
	XtSetArg(args[1],XtNborderWidth,0);
	FSNthWidget(fsw,FS_I_PATH_LIST_TITLE) =
		XtCreateManagedWidget("path_list_title",
				      labelWidgetClass,(Widget)fsw,args,2);

		/* Directory List */

	XtSetArg(args[0],XtNlist,dummy_string_list);
	XtSetArg(args[1],XtNnumberStrings,0);
	FSNthWidget(fsw,FS_I_PATH_LIST) =
		XtCreateManagedWidget("path_list",
			xfwfScrolledListWidgetClass,(Widget)fsw,args,2);
	XtAddCallback(FSNthWidget(fsw,FS_I_PATH_LIST),
		      XtNcallback,(XtCallbackProc)ClickOnPathList,
		      (XtPointer)fsw);

		/* File List Title */

	XtSetArg(args[0],XtNlabel,"Directory Contents");
	XtSetArg(args[1],XtNborderWidth,0);
	FSNthWidget(fsw,FS_I_FILE_LIST_TITLE) =
		XtCreateManagedWidget("file_list_title",
				      labelWidgetClass,(Widget)fsw,args,2);

		/* File List */

	XtSetArg(args[0],XtNlist,dummy_string_list);
	XtSetArg(args[1],XtNnumberStrings,0);
	FSNthWidget(fsw,FS_I_FILE_LIST) =
		XtCreateManagedWidget("file_list",
			xfwfScrolledListWidgetClass,(Widget)fsw,args,2);
	XtAddCallback(FSNthWidget(fsw,FS_I_FILE_LIST),
		      XtNcallback,(XtCallbackProc)ClickOnFileList,
		      (XtPointer)fsw);

		/* Goto Button */

	XtSetArg(args[0],XtNlabel,"Show" /* "Goto" */);
	XtSetArg(args[1],XtNborderWidth,1);
	FSNthWidget(fsw,FS_I_GOTO_BUTTON) =
		XtCreateManagedWidget("goto_button",
				      commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_GOTO_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonGoto,
		      (XtPointer)fsw);

		/* Select Button */

	XtSetArg(args[0],XtNlabel,"Select");
	XtSetArg(args[1],XtNborderWidth,1);
	FSNthWidget(fsw,FS_I_SELECT_BUTTON) =
		XtCreateManagedWidget("select_button",
				      commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_SELECT_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonSelect,
		      (XtPointer)fsw);

		/* Autostart Button.  ([EP] 02/22/97) */

	XtSetArg(args[0],XtNlabel,"Autostart");
/*	XtSetArg(args[1],XtNborderWidth,2); */
	FSNthWidget(fsw,FS_I_AUTOSTART_BUTTON)
                = XtCreateManagedWidget("autostart_button",
		commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_AUTOSTART_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonAutostart,
		      (XtPointer)fsw);

	/* Contents Button */
	XtSetArg(args[0],XtNlabel,"Contents");
	FSNthWidget(fsw,FS_I_CONTENTS_BUTTON) = XtCreateManagedWidget("contents_button",
		commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_CONTENTS_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonContents,
		      (XtPointer)fsw);

		/* OK Button */

	XtSetArg(args[0],XtNlabel,"OK");
/*	XtSetArg(args[1],XtNborderWidth,2); */
	FSNthWidget(fsw,FS_I_OK_BUTTON) = XtCreateManagedWidget("ok_button",
		commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_OK_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonOk,
		      (XtPointer)fsw);

		/* Cancel Button */

	XtSetArg(args[0],XtNlabel,"Cancel");
/*	XtSetArg(args[1],XtNborderWidth,2); */
	FSNthWidget(fsw,FS_I_CANCEL_BUTTON) =
		XtCreateManagedWidget("cancel_button",
				      commandWidgetClass,(Widget)fsw,args,1);
	XtAddCallback(FSNthWidget(fsw,FS_I_CANCEL_BUTTON),
		      XtNcallback,(XtCallbackProc)ButtonCancel,
		      (XtPointer)fsw);
} /* End ChildrenCreate */


/*---------------------------------------------------------------------------*

	ChildrenRealize(fsw)

	This routine realizes the child widgets.  The widgets must
	already have been created and initialized.  Their coordinates
	should already have been set.

 *---------------------------------------------------------------------------*/

static void ChildrenRealize(fsw)
XfwfFileSelectorWidget fsw;
{
	int i;
	Widget widget;

	for (i = 0; i < FS_NUM_CHILDREN; i++)
	{
		if (FSNthWidget(fsw,i) != NULL)
		{
			widget = FSNthWidget(fsw,i);
			XtRealizeWidget(widget);
			if ((i == FS_I_OK_BUTTON &&
			     !FSShowOkButton(fsw)) ||
			    (i == FS_I_CANCEL_BUTTON &&
			     !FSShowCancelButton(fsw)))
			{
				XtUnmanageChild(widget);
			}
		}
	}

#ifdef ENABLE_TEXTFIELD
	/* [EP] 11/25/96 */
	XtCallActionProc(FSNthWidget(fsw,FS_I_CUR_DIR_TEXT),"set-keyboard-focus",
			 NULL,NULL,0);
#endif
} /* End ChildrenRealize */


/*---------------------------------------------------------------------------*

        ChildrenRecalculate(fsw)

	This routine takes a file selector widget and recalculates
	the coordinates and sizes of the constituent components
	based on the current size of the file selector.

	This function does not actually change the child widgets, it
	just calculates the coordinates and caches the coordinates in
	the FileSelector widget.

 *---------------------------------------------------------------------------*/

static void ChildrenRecalculate(fsw)
XfwfFileSelectorWidget fsw;
{
	BOX *coords;
	Widget widget;
	int i,w,h,empty_space,gap,orig_path_list_h,orig_file_list_h,top;
	XtWidgetGeometry parent_idea,child_idea;

	w = FSCorePart(fsw)->width;
	h = FSCorePart(fsw)->height;

	/* Get The Child Widgets Current Widths And Heights */

	for (i = 0; i < FS_NUM_CHILDREN; i++)
	{
		if (FSNthWidget(fsw,i) != NULL)
		{
			widget = FSNthWidget(fsw,i);
			coords = FSNthCoords(fsw,i);
			BoxW(coords) = CoreWidth(widget);
			BoxH(coords) = CoreHeight(widget);
		}
	}

		/* Adjust Widths */
		/* (little fixes by [EP] Sept 5th, 1996) */

	BoxW(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) = .7 * w;
	BoxW(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) = .7 * w;
	BoxW(FSNthCoords(fsw,FS_I_GOTO_BUTTON)) = .20 * w;
	BoxW(FSNthCoords(fsw,FS_I_SELECT_BUTTON)) = .20 * w;

	BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) = .45 * w;
	BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)) = .45 * w;
	BoxW(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON)) =
		BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) * .45;
	BoxW(FSNthCoords(fsw,FS_I_CONTENTS_BUTTON)) =
		BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) * .45;
	BoxW(FSNthCoords(fsw,FS_I_OK_BUTTON)) =
		BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)) * .45;
	BoxW(FSNthCoords(fsw,FS_I_CANCEL_BUTTON)) =
		BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)) * .45;

		/* Adjust Heights */

	BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) =
		max(BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)),
		    BoxH(FSNthCoords(fsw,FS_I_GOTO_BUTTON)));
	BoxH(FSNthCoords(fsw,FS_I_GOTO_BUTTON)) =
		BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT));

	BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) =
		max(BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)),
		    BoxH(FSNthCoords(fsw,FS_I_SELECT_BUTTON)));
	BoxH(FSNthCoords(fsw,FS_I_SELECT_BUTTON)) =
		BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT));

#ifndef VICE			/* [EP] 11/3/1996*/
	empty_space = h - (BoxH(FSNthCoords(fsw,FS_I_TITLE)) +
			   BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) +
			   BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) +
			   BoxH(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE)) +
			   BoxH(FSNthCoords(fsw,FS_I_OK_BUTTON)));
#else
	empty_space = h - (BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) +
			   BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) +
			   BoxH(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE)) +
			   BoxH(FSNthCoords(fsw,FS_I_OK_BUTTON)));
#endif
	gap = .025 * h;
	BoxH(FSNthCoords(fsw,FS_I_PATH_LIST)) = empty_space - 8 * gap;
	BoxH(FSNthCoords(fsw,FS_I_FILE_LIST)) = empty_space - 8 * gap;
	orig_path_list_h = BoxH(FSNthCoords(fsw,FS_I_PATH_LIST));
	orig_file_list_h = BoxH(FSNthCoords(fsw,FS_I_FILE_LIST));

		/* Listen To Child Height Requests For Lists */

	parent_idea.request_mode = CWWidth | CWHeight;
	parent_idea.width = BoxW(FSNthCoords(fsw,FS_I_PATH_LIST));
	parent_idea.height = BoxH(FSNthCoords(fsw,FS_I_PATH_LIST));
	XtQueryGeometry(FSNthWidget(fsw,FS_I_PATH_LIST),
			&parent_idea,&child_idea);
	if ((child_idea.request_mode & CWHeight) &&
	    (child_idea.height < parent_idea.height))
	{
		BoxH(FSNthCoords(fsw,FS_I_PATH_LIST)) = child_idea.height;
	}

	parent_idea.request_mode = CWWidth | CWHeight;
	parent_idea.width = BoxW(FSNthCoords(fsw,FS_I_FILE_LIST));
	parent_idea.height = BoxH(FSNthCoords(fsw,FS_I_FILE_LIST));
	XtQueryGeometry(FSNthWidget(fsw,FS_I_FILE_LIST),
			&parent_idea,&child_idea);
	if ((child_idea.request_mode & CWHeight) &&
	    (child_idea.height < parent_idea.height))
	{
		BoxH(FSNthCoords(fsw,FS_I_FILE_LIST)) = child_idea.height;
	}

		/* Make Sure Both Lists Have Same Minimum Height */

	BoxH(FSNthCoords(fsw,FS_I_PATH_LIST)) =
		min(BoxH(FSNthCoords(fsw,FS_I_PATH_LIST)),
		    BoxH(FSNthCoords(fsw,FS_I_FILE_LIST)));
	BoxH(FSNthCoords(fsw,FS_I_FILE_LIST)) =
		min(BoxH(FSNthCoords(fsw,FS_I_PATH_LIST)),
		    BoxH(FSNthCoords(fsw,FS_I_FILE_LIST)));

		/* Vertical Positions */

#ifndef VICE			/* [EP] 11/3/96 */
	BoxY(FSNthCoords(fsw,FS_I_TITLE)) = gap;
	BoxY(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) =
		(BoxY(FSNthCoords(fsw,FS_I_TITLE)) +
		 BoxH(FSNthCoords(fsw,FS_I_TITLE))) + gap;
#else
	BoxY(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) = gap;
#endif

	BoxY(FSNthCoords(fsw,FS_I_GOTO_BUTTON)) =
		BoxY(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT));

	BoxY(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) =
		(BoxY(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) +
		 BoxH(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT))) + gap;
	BoxY(FSNthCoords(fsw,FS_I_SELECT_BUTTON)) =
		BoxY(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT));

	BoxY(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE)) =
		(BoxY(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) +
		 BoxH(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT))) + gap;
	BoxY(FSNthCoords(fsw,FS_I_FILE_LIST_TITLE)) =
		BoxY(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE));

	BoxY(FSNthCoords(fsw,FS_I_PATH_LIST)) =
		(BoxY(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE)) +
		 BoxH(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE))) + gap +
		(orig_path_list_h - BoxH(FSNthCoords(fsw,FS_I_PATH_LIST))) / 2;
	BoxY(FSNthCoords(fsw,FS_I_FILE_LIST)) =
		BoxY(FSNthCoords(fsw,FS_I_PATH_LIST));

	top = BoxY(FSNthCoords(fsw,FS_I_PATH_LIST)) +
		BoxH(FSNthCoords(fsw,FS_I_PATH_LIST));
	empty_space = h - top;
	BoxY(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON)) = top +
		(h - top - BoxH(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON))) / 2;
	BoxY(FSNthCoords(fsw,FS_I_CONTENTS_BUTTON)) = top +
		(h - top - BoxH(FSNthCoords(fsw,FS_I_CONTENTS_BUTTON))) / 2;
	BoxY(FSNthCoords(fsw,FS_I_OK_BUTTON)) = top +
		(h - top - BoxH(FSNthCoords(fsw,FS_I_OK_BUTTON))) / 2;
	BoxY(FSNthCoords(fsw,FS_I_CANCEL_BUTTON)) = top +
		(h - top - BoxH(FSNthCoords(fsw,FS_I_CANCEL_BUTTON))) / 2;

		/* Horizontal Positions */

#ifndef VICE			/* EP 11/3/96 */
	BoxX(FSNthCoords(fsw,FS_I_TITLE)) =
		(w - BoxW(FSNthCoords(fsw,FS_I_TITLE))) / 2;
#else
	BoxX(FSNthCoords(fsw,FS_I_TITLE)) = w / 2;
#endif

	empty_space = w - (BoxW(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) +
			   BoxW(FSNthCoords(fsw,FS_I_GOTO_BUTTON)));
	gap = empty_space / 3;
	BoxX(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) = gap;
	BoxX(FSNthCoords(fsw,FS_I_GOTO_BUTTON)) =
		(BoxX(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT)) +
		 BoxW(FSNthCoords(fsw,FS_I_CUR_DIR_TEXT))) + gap;

	empty_space = w - (BoxW(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) +
			   BoxW(FSNthCoords(fsw,FS_I_SELECT_BUTTON)));
	gap = empty_space / 3;
	BoxX(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) = gap;
	BoxX(FSNthCoords(fsw,FS_I_SELECT_BUTTON)) =
		(BoxX(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT)) +
		 BoxW(FSNthCoords(fsw,FS_I_CUR_FILE_TEXT))) + gap;

	empty_space = w - (BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) +
			   BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)));
	gap = empty_space / 3;
	BoxX(FSNthCoords(fsw,FS_I_PATH_LIST)) = gap;
	BoxX(FSNthCoords(fsw,FS_I_FILE_LIST)) =
		(BoxX(FSNthCoords(fsw,FS_I_PATH_LIST)) +
		 BoxW(FSNthCoords(fsw,FS_I_PATH_LIST))) + gap;

	BoxX(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE)) =
		(BoxX(FSNthCoords(fsw,FS_I_PATH_LIST)) +
		 (BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) -
		  BoxW(FSNthCoords(fsw,FS_I_PATH_LIST_TITLE))) / 2);

	BoxX(FSNthCoords(fsw,FS_I_FILE_LIST_TITLE)) =
		(BoxX(FSNthCoords(fsw,FS_I_FILE_LIST)) +
		 (BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)) -
		  BoxW(FSNthCoords(fsw,FS_I_FILE_LIST_TITLE))) / 2);

	empty_space = BoxW(FSNthCoords(fsw,FS_I_PATH_LIST)) -
	    (BoxW(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON)) +
	     BoxW(FSNthCoords(fsw,FS_I_CONTENTS_BUTTON)));
	gap = empty_space / 3;
	BoxX(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON)) =
		BoxX(FSNthCoords(fsw,FS_I_PATH_LIST)) + gap;
	BoxX(FSNthCoords(fsw,FS_I_CONTENTS_BUTTON)) =
	    (BoxX(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON)) +
	     BoxW(FSNthCoords(fsw,FS_I_AUTOSTART_BUTTON))) + gap;

	empty_space = BoxW(FSNthCoords(fsw,FS_I_FILE_LIST)) -
		(BoxW(FSNthCoords(fsw,FS_I_OK_BUTTON)) +
		 BoxW(FSNthCoords(fsw,FS_I_CANCEL_BUTTON)));
	gap = empty_space / 3;
	BoxX(FSNthCoords(fsw,FS_I_OK_BUTTON)) =
		BoxX(FSNthCoords(fsw,FS_I_FILE_LIST)) + gap;
	BoxX(FSNthCoords(fsw,FS_I_CANCEL_BUTTON)) =
		(BoxX(FSNthCoords(fsw,FS_I_OK_BUTTON)) +
		 BoxW(FSNthCoords(fsw,FS_I_OK_BUTTON))) + gap;
} /* End ChildrenRecalculate */


/*---------------------------------------------------------------------------*

	ChildrenUpdate(fsw)

	This routine takes a File Selector widget <fsw> and updates
	the child widgets by recalculating their coordinates and
	setting the appropriate resources.

 *---------------------------------------------------------------------------*/

static void ChildrenUpdate(fsw)
XfwfFileSelectorWidget fsw;
{
	int i;
	Widget widget;
	BOX *coords;
	Boolean not_at_root;
	XfwfScrolledListWidget file_list;

	ChildrenRecalculate(fsw);

	for (i = 0; i < FS_NUM_CHILDREN; i++)
	{
		if (FSNthWidget(fsw,i) != NULL)
		{
			widget = FSNthWidget(fsw,i);
			coords = FSNthCoords(fsw,i);
			XtMoveWidget(widget,BoxX(coords),BoxY(coords));
			XtResizeWidget(widget,BoxW(coords),BoxH(coords),
				       CoreBorderWidth(widget));
		}
	}

	file_list = (XfwfScrolledListWidget)
		FSNthWidget(fsw,FS_I_FILE_LIST);

	if (FSPathListCount(fsw) != 1)
		not_at_root = True;
	    else
		not_at_root = False;

#if 0				/* Removed by [EP] 02/22/97. */
	XtSetSensitive(FSNthWidget(fsw,FS_I_AUTOSTART_BUTTON),not_at_root);
#endif
} /* End ChildrenUpdate */


/*---------------------------------------------------------------------------*

                 I N T E R N A L    C A L L B A C K S

 *---------------------------------------------------------------------------*/

/* Changed from `ButtonUp' to `ButtonAutostart' [EP] 02/22/97. */
static void ButtonAutostart(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
    XtCallCallbacks((Widget)fsw,XtNautostartButtonCallback,NULL);
} /* End ButtonUp */

static void ButtonContents(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
    XtCallCallbacks((Widget)fsw,XtNcontentsButtonCallback,NULL);
} /* End ButtonDir */


static void ButtonOk(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	XfwfFileSelectorOkButtonReturnStruct ret;

	ret.path = FSCurrentDirectory(fsw);
	ret.file = FSCurrentFile(fsw);
	ret.file_box_text = GetFileBoxText(fsw);
	XtCallCallbacks((Widget)fsw,XtNokButtonCallback,(XtPointer)&ret);
} /* End ButtonOk */


static void ButtonCancel(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	XtCallCallbacks((Widget)fsw,XtNcancelButtonCallback,NULL);
} /* End ButtonCancel */


static void ButtonGoto(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	Widget cur_dir_text;
	Arg args[10];
	String path;
	char *fpath, *fpattern;

	/* what is this actually needed for? */
	XtSetArg(args[0],XtNstring,(XtArgVal)(&path));
	cur_dir_text = FSNthWidget(fsw,FS_I_CUR_DIR_TEXT);
	XtGetValues(cur_dir_text,args,1);

#if defined VICE && (defined HAVE_REGEXP_H || defined HAVE_REGEX_H)
	/* added separation of path and pattern */
	/* path is allocated once, while FSPattern is handled dynamically...*/
	fname_split(path, &fpath, &fpattern);
	if(fpath) {
	  if(strlen(fpath)) {
	    strcpy(FSCurrentDirectory(fsw), fpath);
	  } else {
	    strcpy(FSCurrentDirectory(fsw), "/");
	  }
	  free(fpath);
	} else {
	  strcpy(FSCurrentDirectory(fsw), "/");
	}
	XtFree(FSPattern(fsw));
	if(fpattern) {
	  if(strlen(fpattern)) {
	    FSPattern(fsw) = StrCopy(fpattern);
	  } else {
	    FSPattern(fsw) = StrCopy("*");
	  }
	  free(fpattern);
	} else {
	  FSPattern(fsw) = StrCopy("*");
	}
#else
	strcpy(FSCurrentDirectory(fsw),path);
#endif

	Chdir(fsw);
} /* End ButtonGoto */


static void ButtonSelect(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	String file;

	file = GetFileBoxText(fsw);
	if (SelectFileByName(fsw,file) == False) XBell(XtDisplay(fsw),0);
	UpdateTextLines(fsw);
} /* End ButtonSelect */


static char *GetFileBoxText(fsw)
XfwfFileSelectorWidget fsw;
{
	char *text;
	Arg args[1];
	Widget file_box_widget;

	XtSetArg(args[0],XtNstring,(XtArgVal)(&text));
	file_box_widget = FSNthWidget(fsw,FS_I_CUR_FILE_TEXT);
	XtGetValues(file_box_widget,args,1);
	return(text);
} /* End GetFileBoxText */


static void ClickOnPathList(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	int i;
	XfwfScrolledListReturnStruct *ret;

	ret = (XfwfScrolledListReturnStruct *)call_data;
	if (ret->index == -1)
	{
		UnselectAll(fsw);		/* Click On Blank Space */
		return;
	}
	strcpy(FSCurrentDirectory(fsw),"/");
	for (i = 1; i <= ret->index; i++)
	{
		strcat(FSCurrentDirectory(fsw),FSPathList(fsw)[i]);
		strcat(FSCurrentDirectory(fsw),"/");
	}
	Chdir(fsw);
} /* End ClickOnPathList */


static void ClickOnFileList(w,fsw,call_data)
Widget w;
XfwfFileSelectorWidget fsw;
XtPointer call_data;
{
	XfwfScrolledListReturnStruct *ret;

	ret = (XfwfScrolledListReturnStruct *)call_data;
	if (ret->index == -1)
		UnselectAll(fsw);		/* Click On Blank Space */
	    else
		SelectFileByIndex(fsw,ret->index);
} /* End ClickOnFileList */


/*---------------------------------------------------------------------------*

             I N T E R N A L    S U P P O R T    R O U T I N E S

 *---------------------------------------------------------------------------*/

static void SelectFileByIndex(fsw,index)
XfwfFileSelectorWidget fsw;
int index;
{
	DirEntry *dir_entry;

	DirectoryMgrGotoItem(FSDirMgr(fsw),index);
	dir_entry = DirectoryMgrCurrentEntry(FSDirMgr(fsw));
	if (dir_entry == NULL)
	{
		fprintf(stderr,"SelectFileByIndex: Entry %d invalid\n",index);
		exit(-1);
	}
	if (DirEntryIsDir(dir_entry) || DirEntryIsDirectoryLink(dir_entry))
	{
		strcat(FSCurrentDirectory(fsw),DirEntryFileName(dir_entry));
		Chdir(fsw);
	}
	    else if (!DirEntryIsBrokenLink(dir_entry))	/* File */
	{
		strcpy(FSCurrentFile(fsw),DirEntryFileName(dir_entry));
		if (FSCheckExistence(fsw))
		{
			XtSetSensitive(FSNthWidget(fsw,FS_I_OK_BUTTON),True);
			XtSetSensitive(FSNthWidget(fsw,FS_I_CONTENTS_BUTTON),
				       True);
			XtSetSensitive(FSNthWidget(fsw,FS_I_AUTOSTART_BUTTON),
				       True);
		}
		FSFileSelected(fsw) = True;
		TextWidgetSetText(FSNthWidget(fsw,FS_I_CUR_FILE_TEXT),
				  FSCurrentFile(fsw));
		XfwfScrolledListHighlightItem(FSNthWidget(fsw,FS_I_FILE_LIST),
					  index);
		NotifySelectionChange(fsw);
	}
	    else					/* Broken Link */
	{
		XBell(XtDisplay(fsw),0);
		UnselectAll(fsw);
	}
} /* End SelectFileByIndex */


static Boolean SelectFileByName(fsw,name)
XfwfFileSelectorWidget fsw;
char *name;
{
	if (DirectoryMgrGotoNamedItem(FSDirMgr(fsw),name) == FALSE)
	{
		return(False);
	}
	SelectFileByIndex(fsw,DirectoryMgrCurrentIndex(FSDirMgr(fsw)));
	return(True);
} /* End SelectFileByName */


static void UnselectAll(fsw)
XfwfFileSelectorWidget fsw;
{
	Boolean old_file_selected_flag;

	old_file_selected_flag = FSFileSelected(fsw);
	if (FSCheckExistence(fsw))
	{
		XtSetSensitive(FSNthWidget(fsw,FS_I_OK_BUTTON),False);
		XtSetSensitive(FSNthWidget(fsw,FS_I_CONTENTS_BUTTON),False);
		XtSetSensitive(FSNthWidget(fsw,FS_I_AUTOSTART_BUTTON),False);
	}
	FSCurrentFile(fsw)[0] = '\0';
	FSFileSelected(fsw) = False;
	TextWidgetSetText(FSNthWidget(fsw,FS_I_CUR_FILE_TEXT),
			  FSCurrentFile(fsw));
	XfwfScrolledListUnhighlightAll(FSNthWidget(fsw,FS_I_FILE_LIST));
	if (old_file_selected_flag) NotifySelectionChange(fsw);
} /* End UnselectAll */


static void NotifySelectionChange(fsw)
XfwfFileSelectorWidget fsw;
{
	XfwfFileSelectorSelectionChangeReturnStruct ret;

	if (FSFileSelected(fsw) == True)
	{
		ret.file_selected = True;
		ret.path = FSCurrentDirectory(fsw);
		ret.file = FSCurrentFile(fsw);
	}
	    else
	{
		ret.file_selected = False;
		ret.path = NULL;
		ret.file = NULL;
	}
	XtCallCallbacks((Widget)fsw,XtNselectionChangeCallback,
			(XtPointer)&ret);
} /* End NotifySelectionChange */


/*---------------------------------------------------------------------------*

	ParentizeDirectory(dir)

	This routine takes a directory pathname <dir> and modifies the
	pathname to strip off the deepest directory, leaving just the parent
	path, and the trailing slash.  The parent directory of the root
	directory (a single slash) is the root directory.

        (bug fix by [EP] 10/31/96)
 *---------------------------------------------------------------------------*/

static void ParentizeDirectory(dir)
char *dir;
{
	char *end_of_dir;

	if (*dir != '\0')
	        for (end_of_dir = dir; *(end_of_dir + 1) != '\0'; ++ end_of_dir);
	else
	        end_of_dir = dir;
	if ((*end_of_dir == '/') && (end_of_dir != dir))
		-- end_of_dir;
	while ((*end_of_dir != '/') && (end_of_dir != dir))
	{
		-- end_of_dir;
	}
	if (*end_of_dir == '/')
	  ++ end_of_dir;
	*end_of_dir = '\0';
} /* End ParentizeDirectory */


/*---------------------------------------------------------------------------*

	GotoDeepestLegalDirectory(fsw)

	This function takes a FileSelector widget <fsw> and modifies the
	directory string in FSCurrentDirectory(fsw) to be the deepest
	legal directory above the string.  Partial or incorrect directory
	names are stripped starting at the end.

	This routine takes a File Selector widget <fsw> and updates
	the child widgets by recalculating their coordinates and
	setting the appropriate resources.  The old directory manager
	is closed and a new one is opened for this directory.  The
	file and path lists are deallocated, reallocated, and loaded
	with the path and file data lists.  The lists are then reset
	in the scrolled list widgets.

	This routine requires that all the child widgets have already
	been created.

	(added support for ~ as home directory, [EP] 10/15/96)
	(bugfix: invalid directory paths could cause an endless loop,
	[EP] 11/3/96)
	(fixed ~ bug, [EP] 06/09/97)
 *---------------------------------------------------------------------------*/

static void GotoDeepestLegalDirectory(fsw)
XfwfFileSelectorWidget fsw;
{
	char dir[MAXPATHLEN + 2];

	if (FSCurrentDirectory(fsw)[0] == '~')	/* [EP] 10/15/96 */
	{
	        char *p = strchr(FSCurrentDirectory(fsw), '/');

		if (p == NULL)
			strcpy(dir, getenv("HOME"));
		else
		        sprintf (dir, "%s/%s", getenv("HOME"), p + 1);
	}
	else
	{
		strcpy(dir,FSCurrentDirectory(fsw));
	}

	while (1)
	{
		/* [EP] 11/3/96 */
		if (*dir && !DirectoryMgrCanOpen(dir))
		{
			XBell(XtDisplay(fsw),0);
			if (strcmp(dir,"/") == 0)
			{
				fprintf(stderr,"%s: Can't open root\n",
					"GotoDeepestLegalDirectory");
				exit(1);
			}
			/*
			 * BUGFIX: moved the next line from before
			 * the if-statement, after a bug report by
			 * Andrew Robinson. [BB]
			 */
			ParentizeDirectory(dir);
		}
		    else if (!*dir) /* [EP] 11/3/96 */
		{
			getcwd(FSCurrentDirectory(fsw), MAXPATHLEN);
			strcat(FSCurrentDirectory(fsw), "/");
			break;
		}
		    else
		{
			DirectoryPathExpand(dir,FSCurrentDirectory(fsw));
			if (!DirectoryMgrCanOpen(dir))
				strcpy(FSCurrentDirectory(fsw),dir);
			break;
		}
	}
	UnselectAll(fsw);
	UpdateLists(fsw);
} /* End GotoDeepestLegalDirectory */


/*---------------------------------------------------------------------------*

	UpdateLists(fsw)

	This routine takes a FileSelector widget and builds new path
	and file lists from the current directory, sort mode, and pattern
	strings.  The lists and text items are then changed.

 *---------------------------------------------------------------------------*/

static void UpdateLists(fsw)
XfwfFileSelectorWidget fsw;
{
	int i,count;
	char *dir,*start;
	DirEntry *dir_entry;
	DirectoryMgr *dir_mgr;
	char temp[MAXPATHLEN + 2];

	if (FSDirMgr(fsw)) DirectoryMgrClose(FSDirMgr(fsw));
	dir_mgr = DirectoryMgrSimpleOpen(FSCurrentDirectory(fsw),
					 FSSortMode(fsw),
					 FSPattern(fsw));
	if (dir_mgr == NULL)
	{
		fprintf(stderr,"UpdateLists: Can't read directory '%s'\n",
			FSCurrentDirectory(fsw));
		exit(1);
	}

	FSDirMgr(fsw) = dir_mgr;
	if (FSPathList(fsw) != NULL)
	{
		for (i = 0; i < FSPathListCount(fsw); i++)
			free(FSPathList(fsw)[i]);
		free(FSPathList(fsw));
	}
	if (FSFileList(fsw) != NULL)
	{
		for (i = 0; i < FSFileListCount(fsw); i++)
			free(FSFileList(fsw)[i]);
		free(FSFileList(fsw));
	}

	FSFileListCount(fsw) = DirectoryMgrFilteredCount(FSDirMgr(fsw));
	FSPathListCount(fsw) = 1;
	for (dir = FSCurrentDirectory(fsw) + 1; *dir != '\0'; dir++)
	{
		if (*dir == '/') ++ FSPathListCount(fsw);
	}

	FSFileList(fsw) = (char **)malloc(sizeof(char *) *
					  (FSFileListCount(fsw) + 1));
	if (FSFileList(fsw) == NULL)
	{
		fprintf(stderr,"UpdateLists: Out of memory\n");
		exit(-1);
	}

	for (i = 0; i < FSFileListCount(fsw); i++)
	{
		dir_entry = DirectoryMgrNextEntry(FSDirMgr(fsw));
		if (dir_entry == NULL) XtError("Inconsistent Directory");
		strcpy(temp,DirEntryFileName(dir_entry));
		if (DirEntryIsDir(dir_entry))
			strcat(temp,"/");
		    else if (DirEntryIsBrokenLink(dir_entry))
			strcat(temp," X");
		    else if (DirEntryIsDirectoryLink(dir_entry))
			strcat(temp,"/");
		    else if (DirEntryIsSymLink(dir_entry) && FSFlagLinks(fsw))
			strcat(temp," @");

		FSFileList(fsw)[i] = StrCopy(temp);
	}
	FSFileList(fsw)[i] = NULL;

	FSPathList(fsw) = (char **)malloc(sizeof(char *) *
					  (FSPathListCount(fsw) + 1));
	start = FSCurrentDirectory(fsw);
	FSPathList(fsw)[0] = StrCopy("/");
	for (i = 1; i < FSPathListCount(fsw); i++)
	{
		while (*start != '\0' && *start == '/') ++start;
		count = 0;
		while (*start != '\0' && *start != '/')
			temp[count++] = *start++;
		temp[count++] = '\0';
		FSPathList(fsw)[i] = StrCopy(temp);
	}
	FSPathList(fsw)[i] = NULL;

	XfwfScrolledListSetList(FSNthWidget(fsw,FS_I_PATH_LIST),
			    FSPathList(fsw),FSPathListCount(fsw),True,NULL);
	XfwfScrolledListSetList(FSNthWidget(fsw,FS_I_FILE_LIST),
			    FSFileList(fsw),FSFileListCount(fsw),True,NULL);
	UpdateTextLines(fsw);
} /* End UpdateLists */


static void UpdateTextLines(fsw)
XfwfFileSelectorWidget fsw;
{
        /* [EP] 10/31/96: display '~' for $HOME */
        char tmpstr[2*MAXPATHLEN + 1], *home;
	int l;

	home = getenv ("HOME");
        l = strlen (home);
        if (!strncmp (FSCurrentDirectory(fsw), home, l)
	    && strlen (FSCurrentDirectory(fsw) - l + 1) < MAXPATHLEN) /* safety... */
	  {
	    sprintf (tmpstr, "~%s", FSCurrentDirectory(fsw) + l);
	    TextWidgetSetText (FSNthWidget (fsw, FS_I_CUR_DIR_TEXT),
			       tmpstr);
	  }
	else
          {
	    sprintf (tmpstr, "%s", FSCurrentDirectory(fsw) );
	  }

#if defined VICE && (defined HAVE_REGEXP_H || defined HAVE_REGEX_H)
	/* AF 26jun98 - add pattern to be able to edit it */
	if((!strlen(tmpstr)) || tmpstr[strlen(tmpstr)-1]!='/') {
	  strcat(tmpstr, "/");
	}
	strcat(tmpstr, FSPattern(fsw));
#endif

	TextWidgetSetText (FSNthWidget (fsw, FS_I_CUR_DIR_TEXT),
			       tmpstr);

	TextWidgetSetText(FSNthWidget(fsw,FS_I_CUR_FILE_TEXT),
			  FSCurrentFile(fsw));
} /* End UpdateTextLines */


static void Chdir(fsw)
XfwfFileSelectorWidget fsw;
{
	DoBusyCursor((Widget)fsw);
	GotoDeepestLegalDirectory(fsw);
	ChildrenUpdate(fsw);
	UndoBusyCursor((Widget)fsw);
} /* End Chdir */


static void DoBusyCursor(w)
Widget w;
{
#ifndef NO_BUSY_GRAB
	if (XtIsRealized(w))
	{
		XGrabPointer(XtDisplay(w),XtWindow(w),True,None,
			     GrabModeSync,GrabModeSync,None,FSBusyCursor(w),
			     CurrentTime);
	}
#endif
} /* End DoBusyCursor */


static void UndoBusyCursor(w)
Widget w;
{
#ifndef NO_BUSY_GRAB
	if (XtIsRealized(w))
	{
		XUngrabPointer(XtDisplay(w),CurrentTime);
	}
#endif
} /* End UndoBusyCursor */


static void TextWidgetSetText(tw,text)
Widget tw;
char *text;
{
	Arg args[3];
	int length,insert_position;
#ifdef X11R3
	static char text_widget_storage[MAXPATHLEN + 2];
#endif

	length = strlen(text);
	insert_position = max(length,0);
#ifdef X11R3
	/*
	XtTextSetInsertionPoint(tw,insert_position);
	XtSetArg(args[0],XtNstring,text);
	XtSetValues(tw,args,1);
	{
		XtTextBlock block;

		block.firstPos = 0;
		block.length = length + 1;
		block.ptr = text;
		block.format = FMT8BIT;
		XtTextReplace(fsw,0,block.length - 1,&block);
	}
	*/
#else
	XtSetArg(args[0],XtNstring,text);
	XtSetValues(tw,args,1);
#ifndef ENABLE_TEXTFIELD		/* [EP] 11/14/96 */
	XawTextSetInsertionPoint(tw,insert_position);
#else
	XtVaSetValues(tw,XtNinsertPosition,insert_position,NULL);
#endif
#endif
} /* End TextWidgetSetText */


/* [EP] 11/25/96 */
static void TextWidgetSetKeyboardFocusAction(w,event,params,num_params)
Widget w;
XEvent *event;			/* Unused */
String *params;
Cardinal *num_params;
{
	XtVaSetValues(FSNthWidget((XfwfFileSelectorWidget)XtParent(w),FS_I_CUR_DIR_TEXT),
		      XtNdisplayCaret,False,NULL);
	XtVaSetValues(FSNthWidget((XfwfFileSelectorWidget)XtParent(w),FS_I_CUR_FILE_TEXT),
		      XtNdisplayCaret,False,NULL);
	XtSetKeyboardFocus(XtParent(w),w);
	XtVaSetValues(w,XtNdisplayCaret,True,NULL);
}


/*---------------------------------------------------------------------------*

                    E X T E R N A L    R O U T I N E S

 *---------------------------------------------------------------------------*/

void XfwfFileSelectorChangeDirectory(fsw,dir)
XfwfFileSelectorWidget fsw;
char *dir;
{
	strcpy(FSCurrentDirectory(fsw),dir);
	Chdir(fsw);
} /* End XfwfFileSelectorChangeDirectory */


void XfwfFileSelectorRefresh(fsw)
XfwfFileSelectorWidget fsw;
{
	XfwfFileSelectorChangeDirectory(fsw,".");
} /* End XfwfFileSelectorRefresh */


void XfwfFileSelectorGetStatus(fsw,ssp)
XfwfFileSelectorWidget fsw;
XfwfFileSelectorStatusStruct *ssp;
{
	ssp->file_selected = FSFileSelected(fsw);
	ssp->path = FSCurrentDirectory(fsw);
	ssp->file = FSCurrentFile(fsw);
	ssp->file_box_text = GetFileBoxText(fsw);
} /* End XfwfFileSelectorGetStatus */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.