/*
 * m-settings.c : Settings menu routines
 *
 * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
 */

#include <X11/Intrinsic.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>	/* Need rectangle part of SmeBSBObject */
#include <X11/Xaw/SmeBSBP.h>	/* See below, popupSubmenuAction()     */
#include "stringdefs.h"
#include "menu.h"
#include "xarchie.h"
#include "types.h"
#include "appres.h"
#include "browser.h"
#include "settings.h"
#include "status.h"

/*
 * Functions defined here:
 */
void initSettingsMenu();
void updateSettingsMenuMarks();
void setHostMenuMark(),setSearchMenuMark(),setSortMenuMark(),setNiceMenuMark();

static void settingsSubmenuAction();
static void settingsMenuCallback();
static void hostMenuCallback(),searchMenuCallback();
static void sortMenuCallback(),niceMenuCallback();
static void setHostMenuCallback(),setSearchMenuCallback();
static void setSortMenuCallback(),setNiceMenuCallback();
static void setAutoScrollMenuCallback();
static void ftpTypeMenuCallback(),ftpPromptMenuCallback();
static void ftpTraceMenuCallback(),ftpStripMenuCallback();

/*
 * Data defined here:
 */
static Widget settingsMenu;
static Widget hostMenu,searchMenu,sortMenu,niceMenu;
static Widget setHostMenu,setSearchMenu,setSortMenu,setNiceMenu;
static Widget setAutoScrollMenu;
static Widget ftpTypeMenu,ftpPromptMenu,ftpTraceMenu,ftpStripMenu;
static SmeBSBObject settingsMenuItems[5];
static SmeBSBObject *hostMenuItems,searchMenuItems[7];
static SmeBSBObject sortMenuItems[3],niceMenuItems[6];

static SearchType searchValues[] = {
    GfExact, GfSubstr, GfSubcase, GfRegexp,
    GfExactSubstr, GfExactSubcase, GfExactRegexp
};
static SortType sortValues[] = {
    GfName, GfDate, GfWeight
};
static int niceValues[] = {
 /* Default, Nice, Nicer, Very Nice, Extremely Nice, Nicest */
    0,       500,  1000,  5000,      10000,          32765
};
static Boolean autoScrollValues[] = {
    True, False
};

static char *ftpTypeValues[] = {
    "binary", "ascii"
};
static Boolean ftpPromptValues[] = {
    True, False
};
static Boolean ftpTraceValues[] = {
    True, False
};
static Boolean ftpStripValues[] = {
    True, False
};

static XtActionsRec actionTable[] = {
    { "settings-submenu",		settingsSubmenuAction },
};

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

void
initSettingsMenu()
{
    /* Add action for popup submenus */
    XtAppAddActions(appContext,actionTable,XtNumber(actionTable));
    /* This is the main Settings menu */
    settingsMenu = createMenu("settingsMenu","settingsMenuItem",5,
			      settingsMenuItems,settingsMenuCallback);
    /* Special case for hostMenu so it's easy to change */
    hostMenuItems = (SmeBSBObject *)XtCalloc(appResources.numHosts,
					     sizeof(SmeBSBObject));
    hostMenu = createMenu("hostMenu","hostMenuItem",
			  appResources.numHosts,hostMenuItems,
			  hostMenuCallback);
    setHostMenu = createMenu("setHostMenu","hostMenuItem",
			     appResources.numHosts,NULL,
			     setHostMenuCallback);
    /* These are submenus of the Settings menu */
    searchMenu = createMenu("searchMenu","searchMenuItem",7,searchMenuItems,
			    searchMenuCallback);
    sortMenu = createMenu("sortMenu","sortMenuItem",3,sortMenuItems,
			  sortMenuCallback);
    niceMenu = createMenu("niceMenu","niceMenuItem",6,niceMenuItems,
			  niceMenuCallback);
    /* These are for the settings panel (same labels, different callbacks) */
    setSearchMenu = createMenu("setSearchMenu","searchMenuItem",7,NULL,
			       setSearchMenuCallback);
    setSortMenu = createMenu("setSortMenu","sortMenuItem",3,NULL,
			     setSortMenuCallback);
    setNiceMenu = createMenu("setNiceMenu","niceMenuItem",6,NULL,
			     setNiceMenuCallback);
    setAutoScrollMenu = createMenu("setAutoScrollMenu","setAutoScrollMenuItem",
				   2,NULL,setAutoScrollMenuCallback);
    ftpTypeMenu = createMenu("ftpTypeMenu","ftpTypeMenuItem",2,
			     NULL,ftpTypeMenuCallback);
    ftpPromptMenu = createMenu("ftpPromptMenu","ftpPromptMenuItem",2,
			       NULL,ftpPromptMenuCallback);
    ftpTraceMenu = createMenu("ftpTraceMenu","ftpTraceMenuItem",2,
			       NULL,ftpTraceMenuCallback);
    ftpStripMenu = createMenu("ftpStripMenu","ftpStripMenuItem",2,
			       NULL,ftpStripMenuCallback);
    /* Initialize the menu marks */
    updateSettingsMenuMarks();
}

/*	-	-	-	-	-	-	-	-	*/
/* Action procedures */

/*
 * This function expects to be called from a BtnMotion event in the
 * settingsMenu ONLY. It looks after popping up the submenus, but only
 * if we've pulled right at least a bit.
 */
/*ARGSUSED*/
static void
settingsSubmenuAction(widget,event,params,num_params)
Widget widget;
XEvent *event;
String *params;
Cardinal *num_params;
{
    Arg args[2];
    Widget parent,popup;
    Window root,child;
    int x,y,cx,cy,item,item_y;
    Dimension w,h,item_h;
    unsigned int buttons;

    /* Where'd the event occur? */
    x = event->xmotion.x;
    y = event->xmotion.y;
    /* Check that it's in the menu */
    XtSetArg(args[0],XtNwidth,&w);
    XtSetArg(args[1],XtNheight,&h);
    XtGetValues(widget,args,2);
    if (x < 0 || x >= (int)w || y < 0 || y >= (int)h)
        return;
    /* Check that we've pulled right */
    if (x < (int)w/2)
	return;
    /* It is, figure out which item it's in */
    for (item=0; item < 4; item++) {
	/* Can't do GetValues on XtNy, for some reason. Oh well. */
	/* This is why we need those private header files above. */
	item_y = settingsMenuItems[item]->rectangle.y;
	item_h = settingsMenuItems[item]->rectangle.height;
	if (item_y < y && item_y + (int)item_h > y)
	    break;
    }
    /* Some items have popups, some don't */
    switch (item) {
	case 0: popup = hostMenu;
		break;
	case 1: popup = searchMenu;
		break;
	case 2: popup = sortMenu;
		break;
	case 3: popup = niceMenu;
		break;
	default: return;
    }
    parent = XtParent(widget);
    XQueryPointer(display,XtWindow(parent),
		  &root,&child,&x,&y,&cx,&cy,&buttons);
    /* Put the mouse solidly in the window */
    x -= 20;
    y -= 20;
    /* Position the menu */
    XtSetArg(args[0],XtNx,x);
    XtSetArg(args[1],XtNy,y);
    XtSetValues(popup,args,2);
    /* Pop it up */
    XtPopup(popup,XtGrabExclusive);
}

/*	-	-	-	-	-	-	-	-	*/
/* Callback procedures */

/*ARGSUSED*/
static void
settingsMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    switch (item) {
	case 0: /* Archie Host */
	case 1: /* Search Type */
	case 2: /* Sort Type */
	case 3: /* Nice Level */
	    break;
	case 4: /* Other */
	    item = 0;
	    XtCallActionProc((Widget)w,"popup-settings",(XEvent*)NULL,
			     (String*)NULL,item);
	    break;
    }
}

/*ARGSUSED*/
static void
hostMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;
    Arg args[1];
    char *str,*blank,c;

    setIthItemMark(hostMenuItems,item,appResources.numHosts);
    XtSetArg(args[0],XtNlabel,&str);
    XtGetValues((Widget)(hostMenuItems[item]),args,1);
    if ((blank=index(str,' ')) != NULL) {
	c = *blank;
	*blank = '\0';
    }
    XtFree(appResources.archieHost);
    appResources.archieHost = XtNewString(str);
    if (blank != NULL)
	*blank = c;
    updateSettingsHost(appResources.archieHost);
    status1("Set archie host to %s",appResources.archieHost);
}

/*ARGSUSED*/
static void
searchMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    setIthItemMark(searchMenuItems,item,XtNumber(searchMenuItems));
    appResources.searchType = searchValues[item];
    updateSettingsSearchType(appResources.searchType);
    status1("Set search type to %s",
	    searchTypeToString(appResources.searchType));
}

/*ARGSUSED*/
static void
sortMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    setIthItemMark(sortMenuItems,item,XtNumber(sortMenuItems));
    appResources.sortType = sortValues[item];
    updateSettingsSortType(appResources.sortType);
    resortBrowser();
    status1("Set sort type to %s",sortTypeToString(appResources.sortType));
}

/*ARGSUSED*/
static void
niceMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{

    int item = (int)client_data;

    setIthItemMark(niceMenuItems,item,XtNumber(niceMenuItems));
    appResources.niceLevel = niceValues[item];
    updateSettingsNiceLevel(appResources.niceLevel);
    status1("Set nice level to %d",(char *)appResources.niceLevel);
}

/*ARGSUSED*/
static void
setHostMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;
    Arg args[1];
    char *str,*blank,c;

    XtSetArg(args[0],XtNlabel,&str);
    XtGetValues((Widget)(hostMenuItems[item]),args,1);
    if ((blank=index(str,' ')) != NULL) {
	c = *blank;
	*blank = '\0';
    }
    updateSettingsHost(str);
    if (blank != NULL)
	*blank = c;
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
setSearchMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsSearchType(searchValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
setSortMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsSortType(sortValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
setNiceMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsNiceLevel(niceValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
setAutoScrollMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsAutoScroll(autoScrollValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
ftpTypeMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsFtpType(ftpTypeValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
ftpPromptMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsFtpPrompt(ftpPromptValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
ftpTraceMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsFtpTrace(ftpTraceValues[item]);
    setSettingsChangedFlag(True);
}

/*ARGSUSED*/
static void
ftpStripMenuCallback(w,client_data,call_data)
Widget w;
XtPointer client_data;	/* item */
XtPointer call_data;	/* ignored */
{
    int item = (int)client_data;

    updateSettingsFtpStrip(ftpStripValues[item]);
    setSettingsChangedFlag(True);
}

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

void
updateSettingsMenuMarks()
{
    setHostMenuMark(appResources.archieHost);
    setSearchMenuMark(appResources.searchType);
    setSortMenuMark(appResources.sortType);
    setNiceMenuMark(appResources.niceLevel);
}

/*
 * This function is more omcplicated than the others, since the value
 * of the archieHost resource (that we're getting passed here as the "host"
 * parameter) is a prefix of the corresponding menu label, since after
 * whitespace there can be informative garbage in the menu item.
 */
void
setHostMenuMark(host)
char *host;
{
    Arg args[1];
    char *str;
    int i,l;

    l = strlen(host);
    for (i=0; i < appResources.numHosts; i++) {
	XtSetArg(args[0],XtNlabel,&str);
	XtGetValues((Widget)(hostMenuItems[i]),args,1);
	/* Given host must match the entire prefix up to whitespace (if any) */
	if ((strlen(str) >= l) &&
	    (*(str+l) == '\0' || *(str+l) == ' ') &&
	    strncmp(str,host,l) == 0)
	    break;
    }
    if (i < appResources.numHosts)
	setIthItemMark(hostMenuItems,i,appResources.numHosts);
    else
	clearAllItemMarks(hostMenuItems,appResources.numHosts);
}

void
setSearchMenuMark(type)
SearchType type;
{
    int i;

    for (i=0; i < XtNumber(searchValues) && searchValues[i] != type; i++)
	/*EMPTY*/;
    if (i < XtNumber(searchValues))
	setIthItemMark(searchMenuItems,i,XtNumber(searchMenuItems));
}

void
setSortMenuMark(type)
SortType type;
{
    int i;

    for (i=0; i < XtNumber(sortValues) && sortValues[i] != type; i++)
	/*EMPTY*/;
    if (i < XtNumber(sortValues))
	setIthItemMark(sortMenuItems,i,XtNumber(sortMenuItems));
}

void
setNiceMenuMark(level)
int level;
{
    int i;

    for (i=0; i < XtNumber(niceValues) && niceValues[i] != level; i++)
	/*EMPTY*/;
    if (i < XtNumber(niceValues))
	setIthItemMark(niceMenuItems,i,XtNumber(niceMenuItems));
    else
	clearAllItemMarks(niceMenuItems,XtNumber(niceMenuItems));
}
