/***********************************************************************/
/*                                                                     */
/* Project      : GRAV                                                 */
/* Current Rel. : 3.1                                                  */
/* Creator      : Michael Knigge                                       */
/* Creation Date: 01/21/95                                             */
/* Description  : Functions needed for reading and sorting directories */
/*                                                                     */
/* Functions    : grav_check_filename()                                */
/*                grav_read_directory()                                */
/*                grav_show_directory()                                */
/*                grav_change_directory()                              */
/*                grav_sort_directory()                                */
/*                                                                     */
/***********************************************************************/

#define SUBPROG

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <ncurses.h>
#include "defines.h"
#include "directory.h"
#include "error.h"


int grav_check_filename(char *filename)
{
   struct stat buffer;
   
   /*
    * if stat() returns -1, an error occured and we
    * suppose that the file/directory doen't exist
    */

   if ((stat(filename,&buffer)) == -1)
      return(IS_NOT_FOUND);

   /*
    * check if the given argument is a file or a directory
    */

   if ((buffer.st_mode & 0x7000) == 0x4000)
       return(IS_DIRECTORY);
   else
       return(IS_FILE);
}

int grav_read_directory(char *path, int *files, DIRTAB dirtab[])
{
   DIR           *dir;
   struct dirent *dir_entry;
   char           current_dir[256];
   int            local;
   int            ft;
   int            flag;
   int            type;

   /*
    * get current directory, open the directory given in "path" 
    * and return a pointer
    */
   
   getcwd(current_dir, 255);
   dir   = opendir(path);
   local = 0;
   
   /*
    * call readdir() until all entries in directory were returned
    */
   
   while((dir_entry=readdir(dir)) != NULL)
   {
      /*
       * add always if entry is a directory
       */
      
      if ((type=grav_check_filename(dir_entry->d_name)) == IS_DIRECTORY)
         flag = TRUE;
      else
         flag = FALSE;
      
      /*
       * never add "." directory
       */
       
       if (strcmp(dir_entry->d_name, ".") == 0)
          flag = FALSE;

      /*
       * don't add ".." when in root-directory
       */
       
      if ( strcmp(current_dir, "/")  == 0    && 
           strcmp(dir_entry->d_name, "..") == 0 )
         flag = FALSE;
      
      /*
       * check if the current file is a graphic that can be 
       * displayed. If not, don't add the entry to the structure.
       * if we got more than MAX_DIRTAB entries, we just return TRUE.
       */
          
      if (type == IS_FILE)      
      {
         if (grav_guess_filetype(dir_entry->d_name, &ft) != FALSE)
         {
            flag = TRUE;
            if (local == MAX_DIRTAB)
               return(TRUE);
         }
      }

      if (flag == TRUE)
      {
         strcpy(dirtab[local].filename, dir_entry->d_name);
         dirtab[local].filetype = type;
         dirtab[local].tagged   = FALSE;
         dirtab[local].gfx_type = ft;
         local++;
         *files = local;
      }
   }
   closedir(dir);
   
   /*
    * and at last, sort the directory
    */
   
   qsort (&(dirtab[1]),
          local - 1,
          sizeof(DIRTAB),
          (void *)grav_sort_directory);
                                     

   return(TRUE);
}

int grav_show_directory(int use_color, int page, int max_files, DIRTAB dirtab[])
{
   int  local;
   int  count;
   int  line;
   int  pos;
   char temp[21];
   char current_dir[61];

   
   /*
    * first we have to draw the file-window
    */
    
   if (use_color)
   {
      grav_draw_box(16,47,8,5,BLACK_ON_CYAN);
      attron(COLOR_PAIR(BLACK_ON_CYAN));
   }
   else
   {
      grav_draw_box(16,47,8,5,COLOR_REVERSE);
      attron(A_REVERSE);   
   }

   /*
    * than we will draw the line in the middle of this window
    */

#ifndef BUG_NCURSES       
   for(local=8;local<22;local++)
      mvaddch(local, 27, ACS_VLINE);
#endif

   line  = 1;
   pos   = POS_LEFT;
   local = page * MAX_LINES * 2;
   
   for (count=local;count < local + MAX_LINES * 2; count++)
   {

      /*
       * if we are going to display more entries than allowed,
       * just jump out!
       */
       
      if (count >= max_files)
         break;
         
      /*
       * if the current filen in dirtab is a directory,
       * we will put this filename in "<" and ">". otherwise
       * we will use the unmodified filename
       */
       
      if (dirtab[count].filetype == IS_DIRECTORY)
      {
         strcpy(temp,"<");
         strncat(temp,dirtab[count].filename,18);
         strcat(temp,">");
      }
      else
      {
         strncpy(temp,dirtab[count].filename,20);
      }
      
      temp[20] = 0;   
      
      if (dirtab[count].tagged == FALSE)
      {
         if(use_color)
            attron(COLOR_PAIR(BLACK_ON_CYAN));
         else
            attron(A_REVERSE);
            
         mvaddstr(line+7, pos, temp);
      }
      else
      {
         attron(A_BOLD);
         
         if (use_color)
            attron(COLOR_PAIR(YELLOW_ON_CYAN));
         else
            attron(A_REVERSE);
            
         mvaddstr(line+7, pos, temp);
         attroff(A_BOLD);
      }
      
      if (pos == POS_RIGHT)
      {
         pos = POS_LEFT;
         line ++;
      }
      else
      {
         pos = POS_RIGHT;
      }    
   }
   
   if (use_color)
      attron(COLOR_PAIR(WHITE_ON_BLUE));
   else
      attroff(A_REVERSE);

   getcwd(current_dir,60);
   strncat(current_dir,BLANK60,60-strlen(current_dir));
   mvaddstr(5, 18, current_dir);                     

   refresh();

   return(TRUE);                     
}

int grav_change_directory(int *error, int index, DIRTAB dirtab[])
{
   *error = GRAV_NO_ERROR;
   
   if (chdir(dirtab[index].filename) == -1)
   {
      *error = GRAV_ERROR_CHDIR;
      return(FALSE);
   }
   
   return(TRUE);
}

int grav_sort_directory(void *ptr1, void *ptr2)
{
   DIRTAB *tab1;
   DIRTAB *tab2;
   char   buffer1[256];
   char   buffer2[256];
   
   tab1 = (DIRTAB *)ptr1;
   tab2 = (DIRTAB *)ptr2;


   if (tab1->filetype == IS_DIRECTORY &&
       tab2->filetype == IS_DIRECTORY)
      return(strcmp(tab1->filename,tab2->filename));

   if (tab1->filetype == IS_FILE &&
       tab2->filetype == IS_FILE)
      return(strcmp(tab1->filename,tab2->filename));

   if (tab1->filetype == IS_FILE &&
       tab2->filetype == IS_DIRECTORY)
      return(1);
      
   if (tab1->filetype == IS_DIRECTORY &&
       tab2->filetype == IS_FILE)
      return(-1);      
}
