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




#define _POPUP_C_
#include "ezfm.h"

/************************************************************************************/
EZ_Widget *createPopupFileInfo  MY_ANSIARGS((FileInfo *finfo));
void copyMoveLinkCB  MY_ANSIARGS((EZ_Widget *widget, void *data));
void popupInfoDialogue  MY_ANSIARGS((EZ_Widget *widget, void *data));
/************************************************************************************/
static int getActionItemsOnPopup MY_ANSIARGS((FileInfo *finfo, EZ_Widget *popup));
static void renameCB  MY_ANSIARGS((EZ_Widget *widget, void *data));
static void deleteFileCB  MY_ANSIARGS((EZ_Widget *widget, void *data));
/************************************************************************************/
typedef struct {
  void         (*function)();
  FileInfo     *finfo;
  char         command[1024];
} MActionRecord;
/************************************************************************************/
static void popupCallback(popup, data)
     EZ_Widget *popup; void *data;
{
  EZ_DestroyWidget(popup);
}
/************************************************************************************/
static void updateCB(nbtn, data)
     EZ_Widget *nbtn; void *data;
{
  Folder *folder = (Folder *)data;
  if(folder) updateFolder(folder, 100);
}
/************************************************************************************/
static void removeIconCB(nbtn, data)
     EZ_Widget *nbtn; void *data;
{
  Icon *icon = (Icon *)data;
  if(icon) { deleteIcon(icon);}
}
/************************************************************************************/
static void mAItemCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  if(data)
    {
      MActionRecord *arec = (MActionRecord *)data;
      if(arec->function) /* builtin action */
	(arec->function)(NULL, arec->finfo);
      else if(arec->command[0]) /* external commands */
	executeShCmd(arec->command, NULL, 0, NULL);
    }
}
/************************************************************************************/
static void mAItemDestroyCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  if(data) (void) EZ_Free(data);
}
/************************************************************************************/
static void printCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      char *pathname = finfo->pathname;
      doPrintDialogue(pathname);
    }
}
/************************************************************************************/
static void trashCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      char *pathname = finfo->pathname;
      move2Trashcan(pathname);
    }
}
/************************************************************************************/
static void deleteFileCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      char *pathname = finfo->pathname;
      char command[1024], *ptr, *q;
      strcpy(command, "/bin/rm -rf  ");
      ptr = command + 12; *ptr++='\"'; /* " */
      q = pathname;
      while(*q) 
        {
          if(*q == '"') { *ptr++ ='\\'; *ptr++='\"'; q++;} /* " */
          else *ptr++ = *q++;          
        }
      *ptr++ = '\"'; *ptr++ = 0; /* " */
      oneCommandDialogue(" Delete ",  "Please CONFIRM !", command, 0,
			 NULL, 0, NULL);
    }
}
/************************************************************************************/
static void renameCB(widget, data) 
     EZ_Widget *widget; void *data;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      char command[1024], tmp[500], smp[500], *ptr, *q;
      char *pathname = finfo->pathname;
      ptr = tmp; q = pathname;
      *ptr++='\"'; /* " */
      while(*q) 
        {
          if(*q == '"') { *ptr++ ='\\'; *ptr++='\"'; q++;} /* " */
          else *ptr++ = *q++;          
        }      
      *ptr++ = '\"'; *ptr++ = 0; /* " */

      strcpy(smp, pathname);
      ptr = strrchr(tmp, '/');
      if(ptr) ptr[1] = '\0';
      sprintf(command, "/bin/mv -f %s %s/", tmp, smp);
      oneCommandDialogue("Rename", "Please enter the new name", command, 'e',
			 NULL, 0, NULL);
    }
}
/************************************************************************************/
void popupInfoDialogue(widget, data)
     EZ_Widget *widget; void *data;
{
  FileInfo *finfo = (FileInfo *)data;
  if(finfo)
    {
      int type = finfo->type;
      char *pathname = finfo->pathname;
      char info_str[512];
      struct stat statbuf;
      if(getFileInfo(pathname, info_str, &statbuf) >= 90)
	infoDialogue(pathname, info_str, &statbuf, NULL);
    }
}
/******************************************************************/
static void openWithCB(widget, data)
     EZ_Widget *widget; void *data;
{
  if(data)
    {
      FileInfo *finfo = (FileInfo *)data;
      char     *pathname = finfo->pathname;
      oneCommandDialogue("Open With ...",  "Please complete the command ... ", pathname, 'e',
			 NULL, 0, NULL);
    }
}
/******************************************************************/
    
EZ_Widget *createPopupFileInfo(finfo)
     FileInfo *finfo;
{
  if(finfo)
    {
      struct stat stat_buf;
      char        *pathname = finfo->pathname;
      char        *name = "Current Folder";
      int         type = finfo->type;
      
      if(type != FOLDER)
	{
	  name = strrchr(pathname, '/');
	  if(name && name[1]) name++; 
	  else name = pathname;
	}
      if(stat(pathname, &stat_buf) >= 0)
	{
	  EZ_Widget *popup, *tmp;

	  popup = EZ_CreateWidgetXrm(EZ_WIDGET_POPUP_MENU,     NULL,
				     "PopupMenu",             "popupMenu",
				     EZ_LABEL_STRING,          name,
				     EZ_MENU_TEAR_OFF,         False,
				     EZ_CALLBACK,              popupCallback, popup,
				     NULL);
	  if((tmp = EZ_GetPopupMenuTitleWidget(popup)) != NULL)
	    {
	      char      *tspec = finfo->ezfmData;
	      char      *label, *clr="black", color[256];
	      int       fontId;
	      getSpecColor(tspec, color); if(color[0]) clr = color;
	      fontId = getSpecFontId(tspec);
	      EZ_ConfigureWidget(tmp,
				 EZ_FONT_ID,    ezfmFontId[fontId],
				 EZ_FOREGROUND, clr,
				 NULL);
	    }
	  
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Properties ...",
				 EZ_CALLBACK,       popupInfoDialogue, finfo,
				 NULL);
	  if(type == FOLDER)
	    {
	      tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				     EZ_LABEL_STRING,  "Update",
				     EZ_FOREGROUND,     "red",
				     EZ_CALLBACK,       updateCB, finfo->obj,
				     NULL);
	    }
	  else if(type == ICON)
	    {
	      tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				     EZ_LABEL_STRING,  "Remove Icon",
				     EZ_FOREGROUND,     "red",
				     EZ_CALLBACK,       removeIconCB, finfo->obj,
				     NULL);
	    }
	  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      popup,
				     NULL);

	  /* default actions */
	  getActionItemsOnPopup(finfo, popup);
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Open with ...",
				 EZ_FOREGROUND,    "red",
				 EZ_CALLBACK,       openWithCB, finfo,
				 NULL);
	  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      popup,
				     NULL);
	  /* print */
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Print...",
				 EZ_CALLBACK,       printCB, finfo,
				 NULL);	  
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Rename...",
				 EZ_CALLBACK,       renameCB, finfo,
				 NULL);	  
	  
	  /* copy, move, link */
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Copy,Move...",
				 EZ_CALLBACK,       copyMoveLinkCB, finfo,
				 NULL);	  	  
	  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      popup,
				     NULL);
	  /* put in trash */
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Put in trash...",
				 EZ_CALLBACK,       trashCB, finfo,
				 NULL);	
	  tmp =  EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup, 
				 EZ_LABEL_STRING,  "Really delete...",
				 EZ_CALLBACK,       deleteFileCB, finfo,
				 NULL);	

	  return(popup);
	}
    }
  return(NULL);
}

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

static int getActionItemsOnPopup(finfo, popup)
     FileInfo *finfo; EZ_Widget *popup;
{
  if(finfo && popup)
    {
      int  i, cnt, type, ncmds = 0, isTool = 0;
      char *ptr, *path = finfo->pathname;
      char *spec = finfo->ezfmData;
      char **cmds;
      char tmpstr[256];
      EZ_Widget *mitem;

      if(finfo->type == ICON)
	{
	  Icon *icon = finfo->obj;
	  if(icon && icon->isTool) isTool = 1;
	}
      
      cmds = ezfmExtractDoubleClickCommands(spec, &ncmds);
      if(cmds == NULL) return(0);

      for(cnt = 0, i = 0; i < ncmds; i++)
	{
	  char  *cmd = NULL, *btnLabel = NULL;
	  char  *ptr, command[1024];
	  void  (*function)();
	  int   internal = 0;

	  ptr = cmds[i];
	  function = NULL;
	  if(ptr[0] == '$')
	    {
	      char *d = tmpstr, *s = ptr+1;
	      while(*s && *s != ' ' && *s !='\t') *d++ = *s++;  *d = '\0';
	      cmd = lookupNameFromHashTable(tmpstr);
	      if(cmd) btnLabel = tmpstr;
	    }
	  else if(ptr[0] == '@')
	    {
	      char *d = tmpstr, *s = ptr+1;
	      while(*s && *s != ' ' && *s !='\t') *d++ = *s++;  *d = '\0';
	      function = ezfmGetBuiltInCommand(tmpstr);
	      internal = 1;
	      if(function)
		{
		  btnLabel = tmpstr;
		  cmd = ptr+1;
		}
	    }
	  else
	    {
	      cmd = ptr;
	      btnLabel = ptr;
	    }
	  /*printf("\t\t(%s)(%s)\n", btnLabel, cmd);*/
	  if(btnLabel != NULL)
	    {
	      MActionRecord *aRec = (MActionRecord *)EZ_Malloc(sizeof(MActionRecord));
	      aRec->function = function;
	      aRec->finfo    = finfo;
	      if(internal == 0)
		ezfmProcessCmdline(cmd, isTool? NULL : finfo->pathname, aRec->command);
	      else aRec->command[0] = '\0';

	      cnt++;
	      mitem = EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON, popup,
				      EZ_LABEL_STRING,              btnLabel,
				      EZ_FOREGROUND,                "blue",
				      EZ_CALLBACK,                  mAItemCB, aRec,
				      EZ_DESTROY_CALLBACK,          mAItemDestroyCB, aRec,
				      NULL);
	    }
	}
      for(i = 0; i < ncmds; i++) EZ_Free(cmds[i]);
      EZ_Free((char *)cmds);

      return(cnt);
    }
  return(0);
}
/************************************************************************************/

#define DIALOGUE_STRING  "Please complete the pathname"
#define CANCELF         0
#define MOVEF           1
#define COPYF           2
#define LINKF           3

static void destCB(widget, data) EZ_Widget *widget; void *data;
{
  EZ_Widget *bbox = (EZ_Widget *)data;  
  EZ_CallWidgetCallbacks(bbox);
}

static void bboxCB(widget, data) EZ_Widget *widget; void *data;
{
  EZ_Widget *btn = getBboxCurrentButton(widget);
  EZ_Widget *dest, *src = (EZ_Widget *)data;
  if(btn && src && (dest = (EZ_Widget *)EZ_GetWidgetPtrData(src)))
    {
      char *si = EZ_GetEntryString(src);
      char *ti = EZ_GetEntryString(dest);
      char s[512], t[512];
      int  which = EZ_GetWidgetIntData(btn);
      char command[1024];
      ezfmQuotePathname(si, s);
      ezfmQuotePathname(ti, t);
      if(which == MOVEF)        sprintf(command, "mv %s %s",s,t);
      else if(which == COPYF)   sprintf(command, "cp %s %s",s,t);
      else if(which == LINKF)   sprintf(command, "ln -s %s %s",s,t);
      else which = 0;
      EZ_HideWidget(EZ_GetToplevelWidget(widget));
      if(which != 0)  executeShCmd(command, NULL, 0, NULL);
    }
}


void copyMoveLinkCB(widget, data)
     EZ_Widget *widget; void *data;
{
  static EZ_Widget *Dialogue = NULL;

  FileInfo *finfo = (FileInfo *)data;
  char *pathname = finfo->pathname;
  
  if(!EZ_WidgetExist(Dialogue))
    {
      EZ_Widget *label, *fframe, *frame, *l1, *l2, *src, *dest, *bbox;
      EZ_Widget *move, *copy, *link, *cancel;
      Dialogue =    EZ_CreateWidget(EZ_WIDGET_FRAME,       NULL,
				    EZ_ORIENTATION,        EZ_VERTICAL,
				    EZ_TRANSIENT,          True,
				    EZ_FILL_MODE,          EZ_FILL_HORIZONTALLY,
				    EZ_PADY,               10,
				    NULL);
      label  =   EZ_CreateWidget(EZ_WIDGET_LABEL,       Dialogue,
				 EZ_BORDER_TYPE,        EZ_BORDER_RAISED,
				 EZ_BORDER_WIDTH,       0,
				 EZ_WIDTH,              0,
				 EZ_LABEL_STRING,       DIALOGUE_STRING,
				 EZ_FOREGROUND,         "red",
				 EZ_FONT_ID,            ezfmFontId[LABEL_LARGE_FONT],
				 EZ_TEXT_LINE_LENGTH,   40,
				 NULL);
      fframe =   EZ_CreateWidget(EZ_WIDGET_FRAME,       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);
      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_ENTRY_EDITABLE,     False,
				 EZ_TEXT_LINE_LENGTH,   40,
				 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);
      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_PADX,                4,
				 EZ_PADY,                3,
				 NULL);

      bbox =  createButtonBox(Dialogue, NULL);
      EZ_AddWidgetCallBack(bbox, EZ_CALLBACK, bboxCB, src, 0);
      EZ_AddWidgetCallBack(dest, EZ_CALLBACK, destCB, bbox, 0);
      move = newBboxButton(bbox, 1);
      EZ_ConfigureWidget(move,
			 EZ_LABEL_STRING,        "move",
			 EZ_UNDERLINE,           0,
			 EZ_CLIENT_INT_DATA,     MOVEF,
			 NULL);
      copy = newBboxButton(bbox, 0);
      EZ_ConfigureWidget(copy,
			 EZ_LABEL_STRING,        "copy",
			 EZ_UNDERLINE,           0,
			 EZ_CLIENT_INT_DATA,     COPYF,
			 NULL);
      link = newBboxButton(bbox, 0);
      EZ_ConfigureWidget(link,
			 EZ_LABEL_STRING,        "link",
			 EZ_UNDERLINE,           0,
			 EZ_CLIENT_INT_DATA,     LINKF,
			 NULL);
      cancel = newBboxButton(bbox, 0);
      EZ_ConfigureWidget(cancel,
			 EZ_LABEL_STRING,        "cancel",
			 EZ_UNDERLINE,           1,
			 EZ_CLIENT_INT_DATA,     CANCELF,
			 NULL);
      EZ_SetWidgetPtrData(Dialogue, src);
      EZ_SetWidgetPtrData(src, dest);
    }
  /* setup */
  {
    char tstr[256], *ptr;
    EZ_Widget *src, *dest;


    src = (EZ_Widget *)EZ_GetWidgetPtrData(Dialogue);
    dest = (EZ_Widget *)EZ_GetWidgetPtrData(src);

    EZ_SetEntryString(src, pathname);
    strcpy(tstr, pathname);
    ptr = strrchr(tstr, '/'); if(ptr) ptr[1] = '\0';
    EZ_SetEntryString(dest, tstr);
    EZ_DisplayWidgetUnderPointer(Dialogue, -10, -10);
    EZ_SetFocusTo(dest);
  }
}
/************************************************************************************/
#undef _POPUP_C_
