/*********************************************************************
 *
 *            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 _MBTN_FILE_C_
#include "ezfm.h"

/**********************************************************************************/
void setupMBtnFile      MY_ANSIARGS((void *btn, void *data));
void disableMtnFileNewFileDirItems MY_ANSIARGS((void));
void enableMtnFileNewFileDirItems MY_ANSIARGS((void));

void mBarItemDestroyCB  MY_ANSIARGS((void *widget, void *data));
void gotoHome           MY_ANSIARGS((void *widget, void *data));
void startFolder         MY_ANSIARGS((Folder *fldr, char *iname, char *title, char *instr));

/**********************************************************************************/
static void newFolder   MY_ANSIARGS((void *widget, void *data));
static void newFile     MY_ANSIARGS((void *widget, void *data));

static void gotoFolder  MY_ANSIARGS((void *widget, void *data));
static void findFiles   MY_ANSIARGS((void *widget, void *data));

static void closeFolder  MY_ANSIARGS((void *widget, void *data));
static void beCallback  MY_ANSIARGS((void *widget, void *data));
static void cancelCallback  MY_ANSIARGS((void *widget, void *data));
static int  entryDecodeFileName MY_ANSIARGS ((void *obj, void *data, char *msg, int len));
static void updateFileMenu MY_ANSIARGS((void *widget, void *data));


#define NEW_FOLDER_ITEM      0
#define NEW_FILE_ITEM        1
#define OPEN_DRIVES_START    2

/**********************************************************************************
 *
 */
void mBarItemDestroyCB(mitem, data)  EZ_Widget *mitem; void *data;
{
  EZ_Widget *theMenu = (EZ_Widget *)data;
  EZ_DestroyWidget(theMenu);
}
/**********************************************************************************
 *
 * setup MenuButton 'File'
 */
void setupMBtnFile(mbar, data)
     EZ_Widget *mbar; void *data; 
{
  Toplevel  *toplevel = (Toplevel *)data;
  EZ_Widget *menu, *tmp, *mitem;
  EZ_UnknownDataType unknown;
  
  menu =     EZ_CreateWidgetXrm(EZ_WIDGET_MENU,      NULL,
				"FileMenu", "fileMenu",
				EZ_MENU_TEAR_OFF,    1,
				NULL);
  EZ_SetMenuSetupProcedure(menu, updateFileMenu, data);

  /* new folder/file buttons */
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "New Folder...",
			     EZ_UNDERLINE,                  0,
			     EZ_CALLBACK,                   newFolder, data,
			     NULL);
  unknown.p = tmp;
  EZ_SetWidgetUnknownData(menu, NEW_FOLDER_ITEM, unknown);

  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "New File...",
			     EZ_UNDERLINE,                  2,
			     EZ_CALLBACK,                   newFile, data,
			     NULL);
  unknown.p = tmp;
  EZ_SetWidgetUnknownData(menu, NEW_FILE_ITEM, unknown);
  
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      menu,
			     NULL);

  /* goto ... find ... buttonds */
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "Go Home",
			     EZ_UNDERLINE,                  3,
			     EZ_CALLBACK,                   gotoHome, data,
			     NULL);
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "Goto ...",
			     EZ_UNDERLINE,                  0,
			     EZ_CALLBACK,                   gotoFolder, data,
			     NULL);
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "Find ...",
			     EZ_UNDERLINE,                  0,
			     EZ_CALLBACK,                   findFiles, data,
			     NULL);
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      menu,
			     NULL);


  /* Removable drives */
#ifdef REMOVABLE_DRIVES
  {
    int i;
    for(i = 0; i < 8; i++)
      {
	int status = ezfmDrives[i].status;
	int ivalue;
	if( status >= 0)
	  {
	    char       labstr[64];
	    sprintf(labstr,"Open %s", ezfmDrives[i].name);

	    tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
				       EZ_LABEL_STRING,               labstr,
				       EZ_CLIENT_INT_DATA,            i,
				       EZ_CALLBACK,                   openDrive, data,
				       NULL);
	  }
	else break;
      }
  }
#endif
  
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_SEPARATOR,      menu,
			     NULL);  
  /* close button */
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "Close",
			     EZ_UNDERLINE,                  0,
			     EZ_CALLBACK,                   closeFolder, data,
			     NULL);
  /* exit button */
  tmp  =     EZ_CreateWidget(EZ_WIDGET_MENU_NORMAL_BUTTON,  menu,
			     EZ_LABEL_STRING,               "Exit",
			     EZ_UNDERLINE,                  0,
			     EZ_CALLBACK,                   exitEzfm, data,
			     NULL);

  mitem = EZ_MenuBarAddItemAndMenu(mbar, "File", 0, menu);
  EZ_AddWidgetCallBack(mitem, EZ_DESTROY_CALLBACK, mBarItemDestroyCB, menu, 0);
}
/******************************************************************************
 *
 * make a new directory in current folder
 */
static void newFolder(widget, data)
     EZ_Widget *widget;  void *data;     
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      FileInfo  *dinfo;
      char      *pathname;
      char command[1024];
      Folder    *folder = tp->activeFolder;

      if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
      dinfo = folder->finfo;
      pathname = dinfo->pathname;

      sprintf(command, "mkdir %s/", pathname);
      oneCommandDialogue("New Folder", "Please Complete the Folder Name", command, 'e',
			 NULL, 0, NULL);
    }
}

/******************************************************************************
 *
 * make a new file in current folder
 */
static void newFile(widget, data)
     EZ_Widget *widget;  void *data;     
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      FileInfo  *dinfo;
      char      *pathname;
      char command[1024];
      Folder    *folder = tp->activeFolder;

      if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
      dinfo = folder->finfo;
      pathname = dinfo->pathname;

      sprintf(command, "touch %s/", pathname);
      oneCommandDialogue("New File", "Please Complete the File Name", command, 'e',
			 NULL, 0, NULL);
    }
}
/******************************************************************************
 *
 *   goto a specified folder
 */
static void gotoCancelCallback(widget, data)
     EZ_Widget *widget; void *data;
{
  EZ_Widget *frame = (EZ_Widget *)data;
  EZ_DestroyWidget(frame);      
}

static void gotoEntryCallback(widget, data)
     EZ_Widget *widget; void *data;
{
  EZ_Widget *entry = (EZ_Widget *)data;
  EZ_Widget *frame = (EZ_Widget *)EZ_GetWidgetPtrData(entry);
  Folder *folder = (Folder *)EZ_GetWidgetPtrData(frame);
  char *str = EZ_GetEntryString(entry);
  if(folder == NULL)  OpenFolder(str, NULL, 1, 0);
  else 
    {
      if(folderExists(folder))  OpenFolder(str, folder, 1, 0);
      else  ezfmWarning("Goto ...", "Folder no longer exists");
    }
  EZ_DestroyWidget(frame);      
}

static void gotoFolder(widget, data)
     EZ_Widget *widget; void *data;
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      char      *pathname;
      FileInfo  *dinfo;
      Folder    *folder = tp->activeFolder;
      if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
      dinfo = folder->finfo;
      pathname = dinfo->pathname;
      startFolder(folder, pathname, "Goto ...", "Please enter a folder name");
    }
}

void startFolder(folder, pathname, title, instr) 
     Folder *folder; char *pathname, *title, *instr;
{
  EZ_Widget *frame, *entry, *label, *btn, *cancel;

  frame = EZ_CreateWidget(EZ_WIDGET_FRAME,    NULL,
			  EZ_TRANSIENT,       True,
			  EZ_FONT_ID,         ezfmFontId[LABEL_LARGE_FONT],
			  EZ_LABEL_STRING,    title,
			  EZ_FILL_MODE,       EZ_FILL_BOTH,
			  EZ_IPADY,           10,
			  EZ_GRID_CONSTRAINS, EZ_COLUMN, 0, 100, 100, 0,
			  EZ_GRID_CONSTRAINS, EZ_COLUMN, 1, 100, 100, 0,
			  EZ_CLIENT_PTR_DATA,    folder,
			  NULL);
  label = EZ_CreateWidget(EZ_WIDGET_LABEL,       frame,
			  EZ_TEXT_LINE_LENGTH,   60,
			  EZ_LABEL_STRING,       instr,
			  EZ_GRID_CELL_GEOMETRY, 0, 0, 2, 1,
			  EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
			  EZ_LABEL_POSITION,     EZ_CENTER,
			  NULL);
  entry = EZ_CreateWidget(EZ_WIDGET_ENTRY,       frame,
			  EZ_TEXT_LINE_LENGTH,   24,
			  EZ_FONT_ID,            ezfmFontId[ITEM_MEDIUM_FONT],
			  EZ_GRID_CELL_GEOMETRY, 0, 1, 2, 1,
			  EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,	
			  EZ_CLIENT_PTR_DATA,    frame,
			  NULL);
  EZ_AddWidgetCallBack(entry, EZ_CALLBACK, entryCanonicalString, NULL, -1);
  EZ_AddWidgetCallBack(entry, EZ_CALLBACK, gotoEntryCallback, entry, 0);
  if(pathname) EZ_SetEntryString(entry, pathname);
  EZ_WidgetAddDnDDataDecoder(entry, ezfmFileNameAtom, 0, 
			     entryDecodeFileName, NULL,  NULL, NULL);
  
  btn =  EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, frame,
			 EZ_LABEL_STRING,         "Open",
			 EZ_GRID_CELL_GEOMETRY, 0, 2, 1, 1,
			 EZ_CALLBACK,             gotoEntryCallback, entry,
			 NULL);
  
  cancel =  EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, frame,
			    EZ_LABEL_STRING,         "Cancel",
			    EZ_GRID_CELL_GEOMETRY,   1, 2, 1, 1,
			    EZ_CALLBACK,             gotoCancelCallback, frame,
			    NULL);

  EZ_DisplayWidgetUnderPointer(btn, -10,-10);
  EZ_SetFocusTo(entry);
}

void gotoHome(widget, data)
     EZ_Widget *widget; void *data;
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      char *home = getenv("HOME");
      if(home)
	{
	  Folder    *folder = tp->activeFolder;
	  if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
	  OpenFolder(home, folder, 1, 0);	  
	}
    }
}
/*****************************************************************************
 *
 * Find files 
 */
typedef struct {
  EZ_Widget  *frame;
  EZ_Widget  *pentry, *dentry;
  int        which;
  Folder     *folder;
} findRec;
  
static void findDestroyCb(frame, data)
     EZ_Widget *frame; void *data;
{
  findRec *rec = (findRec *)data;
  if(data) EZ_Free(rec);
}

static void doFindFiles(widget, data)
     EZ_Widget *widget; void *data;
{
  findRec *rec = (findRec *)data;
  if(rec)
    {
      EZ_Widget *pentry = rec->pentry;
      EZ_Widget *dentry = rec->dentry;
      EZ_Widget *frame = rec->frame;
      Folder    *folder = rec->folder;
      char      pattern[1024], *ptn, *dir;
      ptn = EZ_GetEntryString(pentry);
      dir = EZ_GetEntryString(dentry);
      if(ptn[0] == '/' || dir[0] != '/')
	{
	  strcpy(pattern, ptn);
	}
      else
	{
	  char  *p, *q;
	  int len=strlen(ptn), done = 0;
	  p = dir; q = pattern;
	  while(!done)
	    {
	      while(*p && *p != ' ') *q++ = *p++;
	      if(q[-1] != '/') *q++ = '/';
	      strcpy(q, ptn); q += len;
	      if(*p == 0)
		{
		  *q++ = 0;
		  done = 1;
		}
	      else 
		{
		  *q++ = ' ';
		  while( *p && *p == ' ') p++;
		  if(*p == 0) done = 1;
		}
	    }
	  *q = 0;
	}
      /* now do globbing */
      {
	if(rec->which == 0 || ! folderExists(folder)) folder = NULL;
	OpenFolder(pattern, folder,1, 0);
      }
      EZ_DestroyWidget(frame);
    }
}

static void doFindFilesA(widget, data)
     EZ_Widget *widget; void *data;
{
  findRec *rec = (findRec *)data;
  if(rec)
    {
      rec->which = EZ_GetWidgetIntData(widget);
      doFindFiles(NULL, data);
    }
}


static void findFiles(widget, data)
     EZ_Widget *widget; void *data;
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      EZ_Widget *frame, *ptnentry, *direntry, *label, *btn1, *btn2, *cancel,*bframe;
      char      *pathname, path[1024];
      FileInfo  *dinfo;
      Folder    *folder = tp->activeFolder;
      findRec   *rec = (findRec *)EZ_Malloc(sizeof(findRec));

      if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
      dinfo = folder->finfo;
      pathname = dinfo->pathname;
      if(dinfo->glob)
	{
	  char *p ;
	  strcpy(path, pathname);
	  p = strrchr(path, '/');
	  if(p) *p = 0;
	  if(path[0] == 0) { path[0] = '/'; path[1] = 0;}
	  pathname = path;
	}
      
      frame = EZ_CreateWidget(EZ_WIDGET_FRAME,    NULL,
			      EZ_TRANSIENT,       True,
			      EZ_FONT_ID,         ezfmFontId[LABEL_LARGE_FONT],
			      EZ_LABEL_STRING,    "Find Files",
			      EZ_FILL_MODE,       EZ_FILL_BOTH,
			      EZ_IPADY,           10,
			      EZ_GRID_CONSTRAINS, EZ_COLUMN, 0, 100, 100, 0,
			      EZ_GRID_CONSTRAINS, EZ_COLUMN, 1, 100, 100, 0,
			      EZ_DESTROY_CALLBACK, findDestroyCb, rec,
			      NULL);

      label = EZ_CreateWidget(EZ_WIDGET_LABEL,       frame,
			      EZ_LABEL_STRING,       "Name/Pattern(s)",
			      EZ_GRID_CELL_GEOMETRY, 0, 1, 1, 1,
			      EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
			      EZ_LABEL_POSITION,     EZ_CENTER,
			      NULL);
            
      ptnentry = EZ_CreateWidget(EZ_WIDGET_ENTRY,       frame,
				 EZ_TEXT_LINE_LENGTH,   24,
				 EZ_FONT_ID,            ezfmFontId[ITEM_MEDIUM_FONT],
				 EZ_GRID_CELL_GEOMETRY, 1, 1, 2, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,	
				 EZ_CALLBACK,           doFindFiles, rec,
				 NULL);

      label = EZ_CreateWidget(EZ_WIDGET_LABEL,       frame,
			      EZ_LABEL_STRING,       "search path(s):",
			      EZ_GRID_CELL_GEOMETRY, 0, 2, 1, 1,
			      EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
			      EZ_LABEL_POSITION,     EZ_CENTER,
			      NULL);
      
      direntry = EZ_CreateWidget(EZ_WIDGET_ENTRY,       frame,
				 EZ_TEXT_LINE_LENGTH,   24,
				 EZ_FONT_ID,            ezfmFontId[ITEM_MEDIUM_FONT],
				 EZ_GRID_CELL_GEOMETRY, 1, 2, 2, 1,
				 EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
				 EZ_CALLBACK,           doFindFiles, rec,
				 NULL);
      EZ_SetEntryString(direntry, pathname);
      EZ_EntryEditBeginningOfInput(direntry);
      EZ_WidgetAddDnDDataDecoder(direntry, ezfmFileNameAtom, 0, 
				 entryDecodeFileName, NULL,  NULL, NULL);
      
      bframe = EZ_CreateWidget(EZ_WIDGET_FRAME,       frame,
			       EZ_LABEL_STRING,       " ",
			       EZ_GRID_CELL_GEOMETRY, 0, 3, 2, 1,
			       EZ_GRID_CELL_PLACEMENT,EZ_FILL_BOTH, EZ_LEFT,
			       EZ_FILL_MODE,          EZ_FILL_HORIZONTALLY,
			       EZ_IPADX,              20,
			       EZ_HEIGHT,             0,
			       NULL);
      
      btn1 =  EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, bframe,
			      EZ_LABEL_STRING,         "Open new",
			      EZ_CLIENT_INT_DATA,      0,
			      EZ_CALLBACK,             doFindFilesA, rec,
			      NULL);

      btn2 =  EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, bframe,
			     EZ_LABEL_STRING,         "Open in place",
			     EZ_CLIENT_INT_DATA,      1,
			     EZ_CALLBACK,             doFindFilesA, rec,
			     NULL);
  
      cancel =  EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, bframe,
				EZ_LABEL_STRING,         "Cancel",
				EZ_CALLBACK,             gotoCancelCallback, frame,
				NULL);

      rec->frame =  frame;
      rec->pentry = ptnentry;
      rec->dentry = direntry;
      rec->which = 0;
      rec->folder = folder;

      EZ_DisplayWidgetUnderPointer(btn2, -10,-10);
      EZ_SetFocusTo(ptnentry);
    }
}

/******************************************************************************/
static void closeFolder(widget, data)
     EZ_Widget *widget; void *data;
{
  Toplevel *tp = (Toplevel *)data;
  if(tp)
    {
      int cnt = tp->folder[1] == NULL? 1 : 2;
      if(countNFolders() == cnt) exitEzfm(NULL, NULL);
      else EZ_DestroyWidget(tp->toplevel);  
    }
}
/******************************************************************************/
static int entryDecodeFileName(obj, data, msg, len)
     void *obj; void *data; char *msg; int len;
{
  if(len > PATHNAME_OFFSET)
    {
      EZ_Widget *entry = (EZ_Widget *)obj;
      char *path = msg+PATHNAME_OFFSET;
      EZ_SetEntryString(entry, path);
      return(EZ_DND_SUCCESS);
    }
  return(EZ_DND_FAILURE);
}
/******************************************************************************/
static void updateFileMenu(menu, data)
     EZ_Widget *menu; void *data;
{
  EZ_Widget *lab, *clone;
  Toplevel *tp = (Toplevel *)data;
  FileInfo  *dinfo;
  int i;
  EZ_UnknownDataType dd;
  EZ_Widget *newF, *newD;
  Folder    *folder = tp->activeFolder;
  
  if(!folder || folder !=  tp->folder[1]) folder = tp->folder[0];
  dinfo = folder->finfo;
  EZ_GetWidgetUnknownData(menu, NEW_FOLDER_ITEM, &dd);
  newD = (EZ_Widget *)dd.p;
  EZ_GetWidgetUnknownData(menu, NEW_FILE_ITEM, &dd);
  newF = (EZ_Widget *)dd.p;
  if(dinfo->glob)
    {
      EZ_DisableWidget(newD);
      EZ_DisableWidget(newF);
    }
  else
    {
      EZ_EnableWidget(newD);
      EZ_EnableWidget(newF);
    }
}
/******************************************************************************/

#undef _MBTN_FILE_C_
