/*************************************************************************
 * File: builtin.c
 * Author: Jan Newmarch
 * Last modified: $Date: 1992/11/17 00:35:36 $
 * Version: $Revision: 1.7 $
 * Purpose: Handle builtin calls to the file manager. These are calls that
 *	must be done internally (eg change directory) or for efficiency
 *	(none yet)
 * Revision history:
 *	4 Aug 92	filter part added to open dir
 *	6 Aug 92	busy cursor when changing/opening dir
 ************************************************************************/ 

#include "copyright.h"

/*************************************************************************
 * System includes
 ************************************************************************/ 
#include <stdio.h>

/*************************************************************************
 * Local includes
 ************************************************************************/ 
#include "types.h"
#include "const.h"
#include "xmvararg.h"

/*************************************************************************
 * Extern variables
 ************************************************************************/ 
extern XmString empty_string;
extern int pane_count;

/*************************************************************************
 * Extern functions
 ************************************************************************/ 
extern DirectoryMgr *GetFilesInDir (
#ifdef UseFunctionPrototypes
	void
#endif
);
extern void invert_colours (
#ifdef UseFunctionPrototypes
	Widget w
#endif
);
extern Widget CreateApplication (
#ifdef UseFunctionPrototypes
	Widget parent
#endif
);
extern Bool XtChdir (
#ifdef UseFunctionPrototypes
	char *dir
#endif
);
extern void BusyCursor (
#ifdef UseFunctionPrototypes
	Widget toplevel
#endif
);
extern void UnBusyCursor (
#ifdef UseFunctionPrototypes
	Widget toplevel
#endif
);
extern void builtin_info (
#ifdef UseFunctionPrototypes
	dir_pane_info *dpi
#endif
);
extern void ResetFilesInPanes (
#ifdef UseFunctionPrototypes
	dir_pane_info *dpi
#endif
);
extern void refresh_dir (
#ifdef UseFunctionPrototypes
	XtPointer client_data, XtIntervalId *id
#endif
);

/*************************************************************************
 * Functions exported
 ************************************************************************/ 
void builtin_command (
#ifdef UseFunctionPrototypes
	char *command, dir_pane_info *dpi
#endif
);
void builtin_chdir (
#ifdef UseFunctionPrototypes
	char *dir, dir_pane_info *dpi
#endif
);
void builtin_opendir (
#ifdef UseFunctionPrototypes
	char *dir, dir_pane_info *dpi
#endif
);

/*************************************************************************
 * Variables exported
 ************************************************************************/ 

/*************************************************************************
 * Forward functions
 ************************************************************************/ 

/*************************************************************************
 * Local variables
 ************************************************************************/ 


/*************************************************************************
 * Function: SetWMTitle()
 * Purpose: set the title of window and icon.
 * In parameters: dir, toplevel
 * Precondition:
 * Postcondition: title and icon title set to dir
 ************************************************************************/ 
static void
SetWMTitle 
#ifdef UseFunctionPrototypes
	(char *dir, Widget toplevel)
#else
	(dir, toplevel)
	char * dir;
	Widget toplevel;

#endif
{	char *p;
	int len;

	/* set the new window manager title
	   the icon will only show a small amount, so use end of path
	*/
	len = strlen (dir);
	if (strlen (dir) <= 1)
		/* root */
		p = dir;
	else
	{	/* backup over trailing / in dir */
		p = dir + len - 2;
		while (p > dir && *(p - 1) != '/' )
			p--;
	}

	XtVaSetValues (toplevel,
		XmNtitle, dir,
		XmNiconName, p,
		NULL);
}

/*************************************************************************
 * Function: builtin_chdir ()
 * Purpose: handle a change of directory request
 * In parameters: dir, dpi
 * Precondition: dir is an existing directory relative to current one
 * Postcondition: panes are repainted to show the new directory, and
 *                values are set in dpi for this.
 ************************************************************************/ 
void
builtin_chdir 
#ifdef UseFunctionPrototypes
	(char *dir, dir_pane_info *dpi)
#else
	(dir, dpi)
	char * dir;
	dir_pane_info *dpi;

#endif
{
	DirectoryMgr *dm;
	Widget *files_toolbar;
	int i;
#ifdef vax11c
	char new_path[MAXPATHLEN];
	register char *cp;
#endif /* vax11c */

#ifdef DEBUG
	fprintf (stderr, "built in: chdir %s\n", dir);
#endif
#ifdef vax11c
	/*
	 * format the path
	 */
	cp = strstr(dir, ".DIR");
	if (cp) {
		strcpy(new_path, dir);
		cp = strstr(new_path, ".DIR");
		*cp++ = ']';	*cp = '\0';
		cp = strchr(new_path, ']');
		*cp = '.';
	} else
		strcpy(new_path, dir);
	if (XtChdir(new_path) == False)
#else
	if (XtChdir (dir) == False)
#endif /* vax11c */
		/* chdir failed, no changes */
		return;

	/* turn off the highlighted dir */
	if (dpi -> file_selected != NULL)
		invert_colours (dpi -> file_button_selected);
	dpi -> file_button_selected = NULL;
	dpi -> file_selected = NULL;

	/* void the file toolbar */
	files_toolbar = dpi -> files_toolbar;
	for (i = 0; i < FILES_TOOLBAR_SIZE; i++)
	{	XtVaSetValues (files_toolbar[i],
				XmNlabelString, (XtArgVal) empty_string,
				NULL);
		XtSetSensitive (files_toolbar[i], False);
	}

	BusyCursor (dpi -> toplevel);
	DirectoryMgrClose (dpi -> directory_manager);
	dm = GetFilesInDir ();
	dpi -> directory_manager = dm;
	ResetFilesInPanes (dpi);
	UnBusyCursor (dpi -> toplevel);
	SetWMTitle (
		DirectoryPath (DirectoryMgrDir (dpi -> directory_manager)),
		dpi -> toplevel);
}


/*************************************************************************
 * Function: builtin_opendir ()
 * Purpose: handle a change of directory request
 * In parameters: dir, dpi
 * Precondition: dir is an existing directory relative to current one
 * Postcondition: panes are repainted to show the new directory, and
 *                values are set in dpi for this.
 ************************************************************************/ 
void
builtin_opendir 
#ifdef UseFunctionPrototypes
	(char *dir, dir_pane_info *dpi)
#else
	(dir, dpi)
	char * dir;
	dir_pane_info *dpi;

#endif
{
	Widget shell, dir_pane;
	dir_pane_info *new_dpi;

#ifdef DEBUG
	fprintf (stderr, "built in: opendir %s\n", dir);
#endif
	if (XtChdir (dir) == False)
		/* chdir failed, no changes */
		return;
	
	pane_count++;

	shell = XtCreateApplicationShell ("shell",
				vendorShellWidgetClass,
				NULL, 0);
/*
	shell = XtAppCreateShell ("shell",
				vendorShellWidgetClass,
				NULL, 0);
*/

	dir_pane = CreateApplication (shell);
	XtManageChild (dir_pane);

	XtPopup (shell, XtGrabNone);

        /* set files in panes */
        XtVaGetValues (dir_pane,
                        XmNuserData, (XtArgVal) &new_dpi,
                        NULL);

	/* copy over filters */
	new_dpi -> file_filter = XtMalloc (strlen (dpi -> file_filter) + 1);	
	strcpy (new_dpi -> file_filter, dpi -> file_filter);

	/* a compiled regexp is an opaque string, that I suspect may
	   contain NULL bytes. To stop strcpy stopping on them, use
	   bcopy instead
	*/
#ifdef vax11c
	/*
	 *	Under VMS this is a pointer, not a static array
	 */
	new_dpi -> file_filter_regexp = (char *)XtMalloc(FSM_LENGTH);
	if ( !new_dpi -> file_filter_regexp ) {
		fprintf(stderr, "Out of memory in builtin_opendir, unable to allocate a new file_filter regexp!\n");
		exit(1);
	}
#endif /* vax11c */
	bcopy (dpi -> file_filter_regexp, new_dpi -> file_filter_regexp,
		FSM_LENGTH);

	new_dpi -> dir_filter = XtMalloc (strlen (dpi -> dir_filter) + 1);	
	strcpy (new_dpi -> dir_filter, dpi -> dir_filter);

#ifdef vax11c
	/*
	 *	Under VMS this is a pointer, not a static array
	 */
	new_dpi -> dir_filter_regexp = (char *)XtMalloc(FSM_LENGTH);
	if ( !new_dpi -> dir_filter_regexp ) {
		fprintf(stderr, "Out of memory in builtin_opendir, unable to allocate a new dir_filter regexp!\n");
		exit(1);
	}
#endif /* vax11c */
	bcopy (dpi -> dir_filter_regexp, new_dpi -> dir_filter_regexp,
		FSM_LENGTH);

	new_dpi -> executable_filter = 
		XtMalloc (strlen (dpi -> executable_filter) + 1);	
	strcpy (new_dpi -> executable_filter, dpi -> executable_filter);

#ifdef vax11c
	/*
	 *	Under VMS this is a pointer, not a static array
	 */
	new_dpi -> executable_filter_regexp = (char *)XtMalloc(FSM_LENGTH);
	if ( !new_dpi -> executable_filter_regexp ) {
		fprintf(stderr, "Out of memory in builtin_opendir, unable to allocate a new executable_filter regexp!\n");
		exit(1);
	}
#endif /* vax11c */
	bcopy (dpi -> executable_filter_regexp, 
		new_dpi -> executable_filter_regexp,
		FSM_LENGTH);

        SetFiltersInLabels (new_dpi);

	/* and now set the files in the panes */
	BusyCursor (new_dpi -> toplevel);
        ResetFilesInPanes (new_dpi);
	SetActionsInDirsToolbar (new_dpi);
	UnBusyCursor (new_dpi -> toplevel);

	SetWMTitle (
		DirectoryPath (DirectoryMgrDir (dpi -> directory_manager)),
		dpi -> toplevel);

}



/*************************************************************************
 * Function: builtin_command ()
 * Purpose: handle any of the builtin commands
 * In parameters: command
 * Out parameters:
 * Precondition:command is a non-null builtin command
 * Postcondition: builtin command has been executed
 ************************************************************************/ 
void
builtin_command 
#ifdef UseFunctionPrototypes
	(char *command, dir_pane_info *dpi)
#else
	(command, dpi)
	char *command;
	dir_pane_info *dpi;

#endif
{
	/* these start with a $ - lose that, and then look */
	command++;
	
	if (strncmp (command, CHDIR_COMMAND, LEN_CHDIR_COMMAND) == 0)
	{
		/* lose the builtin part */
		command += LEN_CHDIR_COMMAND + 1;
		builtin_chdir (command, dpi);
		return;
	}
	
	if (strncmp (command, OPENDIR_COMMAND, LEN_OPENDIR_COMMAND) == 0)
	{
		/* lose the builtin part */
		command += LEN_OPENDIR_COMMAND + 1;
		builtin_opendir (command, dpi);
		return;
	}
	if (strncmp (command, INFO_COMMAND, LEN_INFO_COMMAND) == 0)
	{
		builtin_info (dpi);
		return;
	}
#ifdef vax11c
	if (strncmp (command, REFRESH_COMMAND, LEN_REFRESH_COMMAND) == 0)
	{
		XtAddTimeOut (0, refresh_dir, dpi);
		return;
	}
#endif /* vax11c */
}
