// My File Manager (MFM).
//
// Copyright 2005-2006 by Stefano Gatti.
//
// This program 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
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
//=====================================================================

#include <locale.h>
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>

#include <FL/Fl_File_Chooser.H>

#include "mfmfind_ui.hxx"
#include "mfm_confirm_ui.hxx"

// Added for Open with... function:
#include "mfm_input_ui.hxx"

#define MAXSIZE 1000

class_mfmfind *ptr_mfmfind;

char *line = NULL;
	
size_t dim_line = 0;



/**************************************************************************
*
* Function: idle_function
*
* function to call during idle
*
****************************************************************************/

void idle_function(void *) {

  if (getline(&line, &dim_line, ptr_mfmfind->stream)>0) {   
  
    line[strlen(line)-1] = 0;

    ptr_mfmfind->mfmfind_browser->add(line);
		
    if (ptr_mfmfind->mfmfind_browser->size() > MAXSIZE)
		
      ptr_mfmfind->mfmfind_browser->remove(1);		
		
		ptr_mfmfind->mfmfind_browser->bottomline(ptr_mfmfind->mfmfind_browser->size());
		
  }			
		
  else  {							
	      
    pclose(ptr_mfmfind->stream);
		
		Fl::remove_idle(idle_function);
		
		Fl::redraw();
						
  }		
	
}


/**************************************************************************
* Metodi di class_mfmfind
****************************************************************************/

/**************************************************************************
* Costruttore
****************************************************************************/

class_mfmfind::class_mfmfind(char *path) : class_mfmfind_fluid() {

  mfmfind_path_input->value(path);
  mfmfind_file_time_input->value("0");
  mfmfind_file_size_input->value("0");

  search_path = NULL;

  mfmfind->show();

  ptr_mfmfind = this;

} // class_mfmfind


/**************************************************************************
*
* Function: convert_names
*
* Convert table's string in real filenames
*
* Add \ character before each space and others special characters 
*
****************************************************************************/

char* class_mfmfind::convert_names (char *string) {

  int lun, count;
	
	char* mod_string;
	
  lun = strlen(string);	
  
  if (mfmfind_content_line_button->value())
  
    for (int j=0; j<lun; j++)
					
      if (string[j] == ':') {
						
        lun = j;		
					
	      break;
					
      } 
  	
  count = lun;
				
  for (int j=0; j<lun; j++) {
  			
    if (string[j] < 42)
				
	    count++;
      
  }						
  
	mod_string = (char *) malloc(count+1);
			
	mod_string[count--] = 0;

	for (int j=lun-1; j>=0; j--) {

    mod_string[count--] = string[j];
				
    if (string[j] < 42)
				
      mod_string[count--] = '\\' ;
      
  }	
	
	return mod_string;

} // convert_names


/**************************************************************************
* 
* mfmfind_selected
*
* Return selected files list 
*
****************************************************************************/

char* class_mfmfind::mfmfind_selected() {

  char *retstr,
       *tmpstr,
       *fl1str,
       *fl2str = NULL;       

  retstr = (char *) malloc(1);
    
  retstr[0] = 0;  

  for (int i = 1; i <= mfmfind_browser->size(); i++) 

    if (mfmfind_browser->selected(i)) {
      
      fl1str = convert_names((char *) mfmfind_browser->text(i));

      if (fl2str == NULL || strcmp(fl1str, fl2str) != 0) { 

        if (fl2str != NULL)
          
          free(fl2str);

        asprintf(&fl2str, "%s", fl1str);  

        tmpstr = retstr;
        
        if (fl1str[0] == '.' && fl1str[1] == '/')
        
          asprintf(&retstr, "%s %s/%s", tmpstr, search_path, fl1str + 2);
          
        else  

          asprintf(&retstr, "%s %s", tmpstr, fl1str);    

        free(tmpstr);               

      }                            

      free(fl1str);                  

    }       

    if (fl2str != NULL)
          
      free(fl2str);
  
    return retstr; 

} // mfmfind_selected


/**************************************************************************
* 
* mfmfind_delete
*
* Delete selected files from list 
*
****************************************************************************/

void class_mfmfind::mfmfind_delete() {

  char *fl1str = NULL,
       *fl2str = NULL;       

  for (int i = 1; i <= mfmfind_browser->size(); i++) 

    if (mfmfind_browser->selected(i)) {
    
      if (fl1str != NULL)
          
        free(fl1str);      
      
      fl1str = convert_names((char *) mfmfind_browser->text(i));
      
      for (int j = 1; j <= mfmfind_browser->size(); j++) {      
      
        if (fl2str != NULL)
          
          free(fl2str);      
      
        fl2str = convert_names((char *) mfmfind_browser->text(j));
        
        if (strcmp(fl1str, fl2str) == 0)

          mfmfind_browser->select(j);
        
      }             
      
    }                   
      
  for (int i = mfmfind_browser->size(); i > 0; i--) 

    if (mfmfind_browser->selected(i)) 

      mfmfind_browser->remove(i);
    
  if (fl1str != NULL)
          
    free(fl1str);    

  if (fl2str != NULL)
          
    free(fl2str);    
      
} // mfmfind_delete


/**************************************************************************
* Callback dei widget dell'interfaccia
****************************************************************************/


void class_mfmfind::mfmfind_path_callback() {
	
	mfmfind_path_input->value(fl_dir_chooser("SELECT DIRECTORY...", NULL));

} // mfmfind_path_callback


// OK button changed to Search in MFMR Find GUI:
void class_mfmfind::mfmfind_ok_callback() {

  char *command,
	     *file_name,
			 *recursive,
			 *content_case,
			 *content_line,
			 *content,
       *size_filter,

// Added mfmfind_show_choicebox:
       *show,

       *time_filter;

			 
  mfmfind_browser->clear();					 			 
  
  if (search_path != NULL) {
  
    free(search_path);
    
    search_path = NULL;
    
  }  
    
  chdir(mfmfind_path_input->value());  
  
  search_path = get_current_dir_name();

// Added mfmfind_show_choicebox:
  if (mfmfind_show_choicebox->value() == 0)

    asprintf(&show, " ");

  else if (mfmfind_show_choicebox->value() == 1)

    asprintf(&show, "-type f");
 
  else if (mfmfind_show_choicebox->value() == 2)
  
    asprintf(&show, "-type d");

  if (mfmfind_file_time->value() == 0)

    asprintf(&time_filter, " ");

  else if (mfmfind_file_time->value() == 1)

    asprintf(&time_filter, "-mmin +%s", mfmfind_file_time_input->value());
 
  else if (mfmfind_file_time->value() == 2)
  
    asprintf(&time_filter, "-mtime +%s", mfmfind_file_time_input->value());

  else if (mfmfind_file_time->value() == 3)
  
    asprintf(&time_filter, "-mmin -%s", mfmfind_file_time_input->value());
 
  else if (mfmfind_file_time->value() == 4)
  
    asprintf(&time_filter, "-mtime -%s", mfmfind_file_time_input->value());
  
  if (mfmfind_file_size->value() == 0)
  
    asprintf(&size_filter, " ");
    
  else if (mfmfind_file_size->value() == 1)
  
    asprintf(&size_filter, "-size +%sb", mfmfind_file_size_input->value());
    
  else if (mfmfind_file_size->value() == 2)
  
    asprintf(&size_filter, "-size +%sk", mfmfind_file_size_input->value());

  else if (mfmfind_file_size->value() == 5)
  
    asprintf(&size_filter, "-size -%sb", mfmfind_file_size_input->value());
    
  else if (mfmfind_file_size->value() == 6)
  
    asprintf(&size_filter, "-size -%sk", mfmfind_file_size_input->value());
    
  else  {
  
    int value;
    
    sscanf(mfmfind_file_size_input->value(), "%i", &value);
    
    value = value * 1024;
    
    if (mfmfind_file_size->value() == 4 || mfmfind_file_size->value() == 8)
  
      value = value * 1024;
      
    if (mfmfind_file_size->value() == 3 || mfmfind_file_size->value() == 4)
    
      asprintf(&size_filter, "-size +%ik", value);
      
    else  
    
      asprintf(&size_filter, "-size -%ik", value);

  }

  if (mfmfind_file_recursive_button->value()){

    recursive= (char *) malloc(1);

    recursive[0] = 0;

  }
		
	else
	
	  asprintf(&recursive, "-maxdepth 1");

	if (strlen(mfmfind_pattern->value()) == 0) {

    file_name = (char *) malloc(1);

    file_name[0] = 0;

  }

  else if (mfmfind_file_case_button->value())

	  asprintf(&file_name, "-name '%s'", mfmfind_pattern->value());

  else

	  asprintf(&file_name, "-iname '%s'", mfmfind_pattern->value());

	if (strlen(mfmfind_content->value()) == 0) {

    content = (char *) malloc(1);

    content[0] = 0;

  }

	else {

	  if (mfmfind_content_case_button->value()) {

      content_case = (char *) malloc(1);

      content_case[0] = 0;

    }

		else

		  asprintf(&content_case, "-i");

	  if (mfmfind_content_line_button->value())

		  asprintf(&content_line, "-nH");

		else

		  asprintf(&content_line, "-l");

	  asprintf(&content, " -exec grep %s %s \"%s\" \\{\\} \\;", content_case, content_line, mfmfind_content->value());

		free(content_case);
		free(content_line);

  }


// Added mfmfind_show_choicebox:
//       asprintf(&command, "find %s %s %s %s %s %s 2>&1", mfmfind_path_input->value(), recursive, file_name, content, time_filter, size_filter);
         asprintf(&command, "find %s %s %s %s %s %s %s 2>&1", mfmfind_path_input->value(), recursive, file_name, content, time_filter, size_filter, show);

  free(file_name);

  free(recursive);

  free(content);

  free(time_filter);

  free(size_filter);

// Added mfmfind_show_choicebox:
  free (show);

  stream = popen(command,"r");

  free(command);

  Fl::add_idle(idle_function); 

} // mfmfind_ok_callback


void class_mfmfind::mfmfind_exit_callback() {

  delete this->mfmfind;
  delete this;

} // mfmfind_exit_callback


void class_mfmfind::mfmfind_help_callback() {

  system("mfmhelp /usr/local/share/doc/mfm.html#find &");

} // mfmfind_help_callback


void class_mfmfind::mfmfind_copy_callback() {

  char *list_selected,
       *path,
       *command;

  list_selected = mfmfind_selected();
  
  path =  fl_dir_chooser("Copy to...",".");
  
  if (path != NULL) { 
  
    asprintf(&command, "mfmexec 'COPYING FILES...' '.' 'cp -r %s %s 2>&1' &", list_selected, path);  

    system(command);  
    
    free(command);    

  }      
    
  free(list_selected);  

} // mfmfind_copy_callback


void class_mfmfind::mfmfind_move_callback() {

  char *list_selected,
       *path,
       *command;

  list_selected = mfmfind_selected();
  
  path =  fl_dir_chooser("Move to...",".");
  
  if (path != NULL) { 
  
    asprintf(&command, "mfmexec 'MOVING FILES...' '.' 'mv %s %s 2>&1' &", list_selected, path);  

    system(command);  
    
    free(command);    
    
    mfmfind_delete();    

  }      
    
  free(list_selected);  

} // mfmfind_move_callback


void class_mfmfind::mfmfind_delete_callback() {

    if (get_confirm("DELETING ITEMS...", "OK to permanently delete selected item(s) ?")) {

      char *list_selected,
           *command;

    list_selected = mfmfind_selected();
  
    asprintf(&command, "mfmexec 'DELETE FILES' '.' 'rm -Rf %s 2>&1' &", list_selected);  

    system(command);  

    mfmfind_delete();

    free(list_selected);
  
    free(command);  

  }

} // mfmfind_delete_callback


void class_mfmfind::mfmfind_editor_callback() {

  char *list_selected,
       *command,
       *cfg_file,
       *EDITOR,
       *stringa = NULL,
       code[21];
       
  size_t dim, 
         start = 0;

// Compile warning, int num set but not used:
// int num;

  FILE *stream;       

  list_selected = mfmfind_selected();

  asprintf(&EDITOR, "editor");

  asprintf(&cfg_file, "%s/.mfm/mfm.cfg", getenv("HOME"));

  if ((stream = fopen (cfg_file,"r"))!=NULL) { 

    while (getline(&stringa, &dim, stream)>0) {

// Compile warning, int num set but not used:
//    num = sscanf(stringa, "%20s", code);

      if (strcmp(code, "editor") == 0) {

        free(EDITOR);

        for (start=strlen(code) + 1; start<strlen(stringa); start++)

          if (stringa[start] != ' ') break;

        for (size_t i=start+1; i<=strlen(stringa); i++)

          if (stringa[i] <= (char) 32) {

            stringa[i] = (char) 0;

            break;

          }

        asprintf(&EDITOR, "%s", stringa + start);

      }
      
    }        

    fclose(stream);

    free(stringa);
      
  }  

  free(cfg_file);

  asprintf(&command, "%s%s &", EDITOR, list_selected);

  system(command);    

  free(list_selected);
  
  free(command);  

} // mfmfind_editor_callback


void class_mfmfind::mfmfind_browse_selected_callback() {

  char *list_selected,
       *command;
       
  list_selected = mfmfind_selected();

// Changed to new mfmr executable, '-s='Find results' %s' crashed Find GUI:
//asprintf(&command, "mfm -s='Find results' %s &", list_selected);
  asprintf(&command, "mfmr %s &", list_selected);

  system(command);  

  free(list_selected);
  
  free(command);  

} // mfmfind_browse_selected_callback()


// Create MFMR Find GUI Open with... option:
void class_mfmfind::mfmfind_open_with_callback() {

    char *list_selected,
         *command;

    list_selected = mfmfind_selected();

          asprintf(&command, "%s %s &", mfmfind_open_with_program->value(), list_selected);

          system(command);

          free(list_selected);

          free(command);

} // mfmfind_open_with_callback()


void class_mfmfind::mfmfind_browse_all_callback() {

  mfmfind_select_callback();

  mfmfind_browse_selected_callback();

} // mfmfind_browse_all_callback()


void class_mfmfind::mfmfind_select_callback() {

  for (int i = 1; i <= mfmfind_browser->size(); i++) 
  
    mfmfind_browser->select(i);

} // mfmfind_select_callback
