/*********************************************************************
 *
 *            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. 
 *
 *************************************************************************/




/***************************************************************************
 *
 *  Folder DnD decoding filter. When a file is draged and released on a
 *  folder/folder-item/folder-icon, the start filter is called to select
 *  the best target. (e.g, use copy file by name instead of copy file
 *  by content if the src is a local file.)
 *
 */
#define _DNDC_C_
#include "ezfm.h"

int dirDnDTargetStartFilter MY_ANSIARGS((void *obj, void *data, char *msg, int len));
int dirDnDTargetFinishFilter MY_ANSIARGS((void *obj, void *data, char *msg, int len));

/***************************************************************************
 *
 *  Dropsite filters.
 */
#define DIALOGUE_STRING  "Please confirm your DnD operation"
/*
 * pop a dialogue ask for confirmation
 */
typedef struct _dialogueJunk {
  EZ_Widget *src, *dest, *dialogue, *move, *copy, *cancel, *link;
} Dialogue;

static void folderTargetDialogueCallback(widget, data)
     EZ_Widget *widget; void *data;
{
  if(widget)
    {
      Dialogue *dg = (Dialogue *)EZ_GetWidgetPtrData(widget);
      *(int *)data = EZ_GetWidgetIntData(widget);
      EZ_HideWidget(dg->dialogue);
      EZ_ReleaseGrab();
    }
}

static int folderGetTargetType(actionType, srcF, destD, multiple)
     unsigned int actionType; char *srcF, *destD; int multiple;
{
  static Dialogue dg = { NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  static int return_value;
  EZ_Widget *focus = NULL;
  int   tmp = EZFM_CANCEL;

  return_value = -1;
  if(dg.dialogue == NULL)
    {
      EZ_Widget *label, *fframe, *frame, *l1, *l2;
      dg.dialogue = EZ_CreateWidgetXrm(EZ_WIDGET_FRAME,       NULL,
				       "DndDialogue",      "dndDialogue",
				       EZ_ORIENTATION,        EZ_VERTICAL,
				       EZ_TRANSIENT,          True,
				       EZ_FILL_MODE,          EZ_FILL_HORIZONTALLY,
				       EZ_PADY,               10,
				       EZ_BG_PIXMAP,      bigPixmap,
				       EZ_EVENT_HANDLER,   ConfigureNotifyHandler, NULL,
				       NULL);
      label  =   EZ_CreateWidget(EZ_WIDGET_LABEL,       dg.dialogue,
				 EZ_BORDER_TYPE,        EZ_BORDER_RAISED,
				 EZ_BORDER_WIDTH,       0,
				 EZ_WIDTH,              0,
				 EZ_LABEL_STRING,       DIALOGUE_STRING,
				 EZ_FOREGROUND,         "red",
				 EZ_FONT_NAME,          "-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*",
                                 EZ_LABEL_SHADOW,       1,1,
				 EZ_TEXT_LINE_LENGTH,   40,
				 NULL);
      fframe =   EZ_CreateWidget(EZ_WIDGET_FRAME,       dg.dialogue,
				 EZ_FILL_MODE,          EZ_FILL_HORIZONTALLY,
				 EZ_GRID_CONSTRAINS,    EZ_COLUMN, 1, 100, 1000, 4,
				 NULL);
      l1 =       EZ_CreateWidget(EZ_WIDGET_LABEL,       fframe,
				 EZ_LABEL_STRING,       "Source:",
				 EZ_PADX,                0,
				 EZ_PADY,                0,
				 EZ_LABEL_POSITION,      EZ_RIGHT,
				 EZ_GRID_CELL_GEOMETRY,  0, 0, 1, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
				 NULL);
      dg.src =   EZ_CreateWidget(EZ_WIDGET_ENTRY,       fframe,
				 EZ_GRID_CELL_GEOMETRY, 1, 0, 1, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
				 EZ_TEXT_LINE_LENGTH,   40,
				 EZ_ENTRY_EDITABLE,     False,
				 EZ_FOREGROUND,         "blue",
				 EZ_PADX,                4,
				 EZ_PADY,                3,
				 NULL);
      l2 =       EZ_CreateWidget(EZ_WIDGET_LABEL,       fframe,
				 EZ_LABEL_STRING,       "Destination:",
				 EZ_LABEL_POSITION,     EZ_RIGHT,
				 EZ_PADX,                0,
				 EZ_PADY,                0,
				 EZ_GRID_CELL_GEOMETRY,  0, 1, 1, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
				 NULL);
      dg.dest =  EZ_CreateWidget(EZ_WIDGET_ENTRY,       fframe,
				 EZ_GRID_CELL_GEOMETRY,      1, 1, 1, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
				 EZ_TEXT_LINE_LENGTH,   40,
				 EZ_ENTRY_EDITABLE,     False,
				 EZ_FOREGROUND,         "blue",
				 EZ_PADX,                4,
				 EZ_PADY,                3,
				 NULL);

      frame =    EZ_CreateWidget(EZ_WIDGET_FRAME,       dg.dialogue,
				 NULL);
      dg.move =     EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON,frame,
				    EZ_LABEL_STRING,        "move",
				    EZ_UNDERLINE,           0,
				    EZ_CLIENT_INT_DATA,     EZFM_MOVE_FILE,
				    EZ_CLIENT_PTR_DATA,     &dg,
				    EZ_CALLBACK,            folderTargetDialogueCallback, (void *)&return_value,
				    NULL);
      dg.copy =     EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON,frame,
				    EZ_LABEL_STRING,        "copy",
				    EZ_UNDERLINE,           0,
				    EZ_CLIENT_INT_DATA,     EZFM_COPY_FILE,
				    EZ_CLIENT_PTR_DATA,     &dg,
				    EZ_CALLBACK,            folderTargetDialogueCallback, (void *)&return_value,
				    NULL);
      dg.link =     EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON,frame,
				    EZ_LABEL_STRING,        "link",
				    EZ_UNDERLINE,           0,
				    EZ_CLIENT_INT_DATA,     EZFM_LINK_FILE,
				    EZ_CLIENT_PTR_DATA,     &dg,
				    EZ_CALLBACK,            folderTargetDialogueCallback, (void *)&return_value,
				    NULL);
      dg.cancel =   EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON,frame,
				    EZ_LABEL_STRING,        "cancel",
				    EZ_UNDERLINE,           1,
				    EZ_CLIENT_INT_DATA,     EZFM_CANCEL,
				    EZ_CLIENT_PTR_DATA,     &dg,
				    EZ_CALLBACK,            folderTargetDialogueCallback, (void *)&return_value,
				    NULL);
    }

  if(actionType == 0)
    {
      focus = dg.move;
      EZ_DisableWidget(dg.copy);
      EZ_DisableWidget(dg.link);
      if(multiple) tmp =  EZFM_MOVE_MFILES;
      else tmp = EZFM_MOVE_FILE;
    }
  else if(actionType == ControlMask)
    {
      focus = dg.copy;
      EZ_DisableWidget(dg.move);
      EZ_DisableWidget(dg.link);
      if(multiple) tmp = EZFM_COPY_MFILES;
      else tmp = EZFM_COPY_FILE;
    }
  else if(actionType == ShiftMask)
    {
      focus = dg.link;
      EZ_DisableWidget(dg.move);
      EZ_DisableWidget(dg.copy);
      if(multiple) tmp = EZFM_LINK_MFILES;
      else tmp = EZFM_LINK_FILE;
    }
  else
    {
      focus = dg.cancel;
      EZ_DisableWidget(dg.move);
      EZ_DisableWidget(dg.copy);
      EZ_DisableWidget(dg.link);
    }
  if( (ezfmFlags & DONT_CONFIRM_DND_BIT) ) return(tmp);

  EZ_EnableWidget(focus);
  EZ_SetEntryString(dg.src, srcF);
  EZ_SetEntryString(dg.dest, destD);
  EZ_DisplayWidgetUnderPointer(focus, -10, -10);
  EZ_SetGrab(dg.dialogue);
  EZ_SetFocusTo(focus);
  
  while(return_value == -1)  EZ_WaitAndServiceNextEvent();
  if(multiple)
    {
      if(return_value == EZFM_MOVE_FILE) return_value=EZFM_MOVE_MFILES;
      else if(return_value == EZFM_COPY_FILE) return_value=EZFM_COPY_MFILES;
      else if(return_value == EZFM_LINK_FILE) return_value=EZFM_LINK_MFILES;
    }
  return(return_value);
}
/***********************************************************************
 * 
 *   Dropsite target start filter is a decoder registered to the 
 *   special target EZ_DND_DROP_START_ATOM. 
 * 
 */
int dirDnDTargetStartFilter(obj, data, msg, len)
     void *obj; void *data; char *msg; int len;
{
  Atom          *atomsInOut;
  int           *natomsInOut;
  unsigned int  *atypeOut;
  int           i, j, answer, multiple = 0;
  FileInfo      *finfo = (FileInfo *)data;
  Folder        *folder = NULL;
  Icon          *icon = NULL;
  int           srclocal = 1, confirmation, srclen, destlen;
  char          *destpath, *src = msg + PATHNAME_OFFSET;
  char          *ptr;
  char          srcpath[256];

  if(finfo == NULL) return (EZ_DND_FAILURE);

  if(finfo->type == FOLDER) folder = finfo->obj;
  else if(finfo->type == ITEM) folder = finfo->host;
  else if(finfo->type == ICON) icon = finfo->obj;

  if(folder)  folder->blocked++;
  else if(icon) icon->blocked++;
  
  EZ_DnDGetMatchedConversionTargets(&atomsInOut,&natomsInOut, &atypeOut);  

  if(natomsInOut == 0)  return (EZ_DND_FAILURE); /* no matching targets */


  /* the confirmation dialogue is only for move/copy/link files
   * around. Don't popup the dialogue if DnD is for other things
   */
  confirmation = 0;
  for(i = 0; i < *natomsInOut; i++)
    {
      if(atomsInOut[i] == ezfmMoveFileByNameAtom ||
	 atomsInOut[i] == ezfmCopyFileByNameAtom ||
	 atomsInOut[i] == ezfmLinkFileByNameAtom)
        {
	  confirmation = 1;
	  break;
        }
      else if(atomsInOut[i] == ezfmMoveMultipleFilesAtom ||
              atomsInOut[i] == ezfmCopyMultipleFilesAtom ||
              atomsInOut[i] == ezfmLinkMultipleFilesAtom)
	{
	  confirmation = 1;
          multiple = 1;
	  break;
	}
    }
  if(confirmation == 0) return(EZ_DND_SUCCESS);

  /* move/copy/link files */

  if(finfo->glob) 
    {
      *natomsInOut = 0; *atomsInOut = None;
      return (EZ_DND_SUCCESS);
    }

  /* check if src is a ancestor of dest */
  destpath = finfo->pathname;
  destlen = strlen(destpath);
  if(multiple == 0)
    {
      strcpy(srcpath, src);
      srclen = strlen(srcpath);

      if(srclen <= destlen && !strncmp(srcpath, destpath, srclen))
        {
          *natomsInOut = 0; *atomsInOut = None;
          return (EZ_DND_SUCCESS);
        }
      ptr = strrchr(srcpath, '/');
      if(ptr)
        {
          if(ptr != srcpath) ptr[0] = '\0';
          else ptr[1] = '\0';
          if(!strcmp(srcpath, destpath))
            {
              *natomsInOut = 0; *atomsInOut = None;
              return (EZ_DND_SUCCESS);
            }
        }
      srclocal  = canSeeTheFile(src, msg);
    }
  /* pop a confirmation dialogue and get an answer */
  {
    char tstr[1024];
    strcpy(tstr, destpath);
    if(tstr[destlen-1] != '/')
      {tstr[destlen] = '/'; tstr[destlen+1] = '\0';}
    if(multiple)
      {
        char tsrc[1024];
        strcpy(tsrc, src); strcat(tsrc, " ... ");
        answer = folderGetTargetType((int)(*atypeOut), tsrc, tstr, multiple);
      }
    else answer = folderGetTargetType((int)(*atypeOut), src, tstr, multiple);
  }

  j = 0;
  switch(answer)
    {
    case EZFM_MOVE_FILE:
      if(srclocal)
	{      
	  for(i = 0; i < *natomsInOut; i++)
	    {
	      Atom atom = atomsInOut[i]; 
	      if(atom == ezfmMoveFileByNameAtom) { atomsInOut[j++] = atom; break; }
	    }
	}
      *natomsInOut = j;
      break;
    case EZFM_COPY_FILE:
      for(i = 0; i < *natomsInOut; i++)
	{
	  Atom atom = atomsInOut[i]; 
	  if(atom == ezfmCopyFileByNameAtom ||
	     (srclocal == 0 && ( atom == ezfmCopyFileByContentAtom ||
				 atom == ezfmCopyFileByTarAtom)))
	    atomsInOut[j++] = atom;
	}
      *natomsInOut = j;
      break;
    case EZFM_LINK_FILE:
      for(i = 0; i < *natomsInOut; i++)
	{
	  Atom atom = atomsInOut[i]; 
	  if(atom == ezfmLinkFileByNameAtom)
	    {
	      atomsInOut[0] = atom;
	      *natomsInOut = 1;
	      break;
	    }
	}
      break;
    case EZFM_MOVE_MFILES:
      for(i = 0; i < *natomsInOut; i++)
	{
	  Atom atom = atomsInOut[i]; 
	  if(atom == ezfmMoveMultipleFilesAtom)
	    {
	      atomsInOut[0] = atom;
	      *natomsInOut = 1;
	      break;
	    }
	}
      break;
    case EZFM_COPY_MFILES:
      for(i = 0; i < *natomsInOut; i++)
	{
	  Atom atom = atomsInOut[i]; 
	  if(atom == ezfmCopyMultipleFilesAtom)
	    {
	      atomsInOut[0] = atom;
	      *natomsInOut = 1;
	      break;
	    }
	}
      break;
    case EZFM_LINK_MFILES:
      for(i = 0; i < *natomsInOut; i++)
	{
	  Atom atom = atomsInOut[i]; 
	  if(atom == ezfmLinkMultipleFilesAtom)
	    {
	      atomsInOut[0] = atom;
	      *natomsInOut = 1;
	      break;
	    }
	}
      break;
    case EZFM_CANCEL:
      *natomsInOut = 0;
      break;
    }
  return (EZ_DND_SUCCESS);
}

/***********************************************************************
 *
 *  Dropsite target end filter is a decoder registered to the special
 *       Target EZ_DND_DROP_FINISH_ATOM.
 */

int dirDnDTargetFinishFilter(obj, data, msg, len)
     void *obj; void *data; char *msg; int len;
{
  FileInfo   *finfo = (FileInfo *)data;
  Folder     *folder = NULL;
  Icon       *icon = NULL;
  
  if(finfo)
    {
      if(finfo->type == FOLDER) folder = finfo->obj;
      else  if(finfo->type == ITEM) folder = finfo->host;
      else if(finfo->type == ICON) icon = finfo->obj;
    }
  if(folderExists(folder) && folder->blocked > 0)
    {
      folder->blocked--;
      updateFolder(folder, 100);
    }
  else if(icon && icon->blocked > 0) icon->blocked--;

  return(EZ_DND_SUCCESS);
}
/****************************************************************/
#undef _DNDC_C_

