/* 
** OpenURL - MUI preferences for openurl.library
** Written by Troels Walsted Hansen <troels@stud.cs.uit.no>
** Placed in the public domain.
**
** This module contains the code to the PrefsWin Window.mui subclass.
*/

#include "urlprefs.h"

/**************************************************************************/

#define myPopButton(image)\
	ImageObject,\
		ImageButtonFrame,\
		MUIA_InputMode,            MUIV_InputMode_RelVerify,\
		MUIA_Background,           MUII_ButtonBack,\
		MUIA_CycleChain,           TRUE,\
		MUIA_Image_Spec,           image,\
		MUIA_Image_FontMatchWidth, TRUE,\
		MUIA_Image_FreeVert,       TRUE,\
		End

#define myKeyCheckMark(selected,control)\
	ImageObject,\
		ImageButtonFrame,\
		MUIA_InputMode        , MUIV_InputMode_Toggle,\
		MUIA_Image_Spec       , MUII_CheckMark,\
		MUIA_Image_FreeVert   , TRUE,\
		MUIA_CycleChain       , TRUE,\
		MUIA_Selected         , selected,\
		MUIA_Background       , MUII_ButtonBack,\
		MUIA_ShowSelState     , FALSE,\
		MUIA_ControlChar      , control,\
		End

/**************************************************************************/

#define MUISN_TWH        328 /* put your OWN serialnumber here! */
#define TAG_MUI_TWH      (TAG_USER | ( MUISN_TWH << 16))
#define TAGBASE_PREFSWIN (TAG_MUI_TWH)

#define MUIM_PrefsWin_Add                    (TAGBASE_PREFSWIN + 0)
#define MUIM_PrefsWin_Clone                  (TAGBASE_PREFSWIN + 1)
#define MUIM_PrefsWin_ActiveChanged          (TAGBASE_PREFSWIN + 2)
#define MUIM_PrefsWin_EntriesChanged         (TAGBASE_PREFSWIN + 3)
#define MUIM_PrefsWin_EntryChanged           (TAGBASE_PREFSWIN + 4)
#define MUIM_PrefsWin_StorePrefs             (TAGBASE_PREFSWIN + 5)

struct MUIP_PrefsWin_Add                     { ULONG MethodID; };
struct MUIP_PrefsWin_Clone                   { ULONG MethodID; };
struct MUIP_PrefsWin_ActiveChanged           { ULONG MethodID; };
struct MUIP_PrefsWin_EntriesChanged          { ULONG MethodID; ULONG Entries; };
struct MUIP_PrefsWin_EntryChanged            { ULONG MethodID; ULONG Redraw; };
struct MUIP_PrefsWin_StorePrefs              { ULONG MethodID; ULONG How; };

#define MUIV_PrefsWin_StorePrefs_Save 0
#define MUIV_PrefsWin_StorePrefs_Use  1

/**************************************************************************/

static ULONG mNew           (struct IClass *cl, Object *obj, struct opSet *msg);
static ULONG mWindow_Setup  (struct IClass *cl, Object *obj, struct MUIP_Window_Setup *msg);
static ULONG mAdd           (struct IClass *cl, Object *obj, struct MUIP_PrefsWin_Add *msg);
static ULONG mClone         (struct IClass *cl, Object *obj, struct MUIP_PrefsWin_Clone *msg);
static ULONG mActiveChanged (struct IClass *cl, Object *obj, struct MUIP_PrefsWin_ActiveChanged *msg);
static ULONG mEntriesChanged(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_EntriesChanged *msg);
static ULONG mEntryChanged  (struct IClass *cl, Object *obj, struct MUIP_PrefsWin_EntryChanged *msg);
static ULONG mStorePrefs    (struct IClass *cl, Object *obj, struct MUIP_PrefsWin_StorePrefs *msg);

static SAVEDS ASM APTR ConstructFunc(REG(a0) struct Hook *hook, REG(a2) APTR pool, REG(a1) struct URL_BrowserNode *bn);
static SAVEDS ASM VOID DestructFunc (REG(a0) struct Hook *hook, REG(a2) APTR pool, REG(a1) struct URL_BrowserNode *bn);
static SAVEDS ASM LONG DisplayFunc  (REG(a0) struct Hook *hook, REG(a2) char **array, REG(a1) struct URL_BrowserNode *bn);

static ULONG STDARGS DoSuperNew(struct IClass *cl, Object *obj, ULONG tag1, ...);

/**************************************************************************/

enum { MEN_ABOUTMUI=1,MEN_HIDE,MEN_QUIT,
       MEN_MUISETTINGS,MEN_SNAPSHOT,MEN_UNSNAPSHOT };

struct NewMenu PrefsWinMenu[] =
{
	{ NM_TITLE, "Project"                 , 0 ,0,0,(APTR)0               },
	{ NM_ITEM , "About MUI..."            ,"¿",0,0,(APTR)MEN_ABOUTMUI    },
	{ NM_ITEM , (STRPTR)NM_BARLABEL       , 0 ,0,0,(APTR)0               },
	{ NM_ITEM , "Hide"                    ,"H",0,0,(APTR)MEN_HIDE        },
	{ NM_ITEM , (STRPTR)NM_BARLABEL       , 0 ,0,0,(APTR)0               },
	{ NM_ITEM , "Quit"                    ,"Q",0,0,(APTR)MEN_QUIT        },

	{ NM_TITLE, "Settings"                , 0 ,0,0,(APTR)0               },
	{ NM_ITEM , "MUI..."                  ,"M",0,0,(APTR)MEN_MUISETTINGS },
	{ NM_ITEM , (STRPTR)NM_BARLABEL       , 0 ,0,0,(APTR)0               },
	{ NM_ITEM , "Snapshot window"         ,"W",0,0,(APTR)MEN_SNAPSHOT    },
	{ NM_ITEM , "Unsnapshot window"       ,"U",0,0,(APTR)MEN_UNSNAPSHOT  },

	{ NM_END,NULL,0,0,0,(APTR)0 },    
};    

/**************************************************************************/

static ULONG mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
	Object *infog, *names, *paths, *ports, *cmdlineurlc, *cmdg, *shows, 
	       *tofronts, *openurls, *openurlws, *browserl, *addb, *cloneb, 
	       *deleteb, *saveb, *useb, *cancelb;

	obj = (Object *)DoSuperNew(cl, obj,
		MUIA_Window_ID,          MAKE_ID('U', 'R', 'L', 'P'),
		MUIA_Window_Title,       APPNAME " Library Preferences",
		MUIA_Window_ScreenTitle, APPNAME " " APPVER ". " APPREV " " __AMIGADATE__ " by " APPAUTHOR,
		MUIA_Window_Menustrip,   MUI_MakeObject(MUIO_MenustripNM, PrefsWinMenu, 0),
		WindowContents, VGroup,
			Child, infog = ColGroup(2),
				GroupFrameT("Browser information"),

				Child, KeyLabel2("Name", 'n'),
				Child, names = StringObject, 
					StringFrame,
					MUIA_CycleChain,    TRUE,
					MUIA_ControlChar,   'n',
					MUIA_String_MaxLen, UBN_NAME_LEN,
				End,

				Child, KeyLabel2("Path", 'p'),
				Child, PopaslObject, 
					MUIA_Popstring_String, paths = StringObject, 
						StringFrame,
						MUIA_CycleChain,    TRUE,
						MUIA_ControlChar,   'p',
						MUIA_String_MaxLen, UBN_PATH_LEN,
					End,
					MUIA_Popstring_Button, myPopButton(MUII_PopFile),
					MUIA_Popasl_Type,      ASL_FileRequest,
				End,

				Child, KeyLabel2("ARexx port", 'x'),
				Child, PopportObject, 
					MUIA_Popstring_String, ports = StringObject, 
						StringFrame,
						MUIA_CycleChain,    TRUE,
						MUIA_ControlChar,   'x',
						MUIA_String_MaxLen, UBN_PORT_LEN,
					End,
					MUIA_Popstring_Button,  myPopButton(MUII_PopUp),
					MUIA_Popport_ARexxOnly, TRUE,
				End,

				Child, RectangleObject, End,
				Child, HGroup,
					Child, RectangleObject, End,
					Child, KeyLabel2("Accepts URL as commandline argument", 't'),
					Child, cmdlineurlc = myKeyCheckMark(FALSE, 't'),
				End,
			End,

			Child, cmdg = ColGroup(2),
				GroupFrameT("ARexx commands"),

				Child, KeyLabel2("Show/Uniconify", 'i'),
				Child, shows = StringObject, 
					StringFrame,
					MUIA_CycleChain,    TRUE,
					MUIA_ControlChar,   'i',
					MUIA_String_MaxLen, UBN_SHOWCMD_LEN,
				End,

				Child, KeyLabel2("Screen to front", 'f'),
				Child, tofronts = StringObject, 
					StringFrame,
					MUIA_CycleChain,    TRUE,
					MUIA_ControlChar,   'f',
					MUIA_String_MaxLen, UBN_TOFRONTCMD_LEN,
				End,

				Child, KeyLabel2("Open URL...", 'o'),
				Child, openurls = StringObject, 
					StringFrame,
					MUIA_CycleChain,    TRUE,
					MUIA_ControlChar,   'o',
					MUIA_String_MaxLen, UBN_OPENURLCMD_LEN,
				End,

				Child, KeyLabel2("...in new window", 'w'),
				Child, openurlws = StringObject, 
					StringFrame,
					MUIA_CycleChain,    TRUE,
					MUIA_ControlChar,   'w',
					MUIA_String_MaxLen, UBN_OPENURLWCMD_LEN,
				End,
			End,

			Child, browserl = ListviewObject,
				MUIA_CycleChain,        TRUE,
				MUIA_Listview_DragType, MUIV_Listview_DragType_Immediate,
				MUIA_Listview_List,     ListObject,
					InputListFrame,
					MUIA_List_DragSortable, TRUE,
					MUIA_List_Title,        TRUE,
					MUIA_List_Format,       ",",
				End,
			End,

			Child, ColGroup(3),
				Child, addb    = SimpleButton("_Add"),
				Child, cloneb  = SimpleButton("C_lone"),
				Child, deleteb = SimpleButton("_Delete"),
			End,

			Child, MUI_MakeObject(MUIO_HBar, 5),

			Child, ColGroup(3),
				Child, saveb   = SimpleButton("_Save"),
				Child, useb    = SimpleButton("_Use"),
				Child, cancelb = SimpleButton("_Cancel"),
			End,
		End,
		TAG_MORE, msg->ops_AttrList);

	if(obj)
	{
		struct PrefsWin_Data *data = INST_DATA(cl, obj);
		memset(data, '\0', sizeof(struct PrefsWin_Data));

		/* init instance data */

		data->InfoGrpObj     = infog;
		data->NameStrObj     = names;
		data->PathStrObj     = paths;
		data->PortStrObj     = ports;
		data->CmdLineChkObj  = cmdlineurlc;

		data->CmdGrpObj      = cmdg;
		data->ShowStrObj     = shows;
		data->ToFrontStrObj  = tofronts;
		data->OpenURLStrObj  = openurls;
		data->OpenURLWStrObj = openurlws;

		data->BrowserLstObj  = browserl;
		data->AddButObj      = addb;
		data->CloneButObj    = cloneb;
		data->DeleteButObj   = deleteb;

		data->SaveButObj     = saveb;
		data->UseButObj      = useb;
		data->CancelButObj   = cancelb;

		/* buttons */

		set(addb,    MUIA_CycleChain, TRUE);
		set(cloneb,  MUIA_CycleChain, TRUE);
		set(deleteb, MUIA_CycleChain, TRUE);
		set(saveb,   MUIA_CycleChain, TRUE);
		set(useb,    MUIA_CycleChain, TRUE);
		set(cancelb, MUIA_CycleChain, TRUE);

		set(obj, MUIA_Window_DefaultObject, browserl);

		/* add hooks */

		data->ConstructHook.h_Entry = (HOOKFUNC)ConstructFunc;
		set(browserl, MUIA_List_ConstructHook, &data->ConstructHook);

		data->DestructHook.h_Entry = (HOOKFUNC)DestructFunc;
		set(browserl, MUIA_List_DestructHook, &data->DestructHook);

		data->DisplayHook.h_Entry = (HOOKFUNC)DisplayFunc;
		set(browserl, MUIA_List_DisplayHook, &data->DisplayHook);
	}

	return((ULONG)obj);
}

/**************************************************************************/

static ULONG mWindow_Setup(struct IClass *cl, Object *obj, struct MUIP_Window_Setup *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);

	if (!DoSuperMethodA(cl,obj,(Msg)msg))
		return(FALSE);

	if(!data->NotifiesAdded)
	{
		struct URL_Prefs *up = URL_GetPrefs();
		STRPTR error = NULL;
		struct URL_BrowserNode *bn;
		Object *strip;

		/* get the openurl.library prefs */

		if(!up) error = "Couldn't get prefs from openurl.library.";
		else if(up->up_Version != (UBYTE)1)
			error = "This version of this program doesn't know\nto handle openurl.library prefs version %ld.";

		if(error)
		{
			MUI_Request(_app(obj), obj, 0, "Error", "Abort", error, up ? up->up_Version : 0);
			if(up) URL_FreePrefs(up);
			CoerceMethod(cl, obj, MUIM_Window_Cleanup);
			return(FALSE);
		}

		for(bn = (struct URL_BrowserNode *)up->up_BrowserList.mlh_Head;
		    bn->ubn_Node.mln_Succ;
		    bn = (struct URL_BrowserNode *)bn->ubn_Node.mln_Succ)
		{
			DoMethod(data->BrowserLstObj, MUIM_List_InsertSingle, bn, MUIV_List_Insert_Bottom);
		}

		URL_FreePrefs(up);

		/* menu notifies */

		get(obj, MUIA_Window_Menustrip, &strip);

		/* Project menu */

		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_ABOUTMUI   ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,_app(obj),2,MUIM_Application_AboutMUI,obj);
		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_HIDE       ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,_app(obj),3,MUIM_Set,MUIA_Application_Iconified,TRUE);
		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_QUIT       ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,_app(obj),2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);

		/* Settings menu */

		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_MUISETTINGS),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,_app(obj),2,MUIM_Application_OpenConfigWindow,0);
		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_SNAPSHOT   ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,obj,2,MUIM_Window_Snapshot,1);
		DoMethod((Object *)DoMethod(strip,MUIM_FindUData,MEN_UNSNAPSHOT ),MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,obj,2,MUIM_Window_Snapshot,0);

		/* window notifies */

		DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, _app(obj), 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

		/* string gadgets */

		DoMethod(data->NameStrObj,     MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, TRUE);
		DoMethod(data->PathStrObj,     MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, TRUE);
		DoMethod(data->PortStrObj,     MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);
		DoMethod(data->ShowStrObj,     MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);
		DoMethod(data->ToFrontStrObj,  MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);
		DoMethod(data->OpenURLStrObj,  MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);
		DoMethod(data->OpenURLWStrObj, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);

		/* checkmark */

		DoMethod(data->CmdLineChkObj,  MUIM_Notify, MUIA_Selected,        MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntryChanged, FALSE);

		/* listview */

		DoMethod(data->BrowserLstObj, MUIM_Notify, MUIA_List_Active,  MUIV_EveryTime, obj, 1, MUIM_PrefsWin_ActiveChanged);
		DoMethod(data->BrowserLstObj, MUIM_Notify, MUIA_List_Entries, MUIV_EveryTime, obj, 2, MUIM_PrefsWin_EntriesChanged, MUIV_TriggerValue);

		/* list buttons */

		DoMethod(data->AddButObj,     MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, MUIM_PrefsWin_Add);
		DoMethod(data->CloneButObj,   MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, MUIM_PrefsWin_Clone);
		DoMethod(data->DeleteButObj,  MUIM_Notify, MUIA_Pressed, FALSE, data->BrowserLstObj, 2, MUIM_List_Remove, MUIV_List_Remove_Active);

		/* window buttons */

		DoMethod(data->SaveButObj,    MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, MUIM_PrefsWin_StorePrefs, MUIV_PrefsWin_StorePrefs_Save);
		DoMethod(data->UseButObj,     MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, MUIM_PrefsWin_StorePrefs, MUIV_PrefsWin_StorePrefs_Use);
		DoMethod(data->CancelButObj,  MUIM_Notify, MUIA_Pressed, FALSE, _app(obj), 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

		/* trigger one and fake another notifications to get the ghostings right */

		set(data->BrowserLstObj, MUIA_List_Active, MUIV_List_Active_Top);
		DoMethod(obj, MUIM_PrefsWin_EntriesChanged, xget(data->BrowserLstObj, MUIA_List_Entries));

		data->NotifiesAdded = TRUE;
	}

	return(TRUE);
}

/**************************************************************************/

static ULONG mAdd(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_Add *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);
	struct URL_BrowserNode bn = {0};
	strcpy(bn.ubn_Name, "«New browser»");
	DoMethod(data->BrowserLstObj, MUIM_List_InsertSingle, &bn, MUIV_List_Insert_Bottom);
	set(data->BrowserLstObj, MUIA_List_Active, xget(data->BrowserLstObj, MUIA_List_InsertPosition));
	return(TRUE);
}

/**************************************************************************/

static ULONG mClone(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_Clone *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);
	ULONG active;
	struct URL_BrowserNode *bn;
	get(data->BrowserLstObj, MUIA_List_Active, &active);
	DoMethod(data->BrowserLstObj, MUIM_List_GetEntry, active, &bn);
	DoMethod(data->BrowserLstObj, MUIM_List_InsertSingle, bn, ++active);
	set(data->BrowserLstObj, MUIA_List_Active, active);
	return(TRUE);
}

/**************************************************************************/

static ULONG mActiveChanged(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_ActiveChanged *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);
	struct URL_BrowserNode *bn = NULL;

	DoMethod(data->BrowserLstObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &bn);

	if(bn)
	{
		set(data->InfoGrpObj,   MUIA_Disabled, FALSE);
		set(data->CmdGrpObj,    MUIA_Disabled, FALSE);
		set(data->CloneButObj,  MUIA_Disabled, FALSE);
		set(data->DeleteButObj, MUIA_Disabled, FALSE);

		nnset(data->NameStrObj,     MUIA_String_Contents, bn->ubn_Name);
		nnset(data->PathStrObj,     MUIA_String_Contents, bn->ubn_Path);
		nnset(data->PortStrObj,     MUIA_String_Contents, bn->ubn_Port);
		nnset(data->ShowStrObj,     MUIA_String_Contents, bn->ubn_ShowCmd);
		nnset(data->ToFrontStrObj,  MUIA_String_Contents, bn->ubn_ToFrontCmd);
		nnset(data->OpenURLStrObj,  MUIA_String_Contents, bn->ubn_OpenURLCmd);
		nnset(data->OpenURLWStrObj, MUIA_String_Contents, bn->ubn_OpenURLWCmd);

		set(data->CmdLineChkObj,    MUIA_Selected,        bn->ubn_Flags & UBNF_URLONCMDLINE);
	}
	else
	{
		nnset(data->NameStrObj,     MUIA_String_Contents, "");
		nnset(data->PathStrObj,     MUIA_String_Contents, "");
		nnset(data->PortStrObj,     MUIA_String_Contents, "");
		nnset(data->ShowStrObj,     MUIA_String_Contents, "");
		nnset(data->ToFrontStrObj,  MUIA_String_Contents, "");
		nnset(data->OpenURLStrObj,  MUIA_String_Contents, "");
		nnset(data->OpenURLWStrObj, MUIA_String_Contents, "");

		set(data->CmdLineChkObj,    MUIA_Selected,        FALSE); 

		set(data->InfoGrpObj,   MUIA_Disabled, TRUE);
		set(data->CmdGrpObj,    MUIA_Disabled, TRUE);
		set(data->CloneButObj,  MUIA_Disabled, TRUE);
		set(data->DeleteButObj, MUIA_Disabled, TRUE);
	}

	return(TRUE);
}

/**************************************************************************/

static ULONG mEntriesChanged(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_EntriesChanged *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);

	set(data->CloneButObj,  MUIA_Disabled, !msg->Entries);
	set(data->DeleteButObj, MUIA_Disabled, !msg->Entries);

	return(TRUE);
}

/**************************************************************************/

static ULONG mEntryChanged(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_EntryChanged *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);
	struct URL_BrowserNode *bn;

	DoMethod(data->BrowserLstObj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &bn);

	if(bn)
	{
		strcpy(bn->ubn_Name,        (char *)xget(data->NameStrObj,     MUIA_String_Contents));
		strcpy(bn->ubn_Path,        (char *)xget(data->PathStrObj,     MUIA_String_Contents));
		strcpy(bn->ubn_Port,        (char *)xget(data->PortStrObj,     MUIA_String_Contents));
		strcpy(bn->ubn_ShowCmd,     (char *)xget(data->ShowStrObj,     MUIA_String_Contents));
		strcpy(bn->ubn_ToFrontCmd,  (char *)xget(data->ToFrontStrObj,  MUIA_String_Contents));
		strcpy(bn->ubn_OpenURLCmd,  (char *)xget(data->OpenURLStrObj,  MUIA_String_Contents));
		strcpy(bn->ubn_OpenURLWCmd, (char *)xget(data->OpenURLWStrObj, MUIA_String_Contents));

		if(xget(data->CmdLineChkObj, MUIA_Selected)) bn->ubn_Flags |= UBNF_URLONCMDLINE;
		else bn->ubn_Flags &= ~UBNF_URLONCMDLINE;

		if(msg->Redraw)
			DoMethod(data->BrowserLstObj, MUIM_List_Redraw, MUIV_List_Redraw_Active);
	}

	return(TRUE);
}

/**************************************************************************/

static ULONG mStorePrefs(struct IClass *cl, Object *obj, struct MUIP_PrefsWin_StorePrefs *msg)
{
	struct PrefsWin_Data *data = INST_DATA(cl,obj);
	struct URL_Prefs up;
	ULONG i;

	set(_app(obj), MUIA_Application_Sleep, TRUE);

	/* copy settings from gadgets into structure */

	up.up_Version = (UBYTE)1;
	NewList((struct List *)&up.up_BrowserList);

	/* browsers */

	for(i = 0;; i++)
	{
		struct URL_BrowserNode *bn;

		DoMethod(data->BrowserLstObj, MUIM_List_GetEntry, i, &bn);
		if(!bn) break;

		AddTail((struct List *)&up.up_BrowserList, (struct Node *)bn);
	}
	
	/* save to disk */
	
	if(!URL_SetPrefs(&up, (msg->How == MUIV_PrefsWin_StorePrefs_Save)))
		MUI_RequestA(_app(obj), obj, 0, "Error", "Abort", "Failed to save prefs", NULL);

	/* quit */

	set(_app(obj), MUIA_Application_Sleep, FALSE);
	DoMethod(_app(obj), MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

	return(TRUE);
}

/**************************************************************************/

SAVEDS ASM ULONG PrefsWin_Dispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
{
	switch(msg->MethodID)
	{
		case OM_NEW                      : return(mNew           (cl,obj,(APTR)msg));
		case MUIM_Window_Setup           : return(mWindow_Setup  (cl,obj,(APTR)msg));
		case MUIM_PrefsWin_Add           : return(mAdd           (cl,obj,(APTR)msg));
		case MUIM_PrefsWin_Clone         : return(mClone         (cl,obj,(APTR)msg));
		case MUIM_PrefsWin_ActiveChanged : return(mActiveChanged (cl,obj,(APTR)msg));
		case MUIM_PrefsWin_EntriesChanged: return(mEntriesChanged(cl,obj,(APTR)msg));
		case MUIM_PrefsWin_EntryChanged  : return(mEntryChanged  (cl,obj,(APTR)msg));
		case MUIM_PrefsWin_StorePrefs    : return(mStorePrefs (cl,obj,(APTR)msg));
	}

	return(DoSuperMethodA(cl,obj,msg));
}

/**************************************************************************/

static SAVEDS ASM APTR ConstructFunc(REG(a0) struct Hook *hook, REG(a2) APTR pool, REG(a1) struct URL_BrowserNode *bn)
{
	struct URL_BrowserNode *new;
	if((new = AsmAllocPooled(pool, sizeof(struct URL_BrowserNode), SysBase)))
		memcpy(new, bn, sizeof(struct URL_BrowserNode));
	return(new);
}

/**************************************************************************/

static SAVEDS ASM VOID DestructFunc (REG(a0) struct Hook *hook, REG(a2) APTR pool, REG(a1) struct URL_BrowserNode *bn)
{
	AsmFreePooled(pool, bn, sizeof(struct URL_BrowserNode), SysBase);
}

/**************************************************************************/

static SAVEDS ASM LONG DisplayFunc(REG(a0) struct Hook *hook, REG(a2) char **array, REG(a1) struct URL_BrowserNode *bn)
{
	if(bn)
	{
		*array++ = bn->ubn_Name;
		*array   = bn->ubn_Path;
	}
	else
	{
		*array++ = MUIX_B "Name";
		*array   = MUIX_B "Path";
	}

	return(0);
}

/**************************************************************************/

static ULONG __stdargs DoSuperNew(struct IClass *cl, Object *obj, ULONG tag1, ...)
{
	return(DoSuperMethod(cl, obj, OM_NEW, &tag1, NULL));
}
