

/*
   *
   * $Id: Drag_Drop.c,v 1.3 1998/06/03 14:01:43 Giambattista_Bloisi Exp $
   *
 */

#define INTERFACE_C

#include "common/extern.h"
#include "common/Grab_mcc.h"

#include <MUI/NListview_mcc.h>
#include <MUI/NFloattext_mcc.h>

/****************************************************************************/
/* Butto Drag&Drop class                                                    */
/****************************************************************************/

/// "New"
ULONG
ButtonDrop_New (struct IClass * cl, Object * obj, struct opSet * msg)
{
// *INDENT-OFF*
  obj = (Object *) DoSuperNew (cl, obj,
                                 ButtonFrame,
                                 MUIA_InputMode,  MUIV_InputMode_RelVerify,
                                 MUIA_Background, MUII_ButtonBack,
                                 TAG_MORE, msg->ops_AttrList);
// *INDENT-ON*








  if (obj)
    return ((ULONG) obj);

  return (NULL);
}
///

/// "DragQuery"
ULONG
ButtonDrop_DragQuery (struct IClass * cl, Object * obj, struct MUIP_DragQuery * msg)
{
  if (msg->obj == obj)
    return (MUIV_DragQuery_Refuse);

  if (muiUserData (msg->obj) != muiUserData (obj))
    return (MUIV_DragQuery_Refuse);

  return (MUIV_DragQuery_Accept);
}
///

/// "DragDrop"
ULONG
ButtonDrop_DragDrop (struct IClass * cl, Object * obj, struct MUIP_DragDrop * msg)
{

  DoMethod (msg->obj, MUIM_Set, MUIA_Grab_Stop, NULL);

  return (NULL);
}
///

/// "Dispatcher"
SAVEDS (ULONG)
ButtonDrop_Dispatcher (REG (a0, struct IClass * cl), REG (a2, Object * obj), REG (a1, Msg msg))
{
  switch (msg->MethodID)
    {
    case OM_NEW:
      return (ButtonDrop_New (cl, obj, (struct opSet *) msg));
    case MUIM_DragQuery:
      return (ButtonDrop_DragQuery (cl, obj, (struct MUIP_DragQuery *) msg));
    case MUIM_DragDrop:
      return (ButtonDrop_DragDrop (cl, obj, (struct MUIP_DragDrop *) msg));
    }
  return (DoSuperMethodA (cl, obj, msg));
}
///

/****************************************************************************/
/* Strin Drag&Drop class                                                    */
/****************************************************************************/

/// "New"
ULONG
StrDrop_New (struct IClass * cl, Object * obj, struct opSet * msg)
{
// *INDENT-OFF*
  obj = (Object *) DoSuperNew (cl, obj,
                                 MUIA_Frame,     MUIV_Frame_String,
                                 MUIA_UserData,  UDB_STRDROP,
                                 MUIA_Dropable,  TRUE,
                                 MUIA_Draggable, TRUE,
                                 TAG_MORE,       msg->ops_AttrList);
// *INDENT-ON*








  if (obj)
    return ((ULONG) obj);

  return (NULL);
}
///

/// "DragQuery"
ULONG
StrDrop_DragQuery (struct IClass * cl, Object * obj, struct MUIP_DragQuery * msg)
{

  if (msg->obj == obj)
    return (MUIV_DragQuery_Refuse);

  if (muiUserData (msg->obj) != muiUserData (obj))
    return (MUIV_DragQuery_Refuse);

  return (MUIV_DragQuery_Accept);
}
///

/// "DragDrop"

ULONG
StrDrop_DragDrop (struct IClass * cl, Object * obj, struct MUIP_DragDrop * msg)
{
  char *buf;

  get (msg->obj, MUIA_String_Contents, &buf);
  set (obj, MUIA_String_Contents, buf);

  return (0);
}
///

/// "Dispatcher"
SAVEDS (ULONG)
StrDrop_Dispatcher (REG (a0, struct IClass * cl), REG (a2, Object * obj), REG (a1, Msg msg))
{
  switch (msg->MethodID)
    {
    case OM_NEW:
      return (StrDrop_New (cl, obj, (struct opSet *) msg));
    case MUIM_DragQuery:
      return (StrDrop_DragQuery (cl, obj, (struct MUIP_DragQuery *) msg));
    case MUIM_DragDrop:
      return (StrDrop_DragDrop (cl, obj, (struct MUIP_DragDrop *) msg));
    }
  return (DoSuperMethodA (cl, obj, msg));
}
///

/*******************************************************************/
/* Image class                                                    */
/*******************************************************************/

/// "Get Bitmap"
struct imgbm
{
  struct BitMapHeader bmhd;

  ULONG *cols;
  UBYTE *body;

};

struct imgbm *
getbmp (char *filename)
{
  ULONG *cols;

  struct imgbm *ibm;
  struct imgbm *ret = NULL;
  struct BitMapHeader *bmhd;

  struct IFFHandle *iffh;
  struct StoredProperty *sp;


  ULONG error;
  LONG propc[] =
  {
    ID_ILBM, ID_BMHD,
    ID_ILBM, ID_CMAP,
    ID_ILBM, ID_BODY,
  };

  UBYTE *rgb;
  ULONG gun;
  int i;
  struct ContextNode *cn;


  if ((iffh = AllocIFF ()))
    {
      if ((iffh->iff_Stream = Open (filename, MODE_OLDFILE)))
	{
	  InitIFFasDOS (iffh);

	  if ((error = OpenIFF (iffh, IFFF_READ)) == 0)
	    {

	      if (((PropChunks (iffh, propc, 3)) == 0) && (StopChunk (iffh, ID_ILBM, ID_BODY) == 0))
		{

		  if (ParseIFF (iffh, IFFPARSE_SCAN) == 0)
		    {

		      if ((sp = FindProp (iffh, ID_ILBM, ID_BMHD)))
			{
			  bmhd = (struct BitMapHeader *) sp->sp_Data;

			  if ((sp = FindProp (iffh, ID_ILBM, ID_CMAP)))
			    {
			      if ((cols = (ULONG *) AllocVecPooled (gd.gd_pool, sizeof (ULONG) * sp->sp_Size)))
				{

				  rgb = (UBYTE *) sp->sp_Data;

				  for (i = 0; i < sp->sp_Size; i++, rgb++)
				    {
				      gun = cols[i] = *rgb;
				      cols[i] |= ((gun << 24) | (gun << 16) | (gun << 8));
				    }

				  cn = CurrentChunk (iffh);
				  if ((ibm = (struct imgbm *) AllocSPooled (gd.gd_pool, sizeof (struct imgbm))))
				    {
				      if ((ibm->body = (UBYTE *) AllocVecPooled (gd.gd_pool, cn->cn_Size)))
					{
					  ReadChunkBytes (iffh, ibm->body, cn->cn_Size);

					  ibm->cols = cols;
					  CopyMem ((APTR) bmhd, (APTR) & ibm->bmhd, sizeof (struct BitMapHeader));

					  // return value
					  ret = ibm;
					}
				      else
					FreeSPooled (gd.gd_pool, ibm, sizeof (struct imgbm));
				    }
				}
			      if (!ret)
				FreeVecPooled (gd.gd_pool, cols);
			    }
			  else
			    D (kprintf ("No ID_CMAP\n"));
			}
		      else
			D (kprintf ("No find prop!\n"));
		    }
		  else
		    D (kprintf ("Error scanning iff!\n"));
		}
	      else
		D (kprintf ("No propchunk!\n"));

	      CloseIFF (iffh);
	    }
	  else
	    D (kprintf ("No open iff!\n"));

	  Close (iffh->iff_Stream);
	}
      else
	D (kprintf ("No open file!\n"));

      FreeIFF (iffh);
    }
  else
    D (kprintf ("No Alloc iff!\n"));

  return (ret);
}
///

/// "New"
ULONG
mImageIFF_New (struct IClass * cl, Object * obj, struct opSet * msg)
{
  char *filename;
  struct imgbm *ibm;

  filename = (STRPTR) GetTagData (MUIA_ImageIFF_Filename, NULL, msg->ops_AttrList);

  if ((ibm = getbmp (filename)))
    {
      // *INDENT-OFF*
      obj = (Object *) DoSuperNew (cl, obj,
                                     MUIA_Bodychunk_Body, ibm->body,
                                     MUIA_Bodychunk_Compression, ibm->bmhd.bmh_Compression,
                                     MUIA_Bodychunk_Depth, ibm->bmhd.bmh_Depth,
                                     MUIA_Bodychunk_Masking, ibm->bmhd.bmh_Masking,
                                     MUIA_FixWidth, ibm->bmhd.bmh_Width,
                                     MUIA_FixHeight, ibm->bmhd.bmh_Height,
                                     MUIA_Bitmap_Height, ibm->bmhd.bmh_Height,
                                     MUIA_Bitmap_Width, ibm->bmhd.bmh_Width,
                                     MUIA_Bitmap_SourceColors, ibm->cols,
                                     MUIA_Bitmap_Transparent, 0L,
                                     MUIA_Bitmap_UseFriend, TRUE,
                                     TAG_MORE, msg->ops_AttrList);
      // *INDENT-ON*






      if (obj)
	{
	  register struct ImageIFF_Data *data = (struct ImageIFF_Data *) INST_DATA (cl, obj);

	  data->cols = ibm->cols;
	  data->body = ibm->body;

	  FreeSPooled (gd.gd_pool, ibm, sizeof (struct imgbm));

	  return ((ULONG) obj);
	}
      else
	error_req (STRING (MSG_OK, "*_OK"), STRING (ERR_NOMEM, "Out of Memory"));

      FreeVecPooled (gd.gd_pool, ibm->body);
      FreeVecPooled (gd.gd_pool, ibm->cols);
      FreeSPooled (gd.gd_pool, ibm, sizeof (struct imgbm));
    }
  else				// try with src image if there is!

    {
      struct BitMapHeader *bmhd;
      UBYTE *body;
      ULONG *cols;

      bmhd = (struct BitMapHeader *) GetTagData (MUIA_ImageIFF_BitMapHeader, NULL, msg->ops_AttrList);
      body = (UBYTE *) GetTagData (MUIA_ImageIFF_Body, NULL, msg->ops_AttrList);
      cols = (ULONG *) GetTagData (MUIA_ImageIFF_SourceColors, NULL, msg->ops_AttrList);

      if (bmhd && body && cols)
	{
       // *INDENT-OFF*
       obj = (Object *) DoSuperNew (cl, obj,
                                     MUIA_Bodychunk_Body, body,
                                     MUIA_Bodychunk_Compression, bmhd->bmh_Compression,
                                     MUIA_Bodychunk_Depth, bmhd->bmh_Depth,
                                     MUIA_Bodychunk_Masking, bmhd->bmh_Masking,
                                     MUIA_FixWidth, bmhd->bmh_Width,
                                     MUIA_FixHeight, bmhd->bmh_Height,
                                     MUIA_Bitmap_Height, bmhd->bmh_Height,
                                     MUIA_Bitmap_Width, bmhd->bmh_Width,
                                     MUIA_Bitmap_SourceColors, cols,
                                     MUIA_Bitmap_Transparent, 0L,
                                     MUIA_Bitmap_UseFriend, TRUE,
                                     TAG_MORE, msg->ops_AttrList);
      // *INDENT-ON*




	  if (obj)
	    {
	      register struct ImageIFF_Data *data = (struct ImageIFF_Data *) INST_DATA (cl, obj);

	      data->cols = NULL;
	      data->body = NULL;

	      return ((ULONG) obj);
	    }
	  else
	    error_req (STRING (MSG_OK, "*_OK"), STRING (ERR_NOMEM, "Out of Memory"));
	}
      else
	error_req (STRING (MSG_OK, "*_OK"), STRING (ERR_NOIMG, "Error loading button image"));
    }

  return (NULL);
}
///

/// "Dispose"
ULONG
mImageIFF_Dispose (struct IClass * cl, Object * obj, Msg msg)
{
  register struct ImageIFF_Data *data = (struct ImageIFF_Data *) INST_DATA (cl, obj);

  if (data->cols)
    FreeVecPooled (gd.gd_pool, data->cols);

  if (data->body)
    FreeVecPooled (gd.gd_pool, data->body);

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

/// "Dispatcher"
SAVEDS (ULONG)
ImageIFF_Dispatcher (REG (a0, struct IClass * cl), REG (a2, Object * obj), REG (a1, Msg msg))
{

  switch (msg->MethodID)
    {
    case OM_NEW:
      return (mImageIFF_New (cl, obj, (struct opSet *) msg));
    case OM_DISPOSE:
      return (mImageIFF_Dispose (cl, obj, (Msg) msg));
    }

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