/*************************************************************************
 * File: $Source: /usr/usrs/xsource/xmfm/RCS/utils.c,v $
 * Author: Jan Newmarch
 * Last modified: $Date: 1992/11/10 05:12:43 $
 * Version: $Revision: 1.6 $
 * Purpose: general purpose routines of use in various places
 *
 * Revision history:
 *	6 Aug 92	BusyCursor covers whole of a pane, rather than 1 widget
 *      22 Aug 92       NULL terminated string for tilde expansion
 *       3 Nov 92       lint-ed
 ************************************************************************/ 

#include "copyright.h"

/*************************************************************************
 * System includes
 ************************************************************************/ 
#ifdef vax11c
#include "param.h"
#else
#include <sys/param.h>
#endif /* vax11c */
#include <string.h>
#include <Xm/Xm.h>
#include <X11/cursorfont.h>
#ifdef vax11c
#include "pwd.h"
#else
#include <pwd.h>
#endif /* vax11c */

/*************************************************************************
 * Local includes
 ************************************************************************/ 
#include "DirMgr.h"
#include "types.h"

/*************************************************************************
 * Functions exported
 ************************************************************************/ 
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 GotoCurrentDir (
#ifdef UseFunctionPrototypes
	Widget w
#endif
);

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

/*************************************************************************
 * Extern variables
 ************************************************************************/ 

/*************************************************************************
 * Extern functions
 ************************************************************************/ 
extern char *getlogin ();   /* gcc (?) has no prototype for this */
extern void ErrorDialog (
#ifdef UseFunctionPrototypes
	char *str
#endif
);

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

/*************************************************************************
 * Local variables
 ************************************************************************/ 
static Window busy_window;
#define IS_WHITE_SPACE(ch)	((ch) == ' ' || (ch) == '\t' || (ch) == '\n')

/*************************************************************************
 * Function        : BusyCursor ()
 * Purpose         : make the cursor turn busy for this window
 * In parameters   : w
 * Out parameters  :
 * Side effects    :
 * Function returns:
 * Precondition    :
 * Postcondition   : cursor over current window is busy
 ************************************************************************/ 
void
BusyCursor 
#ifdef UseFunctionPrototypes
	(Widget toplevel)
#else
	(toplevel)
	Widget toplevel;

#endif
{  
        static Cursor watch = NULL; 
        unsigned long valuemask;
        XSetWindowAttributes attributes;
 
       	if(!watch)
               	watch = XCreateFontCursor(XtDisplay(toplevel),XC_watch);

        /* Ignore device events while the busy cursor is displayed. */
        valuemask = CWDontPropagate | CWCursor;
        attributes.do_not_propagate_mask =  (KeyPressMask | KeyReleaseMask |
           ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
        attributes.cursor = watch;

        /* The window will be as big as the display screen, and clipped by
           its own parent window, so we never have to worry about resizing */
        /* on multiple clicks, this function can get called multiple times.
           check that we haven't already got such a window mapped */
        if (busy_window != NULL)
                return;
        busy_window = XCreateWindow(XtDisplay(toplevel), XtWindow(toplevel), 0, 0,
                       65535, 65535, (unsigned int) 0, CopyFromParent, InputOnly,
                       CopyFromParent, valuemask, &attributes);
        XMapWindow (XtDisplay (toplevel), busy_window);
   

        XmUpdateDisplay(toplevel);

}

/*************************************************************************
 * Function        : UnBusyCursor ()
 * Purpose         : set it back again
 * In parameters   : w
 * Out parameters  :
 * Side effects    :
 * Function returns:
 * Precondition    :
 * Postcondition   : cursor is back to previous cursor
 ************************************************************************/ 
void
UnBusyCursor 
#ifdef UseFunctionPrototypes
	(Widget toplevel)
#else
	(toplevel)
	Widget toplevel;

#endif
{
        /* check that we have a window to destroy */
        if (busy_window == NULL)
               return;       
        XDestroyWindow (XtDisplay (toplevel), busy_window);
        busy_window = NULL;
}

/*************************************************************************
 * Function        : XtChdir ()
 * Purpose         : perform a chdir and report on any error. also does
 *	tilde expansion
 * In parameters   : dir
 * Out parameters  :
 * Side effects    :
 * Function returns: success or fail
 * Precondition    :
 * Postcondition   : application now in new dir (success)
 *		error dialog posted (failure)
 ************************************************************************/ 
Bool
XtChdir 
#ifdef UseFunctionPrototypes
	(char *dir)
#else
	(dir)
	char *dir;

#endif
{	char warning[MAXPATHLEN + 20];
	char full_dir[MAXPATHLEN];
	char name_buf[MAXPATHLEN];
#ifdef vax11c
	char dir_location[MAXPATHLEN+1];
	int  expanded;
#endif /* vax11c */
	char *name;
	char *orig_dir = dir;
        struct passwd *pw_ent;

#ifdef vax11c
	expanded = 0;
#endif /* vax11c */

	while (IS_WHITE_SPACE (*dir))
		dir++;

	/* should it undergo ~ expansion?
	*/ 
	if (*dir == '~')
	{	/* Found a tilde. This isn't full globbing.
		   We only have these cases:
			~
			~/...
			~name
			~name/...
		*/
		/* move past ~ */
		dir++;
		if ( *dir == '\0' || *dir == '/')
		{	/* name is login name */
#ifdef vax11c
			name = getenv("USER");
#else
			name = getlogin ();
#endif /* vax11c */
			/* dir now points to next char after user name */
		}
		else	/* name is someone else */
		{	char *p = dir;

			while ( ! IS_WHITE_SPACE (*p) &&
				*p != '/' && *p != '\0')
				p++;
                        /* leave space for \0 */
			strncpy (name_buf, dir, (int) (p - dir));
                        name_buf[(int) (p - dir)] = '\0';
			name = name_buf;

			dir = p;
			/* dir now points to next char after user name */
		}
		/* put in users home dir */
		pw_ent = getpwnam (name);
		if (pw_ent == NULL)
			/* no such user, restore original pattern */
			dir = orig_dir;
		else
		{
			strcpy (full_dir, pw_ent -> pw_dir);
			/* and what followed after */
			strcat (full_dir, dir);
			/* set dir to point to all of this */
			dir = full_dir;
#ifdef vax11c
			expanded = 1;
#endif /* vax11c */
		}
	}
#ifdef vax11c
	/*
	 *	Most of the time it will be a relative path
	 */
	if (!expanded) {
		register char *cp;

		/*
		 *	First locate the "[", if there then abort and continue
		 */
		cp = (char *)strchr(dir, '[');
		if (!cp) {
			/*
			 *	locate the ".", if not there then return
			 */
			cp = (char *)strchr(dir, '.');
			if (cp) {
				/*
				 *	Add the "[."
				 */
				dir_location[0] = '['; dir_location[1] = '.'; dir_location[2] = '\0';
				/*
				 *	Copy in the directory name
				 */
				strcat(dir_location, dir);
				/*
				 *	Re-aquire the "."
				 */
				cp = (char *)strrchr(dir_location, '.');
				/*
				 *	Add the "]" and null terminate it
				 */
				*cp++ = ']'; *cp = '\0';
				/*
				 *	Set dir pointing at the new stuff
				 */
				dir = dir_location;
			} else {
				strcpy (warning, "cannot chdir to ");
				strcat (warning, dir);
				fprintf (stderr, "%s\n", warning);
				return False;
			}
		}
	}
#endif /* vax11c */
	if (chdir (dir) == -1)
	{
		strcpy (warning, "cannot chdir to ");
		strcat (warning, dir);
/*
		ErrorDialog (warning);
*/
		fprintf (stderr, "%s\n", warning);
		return False;
	}
	return True;
}

/*************************************************************************
 * Function        : GotoCurrentDir ()
 * Purpose         : make sure we are in current dir
 * In parameters   : w
 * Out parameters  :
 * Side effects    :
 * Function returns:
 * Precondition    :
 * Postcondition   : application now in new dir
 ************************************************************************/ 
void
GotoCurrentDir 
#ifdef UseFunctionPrototypes
	(Widget w)
#else
	(w)
	Widget w;

#endif
{	dir_pane_info *dpi;

	XtVaGetValues (w,
			XmNuserData, &dpi,
			NULL);
	XtChdir (DirectoryPath (DirectoryMgrDir (dpi -> directory_manager)));
}
