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

    MODULE
	AppIcon.c

    DESCRIPTION
	XDME Command Module

	to form a Workbench AppIcon for the XDME process

    NOTES
	the "COMMAND"-lines have a specail meaning (see STATIC_COM)
	the SPC_VAR-section has a special meaning (see there)

    BUGS
	none known

    TODO
	tell me

    EXAMPLES

    SEE ALSO

    AUTHOR
	Bernd "0" Noll (b_noll@informatik.uni-kl.de)

    HISTORY
	21-09-94 b_noll created
	01-10-94 b_noll introduced DEFMESSAGE
	27-11-94 b_noll first preparations for multiicon support
	03-12-94 b_noll removed `defs.h'

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


/**************************************
	      Includes
**************************************/

/* #include "defs.h" */

#include <workbench/icon.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>

#include <proto/exec.h>
#include <proto/icon.h>
#include <proto/wb.h>

#include <stdio.h>
#include "xdme_base.h"

/**************************************
	    Global Variables
**************************************/


Prototype UBYTE 	    *APIC_IconTitle;
Prototype UBYTE 	    *APIC_IconFile;
Prototype UBYTE 	    *APIC_ActionDblClick;
Prototype UBYTE 	    *APIC_ActionDrop;
//Prototype UBYTE	       APIC_Active;
Prototype ULONG 	     APIC_SigMask;

/**************************************
      Internal Defines & Structures
**************************************/

#define APIC_OK 0
#define APIC_NOICON	    -1
#define APIC_NODISKOBJECT   -2
#define APIC_NOPORT	    -3
#define APIC_max

#define APIC_BufferSize 500

/**************************************
	   Internal Variables
**************************************/

struct DiskObject *APIC_DiskObject = NULL;
APTR		   APIC_Icon	   = NULL;
struct MsgPort	  *APIC_Port	   = NULL;

UBYTE		  *APIC_IconTitle	= NULL;
UBYTE		  *APIC_IconFile	= NULL;
UBYTE		  *APIC_ActionDblClick	= NULL;
UBYTE		  *APIC_ActionDrop	= NULL;

//UBYTE 	     APIC_Active      = 0;
ULONG		   APIC_SigMask     = 0;

/**************************************
	   Internal Prototypes
**************************************/


/**************************************
		 Macros
**************************************/

#define APIC_DefTitle	    "XDME"
#define APIC_DefIconFile    "XDME"

#define APIC_DefDblClick    "newwindow arpload"
#define APIC_DefDrop	    "newwindow newfile `%s'"

/**************************************
	     Implementation
**************************************/



int APIC_Hide (void) {
    if (!APIC_Icon)
	return APIC_NOICON;

    if (APIC_Icon)
	RemoveAppIcon(APIC_Icon);
    APIC_Icon = NULL;

    if (APIC_DiskObject)
	FreeDiskObject(APIC_DiskObject);
    APIC_DiskObject = NULL;

    APIC_Active = 0;
    return APIC_OK;
} /* APIC_Hide */


int APIC_Show (const UBYTE * iconfile, const UBYTE *icontitle) {
    if (!APIC_Port)
	return APIC_NOPORT;

    if ((APIC_DiskObject = GetDiskObject (APIC_IconFile)) == NULL) {
	if (!getappname(tmp_buffer, sizeof(tmp_buffer)) ||
	   ((APIC_DiskObject = GetDiskObject (tmp_buffer)) == NULL)) {
	    if ((APIC_DiskObject = GetDefDiskObject (WBTOOL)) == NULL) {
		APIC_Hide();
		return APIC_NODISKOBJECT;
	    } /* if */
	} /* if */
    } /* if */

    APIC_Icon = AddAppIconA (NULL, NULL, APIC_IconTitle, APIC_Port, NULL, APIC_DiskObject, NULL);

    if (!APIC_Icon ) {
	APIC_Hide();
	return APIC_NOICON;
    } /* if */

    APIC_Active = 1;
    return APIC_OK;
} /* APIC_Show */

#if 0





struct ApNode {
    struct HNode       Node;
    UBYTE	      *IconTitle;
    UBYTE	      *IconFile;
    struct DiskObject *DiskObject;
    APTR	       Icon;
    BYTE	       IconStatus;
    UBYTE	      *ClickAction;
    UBYTE	      *DropAction;
}; /* struct  */

int APIC_Hide (struct ApNode *n) {
    if (n->IconStatus != VISIBLE)
	return APIC_ISHIDDEN;

    if (n->Icon)
	RemoveAppIcon(n->Icon);
    n->Icon = NULL;

    n->IconStatus = HIDDEN;
    return HL_OK;
} /* APIC_Hide */


int APIC_Show (struct ApNode *n)
{
    if (n->IconStatus == VISIBLE)
	return APIC_ISVISIBLE;

    if (!n->DiskObject) {
	if ((n->DiskObject = GetDiskObject (n->IconFile)) == NULL) {
	    APIC_Hide(n);
	    return APIC_NODISKOBJECT;
	} /* if */
    } /* if */

    n->Icon = AddAppIconA (NULL, n, n->IconTitle, APIC_Port, NULL, n->DiskObject, NULL);
    if (!n->Icon) {
	APIC_Hide(n);
	return APIC_NOICON;
    } /* if */

    n->IconStatus = VISIBLE;
    return HL_OK;
} /* APIC_Show */




int APIC_Dispose (struct ApNode *n)
{
    int rv;
    if (in->Status == VISIBLE)
	APIC_Hide (n);

    if ((rv = HL_Uninit(n)) != HL_OK)
	return rv;

    if (n->DiskObject)
	FreeDiskObject(n->DiskObject);
    n->DiskObject = NULL;

    if (n->IconFile)
	free(n->IconFile);
    n->IconFile = NULL;

    if (n->IconTitle)
	free(n->IconTitle);
    n->IconTitle = NULL;

    if (n->DropAction)
	free(n->DropAction);
    n->DropAction = NULL;

    if (n->ClickAction)
	free(n->ClickAction);
    n->ClickAction = NULL;

    free(n);
    return HL_OK;
} /* APIC_Dispose */


int APIC_New (const UBYTE *name, const UBYTE *ifile, const UBYTE *ititle)
{
    struct ApNode *n;

    if (n = malloc (sizeof (*n))) {
	if ((rv = HL_Init (n, name, APIC_Root, HLF_SYSNODE)) != HL_OK) {
	    free (n);
	    return rv;
	} /* if */
	n->IconFile   = strdup (NULL, ifile);
	n->IconTitle  = strdup (NULL, ititle);
	n->IconStatus = HIDDEN;
	if ((n->DiskObject = GetDiskObject (n->IconFile)) == NULL) {
	    n->IconStatus = NODOBJECT;
	} /* if */

	return HL_OK;
    } /* if */
    return HL_NOMEM
} /* APIC_New */


DEFAUTOEXIT( APIC_Terminate )
{
    /* ---- delete the icons */
    if (APIC_Root) {
	struct DList *icons;
	if ((icons = HL_LockSubs(APIC_Root)))
	    DLL_Scan(icons, APIC_Dispose, NULL);
	HL_Dispose (APIC_Root);
    } /* if */

    { /* ---- drop all waiting messages */
	struct Message *msg;
	while (msg = GetMsg(APIC_Port)) {
	    ReplyMsg (msg);
	} /* while */
    }

    /* ---- close the port */
    if (APIC_Port)
	DeleteMsgPort(APIC_Port);
    APIC_Port = NULL;

} /* APIC_Terminate */


DEFAUTOINIT( APIC_Initialize )
{
//puts (__FILE__);

    APIC_Root = HL_SystemList ("*AppIcons*");
    APIC_Port		= CreateMsgPort();

    if ( !APIC_Port || !APIC_Root ) {
	APIC_Terminate();
	return;
    } /* if */

    APIC_SigMask = 1 << APIC_Port->mp_SigBit;

} /* APIC_Initialize */



#endif





/*************************************************
	Entry & Exit Code
*************************************************/


DEFAUTOEXIT( APIC_Terminate )
{
    /* ---- hide the icon */
    //DLL_Scan(APIC_Icons, APIC_Hide, NULL);
    APIC_Hide();

    { /* ---- drop all waiting messages */
	struct Message *msg;
	while (msg = GetMsg(APIC_Port)) {
	    ReplyMsg (msg);
	} /* while */
    }

    /* ---- close the port */
    if (APIC_Port)
	DeleteMsgPort(APIC_Port);
    APIC_Port = NULL;

} /* APIC_Terminate */


DEFAUTOINIT( APIC_Initialize )
{
//puts (__FILE__);
    APIC_Port		= CreateMsgPort();
    APIC_IconTitle	= strdup (APIC_DefTitle);
    APIC_IconFile	= strdup (APIC_DefIconFile);
    APIC_ActionDrop	= strdup (APIC_DefDrop);
    APIC_ActionDblClick = strdup (APIC_DefDblClick);

    if (!APIC_Port || !APIC_IconTitle || !APIC_IconFile || !APIC_ActionDrop || !APIC_ActionDblClick ) {
	APIC_Terminate();
	return;
    } /* if */

    APIC_SigMask = 1 << APIC_Port->mp_SigBit;

} /* APIC_Initialize */


/*************************************************
	Application Interface
*************************************************/


/*
** Explain an APIC related error
*/
int APIC_Error (int code, const UBYTE *command, ...) {
    switch (code) {
    case APIC_OK:
	return RET_SUCC;
    case APIC_NOICON:
DEFMESSAGE( _APIC_appicon_not_shown, "%s:\nAppIcon not shown!" )
	error (_APIC_appicon_not_shown, command);
	break;
    case APIC_NODISKOBJECT:
DEFMESSAGE( _APIC_icon_not_created, "%s:\nIcon not created!" )
	error (_APIC_icon_not_created, command);
	break;
    case APIC_NOPORT:
DEFMESSAGE( _APIC_module_inactive, "%s:\nAppIcon Module not active!" )
	error (_APIC_module_inactive, command);
	break;
    default:
DEFMESSAGE( _APIC_internal_error, "%s:\nAppIcon Internal Error!" )
	error (_APIC_internal_error, command);
    } /* switch */
    return RET_FAIL;
} /* APIC_Error */


/*
**  Get a message from the AppIcon
*/
Prototype void APIC_Control (void);
void APIC_Control (void) {
    struct AppMessage *msg;

    while (msg = (struct AppMessage *)GetMsg (APIC_Port)) {
	if (!msg->am_NumArgs) {
	    buffered_do_command (APIC_ActionDblClick);
	} else {
	    char *buffer = malloc (APIC_BufferSize);
	    if (buffer) {
		int i;
		for (i = 0; i < msg->am_NumArgs; ++i) {
		    /* ---- getpathto() is found in XDME/Src/Subs.c */
		    if (getpathto(msg->am_ArgList[i].wa_Lock, msg->am_ArgList[i].wa_Name, tmp_buffer)) {
			sprintf (buffer, APIC_ActionDrop, tmp_buffer, tmp_buffer, tmp_buffer, tmp_buffer);
			do_command(buffer);
		    } else {
			/* ---- file not found - und nun? */
		    } /* if */
		} /* for */
	    } else {
		nomemory();
	    } /* if */

	} /* if */

	ReplyMsg ((struct Message *)msg);
    } /* while */
} /* APIC_Control */


/*************************************************
	Fragments of other modules
*************************************************/

#ifdef MAIN_C

DEFSIGHANDLER( APIC_SigMask, APIC_Control(); )

#endif


/***************************************************
		COMMAND INTERFACE
***************************************************/

/*DEFHELP #cmd special APPICON - The AppIcon Interface */
//DEFUSERCMD( "AppIconShow", 0, 0, void, do_apicshow, (void),)
Prototype int do_apicshow (void);
int do_apicshow (void) {
    return APIC_Error( APIC_Show(APIC_IconFile, APIC_IconTitle), av[0]);
} /* do_apicshow */

//DEFUSERCMD( "AppIconHide", 0, 0, void, do_apichide, (void),)
Prototype int do_apichide (void);
int do_apichide (void) {
    return APIC_Error(APIC_Hide(), av[0]);
} /* do_apichide */



/*DEFLONG #long APPICON

That Package allows use of a Workbench AppIcon.
Currently the whole package is conrolled via some special
variables, not via commands;
the following five variables are used:

    $appicon - (BOOL) the status of the appicon:
	 setting it to "1" makes the AppIcon appear,
	 setting it to "0" makes the AppIcon disappear.

    $appiconname - (FILE) the icon to be used for the AppIcon Image;
	plase note, that modification of that variable currently
	only has effect after the NEXT appearance of the AppIcon,
	the visible Image is not changed.
	Defaults to "XDME".

    $appicontitle - (STRING) the titlestring to be used in connection
	with the AppIcon (the same limit as for $appiconname)
	Defaults to "XDME".

    $appicondropaction - (COMMAND) the command to be executed,
	whenever another icon is dropped onto the AppIcon; any
	"%s" in that variable are expanded to the full name of
	the dropped icon (w/ sprintf).
	Defaults to "newwindow newfile `%s'".

    $appiconclickaction - (COMMAND) the command to be executed,
	whenever user doubleclicks on the AppIcon.
	Defaults to "newwindow arpload".

*/




#undef STATIC_COM
/***********************************************************
    The STATIC_COM section has currently _2_ purposes:
=58 abort sub $arg1 $tabstop) if c=59 abort firstnb if ca (checkexistance $currentword ($blockbeginner) (add $arg1 $tabstop))
a (checkexistance $currentword ($blockbeginner) (add $arg1 $tabstop))
top))
	source tree of a tool
      - to achie
	- we can use the "COMMAND(...)" lines to generate
	  a List of all commands of a certain application,
	  (static solution)
	- we can add AUTOINIT and AUTOEXIT functions
	  which add those COMMAND lines to a global
	  database themselfes (dynamic solution)
	  that way is very interesting in case of using
	  a split application, cluttered in many small
	  modules, which can be activated or removed
	  by user request

    Since Dynamic method means too much overhead to be of
    any use for the XDME, we will probably probably never
    use the DYNAMIC solution, and for that reason it might
    be of more use to put those command lines to the
    functions, which implement those commands.
***********************************************************/
#ifdef STATIC_COM
#define COMMAND(n,a,f,p) /* these lines cannot be translated here! */

    /* COMMAND("", , , ) */

    DEFFLAG( 94-09-19, APIC_Active, 0 )


#endif


#undef SPC_VAR
/***********************************************************
    The SPC_VAR section has only one purpose:
      - it contains descriptions for all special
	variables of the module, which are of interest
	for the user - to change them or to ask their
	values via variable interface.
    that section shall _never_ be considered C-Source
    (for that reason the "#undef" is put just before)
    but it is scanned by an external parser in order
    to produce a list of all Special variables and
    their access functions in a seperate File.
***********************************************************/
#ifdef SPC_VAR

generic global bit appicon = %{
    reference = "APIC_Active";
    set       = %[ { char inter; inter = test_arg(value, $(REFERENCE)); if (inter != $(REFERENCE)) if (inter) do_apicshow(); else do_apichide(); } %];
    help      = %[ the IsVisible status of the AppIcon. %];
    gendate   = "21-09-94/1";
    initval   = "0";
%};

generic global str appicontitle = %{
    reference = "APIC_IconTitle";
    set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
    help      = %[ the titlestring to te used when next time showing the AppIcon. %];
    gendate   = "21-09-94/2";
    initval   = %[ "XDME" %];
%};

generic global str appiconname = %{
    reference = "APIC_IconFile";
    set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
    help      = %[ the iconfile to be used when next time showing the AppIcon. %];
    gendate   = "21-09-94/3";
    initval   = %[ "PROGDIR:XDME" %];
%};

generic global str appo·ondropaction = %{
    reference = "APIC_ActionDrop";
    set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
    help      = %[ the command to the called, whenever an icon is dropped onto the AppIcon %];
    gendate   = "21-09-94/4";
    initval   = %[ "newwindow newfile `%s'" %];
%};

generic global str appiconclickaction = %{
    reference = "APIC_ActionDblClick";
    set       = %[ $(REFERENCE) = strrep ($(REFERENCE), value); %];
    help      = %[ the command to be called, whenever the user doubleclicks onto the AppIcon. %];
    gendate   = "21-09-94/5";
    initval   = %[ "newwindow arpload" %];
%};


#endif /* SPC_VAR */

/******************************************************************************
*****  END AppIcon.c
******************************************************************************/



#if 0

struct AppIcon {
    UBYTE	      *IconTitle;
    UBYTE	      *IconFile;
    struct DiskObject *DiskObject;
    APTR	       Icon;
    UBYTE	      *ClickAction;
    UBYTE	      *DropAction;
    BYTE	       IconStatus;
}; /* struct AppIcon */

struct HLClass appiconClass = {
    HL_RootClass;
    sizeof (struct AppIcon);
    APIC_Dispatcher;
};

ULONG APIC_Dispatcher (HObject *o, APTR cl, Msg msg)
{
    struct AppIcon *inst = HINST_DATA(o,cl);
    struct TagItem *ti, *tstate;

    switch (msg->AttributeID) {
    case OM_NEW:
	if (o = (HObject *)HSuperMethod(o, cl, msg)) {
	    inst = HINST_DATA(o,cl);

	    ti	   = ((struct opSet *)msg)->ops_AttrList;
	    tstate = ti;
	    while (ti = NextTagItem(&tstate)) {
		ULONG tg  = ti->ti_Tag;
		ULONG val = ti->ti_Data;
		switch (tg) {

		case HA_DropAction: {
		    inst->DropAction = strrep (inst->DropAction, (STRPTR)ti->ti_Data);
		} break;

		case HA_ClickAction: {
		    inst->ClickAction = strrep (inst->ClickAction, (STRPTR)ti->ti_Data);
		} break;

		case HA_Title: {
		    inst->IconTitle = strrep (inst->IconTitle, (STRPTR)ti->ti_Data);
		} break;

		case HA_IconFile: {
		    inst->IconFile = strrep (inst->IconFile, (STRPTR)ti->ti_Data);
		} break;

		} /* switch */
	    } /* while */

	} /* if */
	return (ULONG)o;

    case OM_DISPOSE:
	if (inst->Status == VISIBLE)
	    APIC_Hide (inst);

	if (inst->DiskObject)
	    FreeDiskObject(inst->DiskObject);
	inst->DiskObject = NULL;

	if (inst->IconFile)
	    free(inst->IconFile);
	inst->IconFile = NULL;

	if (inst->IconTitle)
	    free(inst->IconTitle);
	inst->IconTitle = NULL;

	if (inst->DropAction)
	    free(inst->DropAction);
	inst->DropAction = NULL;

	if (inst->ClickAction)
	    free(inst->ClickAction);
	inst->ClickAction = NULL;

	return HSuperMethod (o,cl,msg);

    case OM_SET:
	ti     = ((struct opSet *)msg)->ops_AttrList;
	tstate = ti;
	while (ti = NextTagItem(&tstate)) {
	    ULONG tg  = ti->ti_Tag;
	    ULONG val = ti->ti_Data;
	    switch (tg) {

	    case HA_DropAction: {
		inst->DropAction = strrep (inst->DropAction, (STRPTR)ti->ti_Data);
	    } break;

	    case HA_ClickAction: {
		inst->ClickAction = strrep (inst->ClickAction, (STRPTR)ti->ti_Data);
	    } break;

	    case HA_Title: {
		inst->IconTitle = strrep (inst->IconTitle, (STRPTR)ti->ti_Data);
	    } break;

	    case HA_IconFile: {
		inst->IconFile = strrep (inst->IconFile, (STRPTR)ti->ti_Data);
	    } break;

	    case HA_Visible: {
		if (!(ti->ti_Data) || *(ULONG *)ti->ti_Data == '0')
		    APIC_Hide(inst);
		else
		    APIC_Show(inst);
	    } break;

	    } /* switch */
	} /* while */

	return HSuperMethod (o,cl,msg);

    case OM_GET:
	switch (tg = ((struct opGet *)msg)->opg_AttrID) {

	case HA_DropAction: {
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->DropAction;
	} break;

	case HA_ClickAction: {
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->ClickAction;
	} break;

	case HA_IconTitle: {
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->IconTitle;
	} break;

	case HA_IconFile: {
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->IconFile;
	} break;

	case HA_Visible: {
	    *((struct opGet *)msg)->opg_Storage = inst->IconStatus;
	} break;

	default:
	    return HSuperMethod(o, cl, msg);
	} /* switch */

	return 1;

    default:
	return HSuperMethod(o, cl, msg);
    } /* switch */

} /* APIC_Dispatcher */



class appicon = {
    superclass = rootclass;

    contents = {
	slot IconTitle = {
	    type    = "UBYTE *";
	    dispose = {{
		if (inst->IconTitle)
		    free (inst->IconTitle);
		inst->IconTitle = NULL;
	    }};
	};
	slot IconFile = {
	    type = "UBYTE *";
	    dispose = {{
		if (inst->IconFile)
		    free (inst->IconFile);
		inst->IconFile = NULL;
	    }};
	};
	slot DropAction = {
	    type = "UBYTE *";
	    dispose = {{
		if (inst->DropAction)
		    free (inst->DropAction);
		inst->DropAction = NULL;
	    }};
	};
	slot ClickAction = {
	    type = "UBYTE *";
	    dispose = {{
		if (inst->ClickAction)
		    free (inst->ClickAction);
		inst->ClickAction = NULL;
	    }};
	};
	slot DiskObject = {
	    type = "struct DiskObject *";
	    dispose = {{
		if (inst->DiskObject)
		    FreeDiskObject(inst->DiskObject);
		inst->DiskObject = NULL;
	    }};
	};
	slot _Icon = {
	    type = "APTR";
	    dispose = {{
		if (inst->_Icon)
		    RemoveAppIcon(inst->_Icon);
		inst->_Icon = NULL;
	    }};
	};
    };

    attribute HA_DropAction = {{
	type	  = "STRPTR";
	reference = "inst->DropAction"
	I = {{
	    inst->DropAction = strrep (inst->DropAction, (STRPTR)ti->ti_Data);
	}};
	S = {{
	    inst->DropAction = strrep (inst->DropAction, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->DropAction;
	}};
    };

    attribute HA_ClickAction = {{
	type	  = "STRPTR";
	reference = "inst->ClickAction"
	I = {{
	    inst->ClickAction = strrep (inst->ClickAction, (STRPTR)ti->ti_Data);
	}};
	S = {{
	    inst->ClickAction = strrep (inst->ClickAction, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->ClickAction;
	}};
    };

    attribute HA_IconTitle = {{
	type	  = "STRPTR";
	reference = "inst->IconTitle"
	I = {{
	    inst->IconTitle = strrep (inst->IconTitle, (STRPTR)ti->ti_Data);
	}};
	S = {{
	    inst->IconTitle = strrep (inst->IconTitle, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->IconTitle;
	}};
    };

    attribute HA_IconFile = {{
	type	  = "STRPTR";
	reference = "inst->IconFile"
	I = {{
	    inst->IconFile = strrep (inst->IconFile, (STRPTR)ti->ti_Data);
	}};
	S = {{
	    inst->IconFile = strrep (inst->IconFile, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (ULONG)inst->IconFile;
	}};
    };

    attribute HA_Visible = {{
	type = "BOOL";
	S = {{
	    if (!(ti->ti_Data) /*|| (*(ULONG *)ti->ti_Data == '0') */)
		APIC_Hide(inst);
	    else
		APIC_Show(inst);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (inst->_Icon != NULL);
	}};
    };
};




#endif
