/*********************************************************************
 *
 *            EZFM---EZWGL based file manager for X11
 *
 *             Copyright (C) 1998  Maorong Zou
 *
 *
 *  This file is part of EZFM.
 *
 *  EZFM is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * EZFM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EZFM; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 *************************************************************************/



/***************************************************************************
 *
 *   Item/Icon DnD filters.
 *
 *  When an item/icon is draged, do the following
 *   1.  block its host-folder/icon from updating (if the file is removed or
 *       modified by other processes, updating will delete the drag source. 
 *       Don't want that till DND finishes.)
 *   2.  encode the filename and stat info in the hand-shaking message, this
 *       will allow the drop site to select the best conversion target.
 *
 *  When drag src finishes conversion, the FinishFilter is called to
 *   1. unblock host-folder/icon and
 *   2. in the case when drag is an item, update its host folder.
 */
#define _DNDE_C_
#include "ezfm.h"

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

int ezfmIIEncodeStartFilter MY_ANSIARGS((void *item, void *data, 
					 char **message, int *length,
					 int *needFree));
int ezfmIIEncodeFinishFilter MY_ANSIARGS((void *item, void *data, 
					 char **message, int *length,
					 int *needFree));

int ezfmIIDecodeStartFilter MY_ANSIARGS((void *item, void *data, 
					   char *message, int length));
int ezfmIIDecodeFinishFilter MY_ANSIARGS((void *item, void *data, 
					  char *message, int length));

int ezfmFolderEncodeStartFilter MY_ANSIARGS((void *item, void *data, 
                                             char **message, int *length,
                                             int *needFree));
int ezfmFolderEncodeFinishFilter MY_ANSIARGS((void *item, void *data, 
					 char **message, int *length,
					 int *needFree));

/***************************************************************************
 *
 *  Drag src start filter. We append the pathname and stat 
 *  info to the dropsite in the initial handshaking message.
 *  Block host folder if drag src is an item.
 */
int ezfmIIEncodeStartFilter(obj, data, msg, len, needFree)
     void *obj; void *data; char **msg; int *len; int *needFree;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      if(finfo->type == ITEM)
	{
	  Folder *folder = finfo->host;
	  if(folder != NULL) folder->blocked++;
	}
      else if(finfo->type == ICON)
	{
	  Icon *icon = finfo->obj;
	  if(icon) icon->blocked++;
	}
    }
  return(finfoEncodeFileName(finfo, msg, len, needFree));  
}

/***************************************************************************
 *
 *  Drag src finish filter. If drag src is an item, unblock host folder 
 *  and update the folder if necessary.
 */
int ezfmIIEncodeFinishFilter(obj, data, msg, len, needFree)
     void *obj; void *data; char **msg; int *len; int *needFree;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      if(finfo->type == ITEM)
	{
	  Folder *folder = finfo->host;
	  if(folder != NULL && folder->blocked > 0)
	    {
	      folder->blocked--;
              folder->flags |= DND_UPDATE_PENDING;
              updateFolder(folder,100); 
	    }
	}
      else if(finfo->type == ICON)
	{
	  Icon *icon = finfo->obj;
	  if(icon && icon->blocked > 0) icon->blocked--;
	}
    }
  return(EZ_DND_SUCCESS);
}

/***********************************************************************
 *
 * Decoder setup routine for dropsite which is not a directory.
 *
 *   1. If drag src is a local file, only request src to convert FileName.
 *   2. If dropsite is an item, block its host folder.
 *   3. If drag src is target, ignore.
 */
int ezfmIIDecodeStartFilter(item, data, msg, len )
     void *item; void *data; char *msg; int len;
{
  Atom          *atomsInOut;
  int           *natomsInOut;
  unsigned int  *atypeOut;
  Atom          atoms[32];
  int           i, j, answer;
  FileInfo      *finfo = (FileInfo *)data;
  Folder        *folder = NULL;
  int           srclocal;
  char          *dest, *src = msg + PATHNAME_OFFSET;

  if(finfo)
    {
      if(finfo->type == ITEM)
	{
	  Folder *folder = finfo->host;
	  if(folder != NULL) folder->blocked++;
	}
      else if(finfo->type == ICON)
	{
	  Icon *icon = finfo->obj;
	  if(icon) icon->blocked++;
	}
      
      EZ_DnDGetMatchedConversionTargets(&atomsInOut,&natomsInOut, &atypeOut);  
      dest = finfo->pathname;
      if(!strcmp(src, dest)) /* drag onto oneself is not allowed */
	{
	  *natomsInOut = 0; *atomsInOut = None;
	  return (EZ_DND_SUCCESS);
	}

      if(canSeeTheFile(src, msg)) /* local file, only need FileName */
	{
	  for(i = 0, j = 0; i < *natomsInOut; i++)
	    {
	      Atom atom = atomsInOut[i]; 
	      if(atom == ezfmFileNameAtom) atoms[j++] = atom;
	    }
	}
      else  /* remote file, request content */
	{
	  for(i = 0, j = 0; i < *natomsInOut; i++)
	    {
	      Atom atom = atomsInOut[i]; 
	      if(atom == ezfmFileContentAtom || atom == ezfmFileTaredContentAtom)
		atoms[j++] = atom;
	    }
	}
      for(i = 0; i < j; i++) atomsInOut[i] = atoms[i];
      *natomsInOut = j;
      return (EZ_DND_SUCCESS);      
    }
  return(EZ_DND_SUCCESS);
}

/***********************************************************************
 *
 * Decoder clean up, if dropsite is an item, unblock its host folder and
 * update the folder.
 */
int ezfmIIDecodeFinishFilter(item, data, msg, len )
     void *item; void *data; char *msg; int len;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      if(finfo->type == ITEM)
	{
	  Folder *folder = finfo->host;
	  if(folderExists(folder) && folder->blocked > 0)
	    {
	      folder->blocked--;
              updateFolder(folder,100); 
              folder->flags |= DND_UPDATE_PENDING;
	    }
	}
      else if(finfo->type == ICON)
	{
	  Icon *icon = finfo->obj;
	  if(icon && icon->blocked > 0)  icon->blocked--;
	}
    }
  return(EZ_DND_SUCCESS);
}
/***************************************************************************
 *
 *  Drag src start filter. We append the pathname and stat 
 *  info to the dropsite in the initial handshaking message.
 *  Block host folder if drag src is an item.
 */
int ezfmFolderEncodeStartFilter(obj, data, msg, len, needFree)
     void *obj; void *data; char **msg; int *len; int *needFree;
{
  Folder *folder = (Folder *)data;
  if(folder)
    {
      EZ_Widget *widget;
      EZ_Item   **items = NULL;
      int cnt, type = folder->type; 

      switch(type)
        {
        case ICON_FOLDER:
          items = EZ_WorkAreaGetHighlightedItemsA(folder->workarea, &cnt);
          break;
        case ICON_FOLDER_SMALL:
          items = EZ_WorkAreaGetHighlightedItemsA(folder->workareaS, &cnt);
          break;
        case LIST_FOLDER:
          items =EZ_FancyListBoxGetHighlightedItemsA(folder->flistbox, &cnt);
          break;
	case TREE_FOLDER:
          items = EZ_ListTreeGetHighlightedItemsA(folder->listtree, &cnt);
          break;
        }
      if(items) 
        {
          struct stat   stat_buf;
          FileInfo      *finfo = EZ_GetItemPtrData(items[0]);
          (void)free(items);
          folder->blocked++;
          return(finfoEncodeFileName(finfo, msg, len, needFree));
        }
    }
  return(EZ_DND_SUCCESS);
}
/***********************************************************************/
int ezfmFolderEncodeFinishFilter(obj, data, msg, len, needFree)
     void *obj; void *data; char **msg; int *len; int *needFree;
{
  Folder *folder = (Folder *)data;
  if(folder)
    {
      folder->blocked--;
      folder->flags |= DND_UPDATE_PENDING;
      updateFolder(folder,100); 
    }
  return(EZ_DND_SUCCESS);
}
/***********************************************************************/
#undef _DNDE_C_


