
#include "includes.h"
#include "installergui_data.h"

#include <string.h>

/********************************************************************
 *
 *  DESCRIPTION
 *
 */

/********************************************************************
 *
 *  STATIC
 *
 */

static BOOL walkdir_function(struct FileInfoBlock *, APTR);

static struct Node * __saveds find_node(struct List *, char *);

static APTR list_construct_hook_fun(register __a0 struct Hook *, register __a1 struct FileInfoBlock *);
static void list_destruct_hook_fun(register __a1 struct FileInfoBlock *);
static long list_display_hook_fun(register __a1 struct FileInfoBlock *, register __a2 char **);
static long list_compare_hook_fun(register __a1 struct FileInfoBlock *, register __a2 struct FileInfoBlock *);

static const struct Hook list_construct_hook = { { NULL, NULL }, (VOID *) list_construct_hook_fun, NULL, NULL };
static const struct Hook list_destruct_hook = { { NULL, NULL }, (VOID *) list_destruct_hook_fun, NULL, NULL };
static const struct Hook list_display_hook = { { NULL, NULL }, (VOID *) list_display_hook_fun, NULL, NULL };
static const struct Hook list_compare_hook = { { NULL, NULL }, (VOID *) list_compare_hook_fun, NULL, NULL };

/********************************************************************
 *
 *  EXTERN
 *
 */

/********************************************************************
 *
 *  PUBLIC
 *
 */

/********************************************************************
 *
 *  CODE
 *
 */

APTR __asm igui_CreateFileList(register __a0 APTR application,
                               register __a1 char *dir,
                               register __a2 struct FunctionEnvironment *localenv)
{
  #ifdef DEBUG
  DEBUG_MAKRO
  #endif

  {
    APTR dirlist;
    struct Application *app = (struct Application *) application;

    // set the localenv to the hook structure, such that the "list_construct_hook" has
    // access to the localenv
    list_construct_hook.h_Data = localenv;

    // create the list object (we cannot use a dirlist, because the list
    // must have special attributes (see PATTERN/FILES/INFOS/CHOICES parameters)
    // which cannot be satisfied by the simple mui dirlist
    app->app_DirlistList = dirlist = ListviewObject,
                                       MUIA_Background, MUII_ListBack,
                                       MUIA_Frame, MUIV_Frame_InputList,
                                       MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_Default,
                                       MUIA_Listview_List, ListObject,
                                         MUIA_List_ConstructHook, &list_construct_hook,
                                         MUIA_List_DestructHook, &list_destruct_hook,
                                         MUIA_List_DisplayHook, &list_display_hook,
                                         MUIA_List_CompareHook, &list_compare_hook,
                                       End,
                                     End;

    if (dirlist)
    {
      // walk through the complete dir and add the entries to the list
      if (sav_DirWalk((char *) localenv->fe_Source, walkdir_function, dirlist))
      {
        // for walking through the list we have to set the "walk-marker"
        app->app_DirlistWalker = MUIV_List_NextSelected_Start;

        // select all the files
        DoMethod(dirlist, MUIM_List_Select, MUIV_List_Select_All, MUIV_List_Select_On, NULL);
      }
      else { /* should not happen */ }
    }

    return (dirlist);
  }
}

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

// give the fib to the list
static BOOL __saveds walkdir_function(struct FileInfoBlock *fib, APTR dirlist)
{
  DoMethod(dirlist, MUIM_List_InsertSingle, fib, MUIV_List_Insert_Sorted);
  return(TRUE);
}

static APTR __asm __saveds list_construct_hook_fun(register __a0 struct Hook *hook, register __a1 struct FileInfoBlock *fib)
{
  APTR fibcpy = NULL;
  BOOL accept = TRUE;

  // the localenv of the function
  struct FunctionEnvironment *localenv = hook->h_Data;

  //
  if (localenv->fe_All) { }

  //
  else if (!sav_IsListEmpty(&(localenv->fe_Choices)))
  {
    accept = (long) find_node((struct List *) &(localenv->fe_Choices), (char *) &(fib->fib_FileName));
  }

  //
  else if (localenv->fe_Pattern)
  {
    accept = sav_MatchPatternNoCase((STRPTR) localenv->fe_Pattern, (char *) &(fib->fib_FileName));
    if (accept == -1) { accept = 0; }
  }

  // if not filtered yet, we have to gon on with checking
  if (localenv->fe_Fonts && accept) { accept = !sav_FontFile((char *) &(fib->fib_FileName)); }
  if (localenv->fe_Infos && accept) { accept = !sav_InfoFile((char *) &(fib->fib_FileName)); }
  if (localenv->fe_Files && accept) { if (fib->fib_EntryType != ST_FILE) { accept = FALSE; } }

  // if we have to accept the file, clone the fib and put this
  // fib to the mui list
  if (accept && (fibcpy = sav_AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
  {
    CopyMem(fib, fibcpy, sizeof(struct FileInfoBlock));
  }

  //
  return(fibcpy);
}

static void __asm __saveds list_destruct_hook_fun(register __a1 struct FileInfoBlock *fib)
{
  sav_FreeVec(fib);
}

static long list_display_hook_fun(register __a1 struct FileInfoBlock *fib, register __a2 char **array)
{
  *array = (char *) &(fib->fib_FileName);
  return(0);
}

static long __asm list_compare_hook_fun(register __a1 struct FileInfoBlock *fib1, register __a2 struct FileInfoBlock *fib2)
{
  return(stricmp((char *) &(fib1->fib_FileName), (char *) &(fib2->fib_FileName)));
}

static struct __asm __saveds Node * __saveds find_node(struct List *list, char *name)
{
  struct Node *node = sav_GetHead(list);

  while(node)
  {
    if (!Stricmp(name, node -> ln_Name)) { return(node); }
    node = sav_GetSucc(node);
  }

  //
  return(NULL);
}
