// Handle drop on an object
BOOL desktop_drop_on_object(BackdropInfo *info,DOpusAppMessage **msg,BackdropObject *drop_obj,UWORD qual)
{
	char *name;
	short ret=1;

	// Allocate buffer
	if (!(name=AllocVec(1024,0))) return 1;

	// Was it an AppIcon?
	if (drop_obj->type==BDO_APP_ICON)
	{
		// Is the icon busy?
		if (drop_obj->flags&BDOF_BUSY)
		{
			// Flash error
			DisplayBeep(info->window->WScreen);
		}

		// Otherwise, pass message on
		else
		{
			struct MsgPort *port;

			// Turn message into an AppIcon one
			(*msg)->da_Msg.am_Type=MTYPE_APPICON;

			// Get port and info
			port=WB_AppWindowData(
				(struct AppWindow *)drop_obj->misc_data,
				&(*msg)->da_Msg.am_ID,
				&(*msg)->da_Msg.am_UserData);

			// Fix reply port
			(*msg)->da_Msg.am_Message.mn_ReplyPort=GUI->appmsg_port;

			// Send the message on
			PutMsg(port,(struct Message *)*msg);

			// Zero message pointer
			*msg=0;
		}
	}

	// Was it a group?
	else
	if (drop_obj->type==BDO_GROUP)
	{
		short arg;
		GroupData *group;
		BOOL ok=0;

		// Find group if it's open
		lock_listlock(&GUI->group_list,0);
		if (!(group=backdrop_find_group(drop_obj)))
			unlock_listlock(&GUI->group_list);

		// Go through arguments
		for (arg=0;arg<(*msg)->da_Msg.am_NumArgs;arg++)
		{
			// Valid file?
			if ((*msg)->da_Msg.am_ArgList[arg].wa_Name &&
				*(*msg)->da_Msg.am_ArgList[arg].wa_Name)
			{
				// Get filename
				GetWBArgPath(&(*msg)->da_Msg.am_ArgList[arg],name,512);

				// Send add message to group if it's open
				if (group)
				{
					char *copy;

					// Copy name
					if ((copy=AllocVec(strlen(name)+1,0)))
					{
						strcpy(copy,name);
						IPC_Command(group->ipc,GROUP_ADD_ICON,0,0,copy,0);
						ok=1;
					}
				}

				// Otherwise add object to group
				else
				{
					backdrop_group_add_object(drop_obj->name,0,name,-1,-1);
					ok=1;
				}
			}
		}

		// Show error if no ok
		if (!ok) DisplayBeep(GUI->screen_pointer);

		// Unlock process list if it's locked
		if (group) unlock_listlock(&GUI->group_list);
	}

	// Or a project?
	else
	if (drop_obj->icon->do_Type==WBPROJECT)
	{
		// Is it an Opus command?
		if (command_filetype)
		{
			BPTR lock,old;

			// Set failure initially
			ret=0;

			// Get lock on directory
			if ((lock=backdrop_icon_lock(drop_obj)))
			{
				// Go there
				old=CurrentDir(lock);

				// See if it's a command
				if (filetype_match_type(drop_obj->name,command_filetype))
				{
					// Run command with args
					backdrop_object_open(
						info,
						drop_obj,
						0,
						0,
						(*msg)->da_Msg.am_NumArgs,
						(*msg)->da_Msg.am_ArgList);
					ret=1;
				}

				// Restore CD
				CurrentDir(old);
			}
		}

		// Beep if not a command
		if (!ret) DisplayBeep(GUI->screen_pointer);
	}

	// Or a tool?
	else
	if (drop_obj->icon->do_Type==WBTOOL)
	{
		// Run program with args
		backdrop_object_open(
			info,
			drop_obj,
			0,
			0,
			(*msg)->da_Msg.am_NumArgs,
			(*msg)->da_Msg.am_ArgList);
	}


	// Or a disk/directory?
	else
	if (drop_obj->icon->do_Type==WBDISK ||
		drop_obj->icon->do_Type==WBDRAWER ||
		drop_obj->icon->do_Type==WBGARBAGE)
	{
		struct ArgArray *arg_array;

		// Get arg array
		if ((arg_array=AppArgArray(*msg,AAF_ALLOW_DIRS)))
		{
			BPTR lock;

			// Get pathname of first file
			DevNameFromLockDopus((*msg)->da_Msg.am_ArgList[0].wa_Lock,name,512);

			// Need source directory; if no name, get parent
			if ((!(*msg)->da_Msg.am_ArgList[0].wa_Name ||
				!*(*msg)->da_Msg.am_ArgList[0].wa_Name) &&
				(lock=ParentDir((*msg)->da_Msg.am_ArgList[0].wa_Lock)))
			{
				// Get pathname of parent
				DevNameFromLockDopus(lock,name,512);
				UnLock(lock);
			}

			// Get destination path
			if ((lock=backdrop_icon_lock(drop_obj)))
			{
				short action;

				// Get path
				DevNameFromLockDopus(lock,name+512,512);
				UnLock(lock);

				// Is object a left-out?
				if (drop_obj->type==BDO_LEFT_OUT)
				{
					// Add left-out name
					AddPart(name+512,drop_obj->name,512);
				}

				// Get filetype action
				if (qual&IEQUALIFIER_CONTROL) action=FTTYPE_CTRL_DRAGDROP;
				else
				if (qual&(IEQUALIFIER_LALT|IEQUALIFIER_RALT)) action=FTTYPE_ALT_DRAGDROP;
				else
				action=FTTYPE_DRAG_DROP;

				// Do filetype action on files
				function_launch(
					FUNCTION_FILETYPE,
					0,
					action,
					FUNCF_DRAG_DROP|FUNCF_ICONS,
					0,0,
					name,name+512,
					arg_array,
					0,
					(Buttons *)CopyAppMessage(*msg,global_memory_pool));
			}
		}
	}
	else ret=0;

	FreeVec(name);
	return ret;
}
// Drop some objects on another one
void backdrop_drop_object(BackdropInfo *info,BackdropObject *on_object)
{
	BackdropObject *object;
	char *buf,*dbuf;
	struct InfoData __aligned data;
	BPTR lock;

	if (!(buf=AllocVec(512,0)))
		return;
	dbuf=buf+256;

	// Drop on an AppIcon
	if (on_object->type==BDO_APP_ICON)
	{
		DOpusAppMessage *msg;
		struct MsgPort *port;

		// Is the icon busy?
		if (on_object->flags&BDOF_BUSY)
		{
			DisplayBeep(info->window->WScreen);
			FreeVec(buf);
			return;
		}

		// Build AppMessage
		if (!(msg=backdrop_appmessage(info,1)))
		{
			FreeVec(buf);
			return;
		}

		// Set message type
		msg->da_Msg.am_Type=MTYPE_APPICON;

		// Get AppInfo
		port=WB_AppWindowData(
			(struct AppWindow *)on_object->misc_data,
			&msg->da_Msg.am_ID,
			&msg->da_Msg.am_UserData);

		// Send the message
		PutMsg(port,(struct Message *)msg);
		FreeVec(buf);
		return;
	}

	// Only support dropping on disks at the moment
	if ((on_object->type!=BDO_DISK && on_object->type!=BDO_BAD_DISK) ||
		on_object->flags&(BDOF_ASSIGN|BDOF_CACHE))
	{
		DisplayBeep(info->window->WScreen);
		FreeVec(buf);
		return;
	}

	// Go through backdrop list
	for (object=(BackdropObject *)info->objects.list.lh_Head;
		object->node.ln_Succ;
		object=(BackdropObject *)object->node.ln_Succ)
	{
		// Selected disk?
		if (object->type==BDO_DISK && !(object->flags&(BDOF_ASSIGN|BDOF_CACHE)) && object->state)
		{
			BPTR lock;

			// Get disk lock
			if (lock=backdrop_icon_lock(object))
			{
				// This is the source
				Info(lock,&data);

				// Get device name
				DeviceFromLock(lock,buf);

				// Unlock lock
				UnLock(lock);
			}
			break;
		}
	}

	// Didn't get anything?
	if (!object->node.ln_Succ)
	{
		DisplayBeep(info->window->WScreen);
		FreeVec(buf);
		return;
	}

	// Drop on a bad disk?
	if (on_object->type==BDO_BAD_DISK)
	{
		// Get device name
		strcpy(dbuf,on_object->name);
	}

	// Real disk
	else
	{
		// Get destination disk lock
		if (!(lock=backdrop_icon_lock(on_object)))
		{
			FreeVec(buf);
			return;
		}

		// Destination is the one we dropped it on
		Info(lock,&data);

		// Get device name
		DeviceFromLock(lock,dbuf);
		UnLock(lock);
	}

	// Launch diskcopy
	function_launch(
		FUNCTION_RUN_FUNCTION,
		def_function_diskcopy,
		0,
		0,
		0,0,
		0,0,
		BuildArgArray(buf,dbuf,0),
		0,0);

	FreeVec(buf);
}