/*
 * view-file.c : Routines for the windows when files are "opened" via ftp
 *
 * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
 */
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/AsciiText.h>
#include "config.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include "xarchie.h"
#include "fchooser.h"
#include "stringdefs.h"
#include "xutil.h"
#include "syserr.h"
#include "debug.h"

/*
 * Functions defined here:
 */
void viewFile();

static void nonmaskableEventHandler();
static void viewDone(),viewDown(),viewUp(),viewSave();
static void viewSaveOk(),viewSaveCancel();
static int fileCopy();

/*
 * Data defined here:
 */
typedef struct _ViewFileInfo {
    Widget shell;
    Widget text;
    String filename;
} ViewFileInfo;

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

void
viewFile(filename)
char *filename;
{
    ViewFileInfo *vfinfo;
    Widget form,button;
    Arg args[2];

    vfinfo = XtNew(ViewFileInfo);
    vfinfo->filename = XtNewString(filename);
    XtSetArg(args[0],XtNtitle,filename);
    vfinfo->shell = XtCreatePopupShell("viewShell",topLevelShellWidgetClass,
				       toplevel,args,1);
    form = XtCreateManagedWidget("viewForm",formWidgetClass,
				 vfinfo->shell,NULL,0);
    button = XtCreateManagedWidget("viewDoneButton",commandWidgetClass,
				   form,NULL,0);
    XtAddCallback(button,XtNcallback,viewDone,(XtPointer)vfinfo);
    button = XtCreateManagedWidget("viewDownButton",commandWidgetClass,
				   form,NULL,0);
    XtAddCallback(button,XtNcallback,viewDown,(XtPointer)vfinfo);
    button = XtCreateManagedWidget("viewUpButton",commandWidgetClass,
				   form,NULL,0);
    XtAddCallback(button,XtNcallback,viewUp,(XtPointer)vfinfo);
    button = XtCreateManagedWidget("viewSaveButton",commandWidgetClass,
				   form,NULL,0);
    XtAddCallback(button,XtNcallback,viewSave,(XtPointer)vfinfo);
    XtSetArg(args[0],XtNtype,XawAsciiFile);
    XtSetArg(args[1],XtNstring,filename);
    vfinfo->text = XtCreateManagedWidget("viewText",asciiTextWidgetClass,
					 form,args,2);
    XtRealizeWidget(vfinfo->shell);
    /* Allow WM_DELETE_WINDOW to the Shell to be Done */
    (void)XSetWMProtocols(XtDisplay(vfinfo->shell),XtWindow(vfinfo->shell),
			  &WM_DELETE_WINDOW,1);
    XtAddEventHandler(vfinfo->shell,NoEventMask,True,
		      nonmaskableEventHandler,(XtPointer)vfinfo);
    XtPopup(vfinfo->shell,XtGrabNone);
}

/*
 * Nonmaskable event handler for Shell: If the event is a ClientMessage
 * of WM_PROTOCOLS then act as if Done had been clicked.
 */
/*ARGSUSED*/
static void
nonmaskableEventHandler(w,client_data,event,continue_to_dispatch)
Widget w;
XtPointer client_data;
XEvent *event;
Boolean *continue_to_dispatch;
{
    DEBUG1("nonmaskableHandler: w=0x%x\n",w);
    if (event->type == ClientMessage &&
        event->xclient.data.l[0] == WM_DELETE_WINDOW) {
	DEBUG0("nonmaskableHandler: calling cancelButtonCallback\n");
	viewDone(NULL,client_data,NULL);
    }
    DEBUG0("nonmaskableHandler: done\n");
}

/*	-	-	-	-	-	-	-	-	*/
/* Callbacks for the view window */

/*ARGSUSED*/
static void
viewDone(w,client_data,call_data)
Widget w;
XtPointer client_data;		/* ViewFileInfo */
XtPointer call_data;		/* not used */
{
    ViewFileInfo *vfinfo = (ViewFileInfo *)client_data;
    char *name;

    DEBUG0("viewDone...\n");
    name = getWidgetString(vfinfo->text);
    if (name != NULL && *name != '\0') {
	DEBUG1("viewDone: unlinking \"%s\"\n",name);
	if (unlink(name) < 0)
	    sysError(name);
    }
    XtPopdown(vfinfo->shell);
    XtUnrealizeWidget(vfinfo->shell);
    XtDestroyWidget(vfinfo->shell);
    XtFree(vfinfo->filename);
    XtFree((char*)vfinfo);
    DEBUG0("viewDone: done\n");
}

/*ARGSUSED*/
static void
viewDown(w,client_data,call_data)
Widget w;
XtPointer client_data;		/* ViewFileInfo */
XtPointer call_data;		/* not used */
{
    ViewFileInfo *vfinfo = (ViewFileInfo *)client_data;

    XtCallActionProc(vfinfo->text,"next-page",NULL,NULL,0);
}

/*ARGSUSED*/
static void
viewUp(w,client_data,call_data)
Widget w;
XtPointer client_data;		/* ViewFileInfo */
XtPointer call_data;		/* not used */
{
    ViewFileInfo *vfinfo = (ViewFileInfo *)client_data;

    XtCallActionProc(vfinfo->text,"previous-page",NULL,NULL,0);
}

/*ARGSUSED*/
static void
viewSave(w,client_data,call_data)
Widget w;
XtPointer client_data;		/* ViewFileInfo */
XtPointer call_data;		/* not used */
{
    ViewFileInfo *vfinfo = (ViewFileInfo *)client_data;
    FileChooserInfo *fcinfo;
    Widget shell,form,text;
    char *name,*basename;
    Arg args[1];

    DEBUG0("viewSave...\n");
    setBusyStatus(True);
    shell = XtCreatePopupShell("viewSaveShell",topLevelShellWidgetClass,
			       vfinfo->shell,NULL,0);
    form = XtCreateManagedWidget("viewSaveForm",formWidgetClass,
				 shell,NULL,0);
    (void)XtCreateManagedWidget("viewSaveLabel",labelWidgetClass,
				form,NULL,0);
    text = XtCreateManagedWidget("viewSaveLabelText",asciiTextWidgetClass,
				 form,NULL,0);
    name = vfinfo->filename;
    setWidgetString(text,name);
    fcinfo = createFileChooser(shell,form,"viewSave",viewSaveOk,
			       viewSaveCancel,(XtPointer)vfinfo);
    /* Adjust vertical layout */
    XtSetArg(args[0],XtNfromVert,text);
#ifdef FILECHOOSER
    XtSetValues(fcinfo->fcw,args,1);
#else
    XtSetValues(fcinfo->text,args,1);
#endif
    /* Realize them all */
    XtRealizeWidget(shell);
    /* Set initial filename (has to be after realize for some reason) */
    if ((basename=rindex(name,'/')) != NULL)
	name = basename+1;
    setWidgetString(fcinfo->text,name);
    /* Register window for WM */
    (void)XSetWMProtocols(XtDisplay(shell),XtWindow(shell),
			  &WM_DELETE_WINDOW,1);
    /* Here we go */
    XtPopup(shell,XtGrabNone);
    setBusyStatus(False);
    DEBUG0("viewSave: done\n");
}

/*	-	-	-	-	-	-	-	-	*/
/* Callbacks from the view-save FileChooser */

/*ARGSUSED*/
static void
viewSaveOk(fcinfo,filename,client_data)
FileChooserInfo *fcinfo;
char *filename;
XtPointer client_data;		/* ViewFileInfo */
{
    ViewFileInfo *vfinfo = (ViewFileInfo *)client_data;

    DEBUG1("viewSaveOk: fcinfo=0x%x\n",fcinfo);
    DEBUG2("viewSaveOk: copying \"%s\" to \"%s\"\n",vfinfo->filename,filename);
    if (fileCopy(vfinfo->filename,filename) >= 0) {
	/* Remove the File Selector if successful */
	XtPopdown(fcinfo->shell);
	XtUnrealizeWidget(fcinfo->shell);
	XtDestroyWidget(fcinfo->shell);
	XtFree((char*)fcinfo);
    }
    DEBUG0("viewSaveOk: done\n");
}

/*ARGSUSED*/
static void
viewSaveCancel(fcinfo,client_data)
FileChooserInfo *fcinfo;
XtPointer client_data;		/* ViewFileInfo */
{
    DEBUG1("viewSaveCancel: fcinfo=0x%x\n",fcinfo);
    XtPopdown(fcinfo->shell);
    XtUnrealizeWidget(fcinfo->shell);
    XtDestroyWidget(fcinfo->shell);
    XtFree((char*)fcinfo);
    DEBUG0("viewSaveCancel: done\n");
}

/*	-	-	-	-	-	-	-	-	*/
/* Misc. functions */

static int
fileCopy(path1,path2)
char *path1,*path2;
{
    FILE *infp,*outfp;
    char buf[BUFSIZ];
    int n,retcode;

    DEBUG2("fileCopy: \"%s\" \"%s\"\n",path1,path2);
    if ((infp=fopen(path1,"r")) == NULL) {
	sysError(path1);
	return(-1);
    }
    if ((outfp=fopen(path2,"w")) == NULL) {
	sysError(path2);
	return(-1);
    }
    retcode = 0;
    while (!feof(infp)) {
	if ((n=fread(buf,1,sizeof(buf),infp)) <= 0) {
	    sysError("read");
	    retcode = -1;
	    break;
	}
	if (fwrite(buf,1,n,outfp) != n) {
	    sysError("write");
	    retcode = -1;
	    break;
	}
    }
    fclose(infp);
    fclose(outfp);
    DEBUG0("fileCopy: done\n");
    return(retcode);
}
