/***********************************************************************
 *
 * TITLE:
 *	selectfile.c
 *
 * AUTHOR:
 *	Kevin J. Miller, Ana Maria Guerrero
 *
 * DESCRIPTION:
 *	A generic OEL module.  It contains routines which initailize
 *	and control a popup use to select files for input and output.
 *
 *				CHANGE HISTORY
 *
 * $Log: selectfile.c,v $
 * Revision 1.15  1994/11/22  17:52:06  jeffb
 * add a new function to change the title of the file selection box
 * traverse to the file name text widget if using explicit keyboardFocusPolicy
 *
 * Revision 1.14  1994/01/06  21:42:08  kevin
 * updates after SGI test
 *
 * Revision 1.13  1994/01/06  05:12:06  kevin
 * port for V20
 *
 * Revision 1.12  1993/11/19  06:29:53  kevin
 * changed XmDIALOG_PRIMARY_APPLICATION_MODAL to
 * XmDIALOG_FULL_APPLICATION_MODAL
 *
 * Revision 1.11  1993/04/15  04:47:59  kevin
 * standardized and added new mesage functions
 *
 * Revision 1.10  1993/03/02  02:40:08  kevin
 * added shell management functions
 *
 * Revision 1.9  1992/08/05  21:02:12  kevin
 * added comments and standardized naming of functions
 *
 * Revision 1.8  1992/08/04  20:33:24  kevin
 * made extract_normal_string local
 *
 * Revision 1.7  1992/01/03  00:15:04  kevin
 * now use APPLICATION_PRIMARY_MODAL to allow focus to shift to help
 * dialogs
 *
 * Revision 1.6  1991/11/14  17:13:43  ana
 * Added help feature
 *
 * Revision 1.5  1991/10/04  16:54:32  ana
 * Added a warning for overwriting files.
 *
 * Revision 1.4  1991/06/15  00:39:20  kevin
 * put titles on dialog shells
 *
 * Revision 1.3  1991/06/10  20:57:15  kevin
 * set to return new filter value
 *
 * Revision 1.2  1991/04/12  01:11:31  kevin
 * added standard SFOC header
 *
 * Revision 1.1  1991/03/04  21:49:17  kevin
 * Initial revision
 *
 ***********************************************************************
 *
 * WARNINGS:
 *
 * EXTERNAL CALLABLE COMPONENTS (PUBLIC):
 *
 * GLOBALS:
 *
 * WAIVERS:
 *
 * NOTES:
 *
 * MANPAGE:
 *
 * NAME
 *	InitFileSelect, FileSelect - pops up modal file
 *	selection dialog box, and returns selected filename
 *	
 * SYNOPSIS
 *	InitFileSelect(parent, title)
 *	Widget parent;
 *	char *title;
 *
 *	FileSelect(txtptr, filter, bewareFlagP, token)
 *	char *txtptr;
 *	char *filter;
 *	int bewareFlagP;
 *	char *token;
 *
 *	FileSelectTitle(title)
 *	char *title;
 *
 * DESCRIPTION
 *	InitFileSelect is called once at the beginning of the
 *	program to initialize the dialog box.  Parent is the
 *	application shell returned by the XtAppCreateShell function.
 *	Title is the title on the mwm outline.  Filter is the default
 *	filter code.  BewareFlagP will cause the Beware dialog to
 *	appear if TRUE.  Token is used for to look up help.  This
 *	function does not return a value.
 *
 *	Selectfile will pop up the modal dialog box defined by the
 *	InitFileSelect function.  Txtptr is the returned file
 *	name.  If the user selected "Cancel" or closed the dialog,
 *	the array txtptr points to is unchanged.  Filter is a text
 *	string used to set directories or select specific file naming
 *	conventions.  Filter is returned back to the caller (the user
 *      can change the filter).  Selectfile returns TRUE if a file was
 *      selected (The "OK" button was pressed), and FALSE otherwise.
 *
 *	FileSelectTitle is used to change the title set by InitFileSelect.
 *
 ***********************************************************************/

#ifndef lint
static char rcsid[] =
    "$Id: selectfile.c,v 1.15 1994/11/22 17:52:06 jeffb OEL $";
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>

#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>

#include "selectfile.h"
#include "shellmgmt.h"
#include "message.h"
#include "beware.h"
#include "help.h"

/*
 * local function prototypes
 */
static void fileSelectOK(Widget, char *, XmSelectionBoxCallbackStruct *);
static void fileSelectCancel(Widget, char *, XmSelectionBoxCallbackStruct *);
static char *extractNormalString(XmString);

/*
 * local variables
 */
static Widget fileSelect;		/* FileSelectionBox widget */
static char *filename = NULL;		/* string containing file name */
static int flag = FALSE;		/* stay in this local event loop */
static int bewareFlag;			/* flag for beware box */
static XtAppContext app;		/* application context */

/***********************************************************************
 *
 * FUNCTION:
 *	InitFileSelect
 *
 * INPUTS:
 *	parent		- (Widget) the application shell
 *	title		- (char *) title for this popup
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	fileSelect	- (Widget) created and set by this function
 *	app		- (XtAppContext) set by this function
 *
 * DESCRIPTION:
 *	This fuction creates a FileSelectionBox widget and sets the
 *	callbacks and WM Close behavior.
 */

void 
InitFileSelect(Widget parent, char *title)
{
    XmString tmpString;			/* title of widget */
    Arg args[4];
    Cardinal n;

    app = XtWidgetToApplicationContext(parent);

    tmpString = XmStringCreateSimple(title);

    n = 0;
    XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
    XtSetArg(args[n], XmNdialogTitle, tmpString); n++;
    fileSelect = XmCreateFileSelectionDialog(parent, "fileSelectionBox",
	args, n);
    XtAddCallback(fileSelect, XmNokCallback,
	(XtCallbackProc)fileSelectOK, NULL);
    XtAddCallback(fileSelect, XmNcancelCallback,
	(XtCallbackProc)fileSelectCancel, NULL);

    XmStringFree(tmpString);

    /*
     * make MWM Close call the Cancel callback
     */
    ShellAddClose(fileSelect, (XtCallbackProc)fileSelectCancel, NULL);
}

/***********************************************************************
 *
 * FUNCTION:
 *	FileSelect
 *
 * INPUTS:
 *	filter		- (char *) filename filter
 *	bewareFlagP	- (int) use beware box if TRUE
 *	token		- (char *) lookup token for help
 *
 * OUTPUTS:
 *	txtptr		- (char *) returned filename
 *	filter		- (char *) filename filter
 *
 * RETURNS:
 *	TRUE		- on OK
 *	FALSE		- on Cancel
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 */

int 
FileSelect(char *txtptr, char *filter, int bewareFlagP,	char *token)
{
    XEvent event;		/* event structure for loop */
    XmString tmpString;		/* Motif compound string */
    char *ptr;			/* temporary character pointer */
    int value;			/* return value */
    Arg args[1];		/* Xt argument list */
    Cardinal n;			/* number of arguments */

    /*
     * set up help
     */
    XtRemoveAllCallbacks(fileSelect, XmNhelpCallback);
    XtAddCallback(fileSelect, XmNhelpCallback,
	(XtCallbackProc)ShowHelp, token);

    /*
     * set beware flag
     */
    bewareFlag = bewareFlagP;

    /*
     * set filter
     */
    tmpString = XmStringCreateSimple(filter);
    n = 0;
    XtSetArg(args[n], XmNdirMask, tmpString); n++;
    XtSetValues(fileSelect, args, n);
    ShellModalManage(fileSelect);
    XmStringFree(tmpString);

    /*
     * go directly to file name text widget if keyboardFocusPolicy is explicit
     */
    XmProcessTraversal(XmFileSelectionBoxGetChild(fileSelect,XmDIALOG_TEXT),
                       XmTRAVERSE_CURRENT);

    /*
     * loop until OK or Cancel
     */
    flag = TRUE;
    while (flag) {		/* local event loop for popup */
	XtAppNextEvent(app, &event);
	XtDispatchEvent(&event);
    }

    /*
     * return answer
     */
    if (filename != NULL) {		/* OK */

	/*
	 * copy filename
	 */
	ptr = filename;
	while ((*(txtptr++) = *(ptr++)));	/* strcpy */

	/*
	 * copy filter
	 */
	n = 0;
	XtSetArg(args[n], XmNdirMask, &tmpString); n++;
	XtGetValues(fileSelect, args, n);
	ptr = extractNormalString(tmpString);
	XmStringFree(tmpString);
	while ((*(filter++) = *(ptr++)));	/* strcpy */

	value = TRUE;
    } else {				/* cancel */
	value = FALSE;
    }
    return value;
}

/***********************************************************************
 *
 * FUNCTION:
 *	FileSelectTitle
 *
 * INPUTS:
 *	title		- (char *) new title for dialog box
 *
 * OUTPUTS:
 *	None
 *
 * RETURNS:
 *	None
 *
 * EXTERNALLY READ:
 *
 * EXTERNALLY MODIFIED:
 *
 * DESCRIPTION:
 *	Change title of file selection dialog box
 */

void 
FileSelectTitle(char *title)
{
    XmString tmpString;			/* title of widget */
    Arg args[4];
    Cardinal n;

    tmpString = XmStringCreateSimple(title);
    n = 0;
    XtSetArg(args[n], XmNdialogTitle, tmpString); n++;
    XtSetValues(fileSelect, args, n);
    XmStringFree(tmpString);
}

/***********************************************************************
 *
 * FUNCTION:
 *	fileSelectOK
 *
 * INPUTS:
 *	w		- (Widget) not used
 *	client_data	- (char *) not used
 *	callback_data	- (XmSelectionBoxCallbackStruct *) for filename
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	fileSelect	- (Widget) to unmanage
 *	bewareFlag	- (static int) if TRUE use beware box
 *
 * EXTERNALLY MODIFIED:
 *	flag		- (static int) set to FALSE
 *
 * DESCRIPTION:
 *	Callback for OK button.
 */

static void 
fileSelectOK(Widget w, char *client_data,
    XmSelectionBoxCallbackStruct *callback_data)
{
    char buf[256];
    struct stat statbuf;

    if (filename != NULL) {
	XtFree(filename);
	filename = NULL;
    }
    filename = extractNormalString(callback_data->value);
    if (bewareFlag) {
        sprintf(buf, "File %s exists.\nDo you wish to overwrite?", filename);
	if ((stat(filename, &statbuf)) || (Beware(buf))) {
	    ShellModalUnmanage(fileSelect);
	    flag = FALSE;               /* exit local loop */
	}
    } else {
    	ShellModalUnmanage(fileSelect);
    	flag = FALSE;		        /* exit local loop */
    }
}

/***********************************************************************
 *
 * FUNCTION:
 *	fileSelectCancel
 *
 * INPUTS:
 *	w		- (Widget) not used
 *	client_data	- (char *) not used
 *	callback_data	- (XmSelectionBoxCallbackStruct *) not used
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	none
 *
 * EXTERNALLY READ:
 *	fileSelect	- (Widget) to unmanage
 *
 * EXTERNALLY MODIFIED:
 *	flag		- (static int) set to FALSE
 *
 * DESCRIPTION:
 *	Callback for Cancel button.
 */

static void 
fileSelectCancel(Widget w, char *client_data,
    XmSelectionBoxCallbackStruct *callback_data)
{
    if (!ShellValidateClose(w)) {
	Warning("Illegal attempt to close File Select");
	return;
    }

    if (filename != NULL) {	/* set to NULL -> no file selected */
	XtFree(filename);
	filename = NULL;
    }
    ShellModalUnmanage(fileSelect);
    flag = FALSE;		/* exit local loop */
}

/***********************************************************************
 *
 * FUNCTION:
 *	extractNormalString
 *
 * INPUTS:
 *	cs		- (XmString) Motif compound string
 *
 * OUTPUTS:
 *	none
 *
 * RETURNS:
 *	primitiveString	- (char *) standard string
 *
 * EXTERNALLY READ:
 *	none
 *
 * EXTERNALLY MODIFIED:
 *	none
 *
 * DESCRIPTION:
 *	Extracts the first component from a Motif compound string as
 *	a character string.
 */

static char *
extractNormalString(XmString cs)
{
    XmStringContext context;
    XmStringCharSet charset;
    XmStringDirection direction;
    Boolean separator;
    static char *primitiveString;

    XmStringInitContext(&context, cs);
    XmStringGetNextSegment (context, &primitiveString, &charset,
	&direction, &separator);
    XmStringFreeContext (context);
    return primitiveString;
}
