/*
 * actions.c : Widget action procedures
 *
 * This file defines the global actionTable used in XtAppAddActions() and
 * defines the action procedures, except those used on the settingsPanel
 * which are imported. Eventually there may be more actions, and they'll
 * be put here.
 *
 * George Ferguson, ferguson@cs.rochester.edu, 12 Nov 1991.
 *
 */

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/Cardinals.h>
#include "procquery.h"
#include "xarchie.h"
#include "types.h"
#include "appres.h"
#include "db.h"
#include "settings.h"		/* for settings actions */
#include "ftp.h"
#include "alert.h"
#include "confirm.h"
#include "dialog.h"
#include "regex.h"
extern char *progname;
extern Database *db;
extern abortDirsend();		/* dirsend.c */

/*
 * Functions defined here
 */
static void quitAction(),queryAction(),ftpAction();
static void saveAction(),abortAction();

/*
 * Data defined here:
 */
XtActionsRec actionTable[22] = {	/* check size in actions.h! */
    { "quit",			quitAction },
    { "query",			queryAction },
    { "ftp",			ftpAction },
    { "settings",		settingsAction },
    { "apply-settings",		applySettingsAction },
    { "default-settings",	defaultSettingsAction },
    { "done-settings",		doneSettingsAction },
    { "set-search-type",	setSearchTypeAction },
    { "set-search-type-now",	setSearchTypeNowAction },
    { "set-sort-type",		setSortTypeAction },
    { "set-sort-type-now",	setSortTypeNowAction },
    { "set-host",		setHostAction },
    { "set-host-now",		setHostNowAction },
    { "set-nice-level",		setNiceLevelAction },
    { "set-nice-level-now",	setNiceLevelNowAction },
    { "save-to-file",		saveAction },
    { "abort",			abortAction },
    { "alert-ok",		alertOk },
    { "confirm-yes",		confirmYes },
    { "confirm-no",		confirmNo },
    { "dialog-ok",		dialogOk },
    { "dialog-cancel",		dialogCancel },
};
static Boolean doingQuery;

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

/*ARGSUSED*/
static void
quitAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
    if (*num_params > ZERO || appResources.expert ||
					confirm0("Really quit xarchie?")) {
	XtDestroyApplicationContext(appContext);
	exit(0);
    }
}

/*ARGSUSED*/
static void
queryAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
    Arg args[1];
    char *s;
    int len;
    Boolean gif;

    if (doingQuery) {
	/* Don't do anything using popups since we could be in dirsend()
	   by now. */
	XBell(display,0);
	return;
    }
    XtSetArg(args[0],XtNstring,&s);
    XtGetValues(searchText,args,ONE);
    if (*s == '\0') {
	alert0("No search term specified.");
	return;
    }
#ifndef DONT_CATCH_GIFS
    len = strlen(s);
    gif = False;
    switch (appResources.searchType) {
	case GfExact:
	    gif = ((len > 4 &&
		    (!strcmp(s+len-4,".gif") || !strcmp(s+len-4,".GIF"))) ||
		   (len > 6 &&
		    (!strcmp(s+len-6,".gif.Z") || !strcmp(s+len-6,".GIF.Z"))));
	    break;
	case GfSubstr:
	case GfExactSubstr:
	case GfSubcase:
	case GfExactSubcase:
	    gif = (sindex(s,"gif") || sindex(s,"GIF"));
	    break;
	case GfRegexp:
	case GfExactRegexp:
	    gif = (re_comp(s) == NULL &&
		   (re_exec("@PrObAbLyNoTaFiLe@.gif") ||
		    re_exec("@PrObAbLyNoTaFiLe@.gif.Z")));
	    break;
    }
    if (gif) {
	if (!confirm0("Your search term will match GIFs. Do it anyway?"))
	    return;
	else if (appResources.niceLevel <= 0 &&
		 !confirm0("Really do it without increasing niceness?"))
	    return;
    }
#endif /* DONT_CATCH_GIFS */
    doingQuery = True;
    if (queryButton != NULL)
	XtSetSensitive(queryButton,False);
    if (abortButton != NULL)
	XtSetSensitive(abortButton,True);
    if (appResources.sortType == GfInvdate)
	procquery(appResources.archieHost,s,appResources.maxHits,
		  appResources.offset,appResources.searchType,True,0);
    else
	procquery(appResources.archieHost,s,appResources.maxHits,
		  appResources.offset,appResources.searchType,False,0);
    doingQuery = False;
    if (abortButton != NULL)
	XtSetSensitive(abortButton,False);
    if (queryButton != NULL)
	XtSetSensitive(queryButton,True);
}

/*ARGSUSED*/
static void
ftpAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
    if (selectedHostEntry == HOST_NULL || selectedLocEntry == LOC_NULL ||
	selectedFileEntry == FILE_NULL) {
	alert0("You must specify a host, location and file before invoking ftp()");
	return;
    }
    if (selectedFileEntry->modes[0] == 'd') {
	alert0("Sorry, can't fetch whole directories yet.");
	return;
    }
    ftp(selectedHostEntry->hostname,selectedLocEntry->linkpath,
	selectedFileEntry->name);
}

/*ARGSUSED*/
static void
saveAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
    static char filename[256];
    Arg args[1];
    char *s;
    FILE *fp;
    HostEntry *hostp;
    LocEntry *locp;
    FileEntry *filep;

    if (*num_params == ZERO) {
	if ((s=dialog("Filename to save to:",filename)) == NULL || *s == '\0')
	    return;
	strncpy(filename,s,255);
    } else if (*num_params == ONE) {
	XtSetArg(args[0],XtNstring,&s);
	XtGetValues(searchText,args,ONE);
 	sprintf(filename,*params,s);
    } else {
	fprintf(stderr,"%s: wrong number of args to \"save-to-file()\"",
								progname);
	return;
    }
    if ((fp=fopen(filename,"w")) == NULL) {
	alert1("Can't open %s for writing",filename);
	return;
    }
    status1("Writing %s...",filename);
    if (appResources.saveFormatOneLine) {
	for (hostp=db->hostEntries; hostp != NULL; hostp = hostp->next)
	    for (locp=hostp->locEntries; locp != NULL; locp = locp->next)
		for (filep=locp->fileEntries; filep != NULL; filep=filep->next)
		    fprintf(fp,"%s %10d  %s  %s:%s/%s\n",
			    filep->modes,filep->size,filep->date,
			    hostp->hostname,locp->linkpath,filep->name);
    } else {
	for (hostp=db->hostEntries; hostp != NULL; hostp = hostp->next) {
	    fprintf(fp,"%s\n",hostp->hostname);
	    for (locp=hostp->locEntries; locp != NULL; locp = locp->next) {
		fprintf(fp,"\t%s\n",locp->linkpath);
		for (filep=locp->fileEntries; filep != NULL; filep=filep->next)
		    fprintf(fp,"\t\t%s %10d  %s  %s\n",
			    filep->modes,filep->size,filep->date,filep->name);
	    }
	}
    }
    fclose(fp);
    status0("Ready");
}

/*ARGSUSED*/
static void
abortAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
    abortDirsend();
}
