
//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library 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
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  GCUI: Golded+ Character-oriented User Interface.
//  wpickfile() - Allows user to select a file name.
//  ------------------------------------------------------------------

#include <gctype.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <gmemdbg.h>
#include <gfilutil.h>
#include <gwildmat.h>
#include <gwinall.h>
#include <gfilutil.h>
#include <gdirposx.h>
#include <gstrall.h>


//  ------------------------------------------------------------------

static bool path_in_title, case_sensitive;
static IfcpCP open_function = NULL;
static char* cwdp;
static char* tcwdp;
static char* namextp;


//  ------------------------------------------------------------------
//  this function is the compare function for std::sort()

static bool compare(const std::string str1, const std::string str2)
{
    // Sort with directories first
    bool dir1 = !!strchr(str1.c_str(), GOLD_SLASH_CHR);
    bool dir2 = !!strchr(str2.c_str(), GOLD_SLASH_CHR);
    if (dir1 && !dir2) return true;
    if (!dir1 && dir2) return false;

    std::string s1 = dir1 ? str1.substr(0, str1.length()-1) : str1;
    std::string s2 = dir2 ? str2.substr(0, str2.length()-1) : str2;

    int cmp;
    if (case_sensitive)
        cmp = strcmp(s1.c_str(), s2.c_str());
    else
    {
        cmp = stricmp(s1.c_str(), s2.c_str());
        if (cmp == 0)
            cmp = strcmp(s1.c_str(), s2.c_str());
    }

    return (cmp < 0);
}


//  ------------------------------------------------------------------
//  this function displays the title on the pick window border

static void disp_title()
{

    char buf[sizeof(Path)+2];

    if(path_in_title or open_function)
    {
        strcpy(buf, " ");
        PathCopy(buf+1, cwdp);
        strcat(buf, namextp);
        strcat(buf, " ");
    }

    if(path_in_title)
    {
        wtitle(buf, TCENTER, gwin.active->battr);
    }

    if(open_function)
    {
        (*open_function)(buf);
    }
}


//  ------------------------------------------------------------------

bool wpickfile(int srow, int scol, int erow, int ecol, int btype, vattr bordattr, vattr winattr, vattr barattr, bool title, std::string &filespec, IfcpCP open, bool casesens)
{
    Path cwd, dir, namext, tcwd, path, spec;

    cwdp = cwd;
    tcwdp = tcwd;
    namextp = namext;

    // set static variables
    open_function = open;
    path_in_title = title;
    case_sensitive = casesens;

    // save current working directory
    getcwd(tcwd, GMAXPATH);

    // if drive was specified, change to it
    char* q = strxcpy(spec, filespec.c_str(), sizeof(Path));

    // split up input filespec into its current
    // working directory and filename/extension
    char* r = strrchr(q, GOLD_SLASH_CHR);
#if defined(__HAVE_DRIVES__)
    if(r == NULL)
        if(q[1] == ':')
            r = q + 1;
#endif
    if(r == NULL)
    {
        *dir = NUL;
        strcpy(namext, q);
    }
    else
    {
        strins(" ", ++r, 0);
        *r++ = NUL;
        strcpy(dir, q);
        strcpy(namext, r);
    }

    bool finished;
    int picked;

    do
    {
        // if directory was specified, change to it
        if (*dir && gchdir(dir))
        {
            gchdir(tcwdp);
            return false;
        }

        // get current working directory
        getcwd(cwd, GMAXPATH);
        strcpy(dir, cwd);

        // find all directories plus all files matching input filespec in
        // current directory, allocating an array element for each
        picked = -1;
        gposixdir d(dir);
        gstrarray strarr;
        const gdirentry *de;

        if (d.ok)
        {
            while((de = d.nextentry()) != NULL)
            {
                const char* name = NULL;
                if (de->is_directory())
                {
                    if(de->name != ".")
                    {
                        strxmerge(path, sizeof(Path), de->name.c_str(), GOLD_SLASH_STR, NULL);
                        name = path;
                    }
                }
                else if(de->is_file())
                {
                    if(case_sensitive ? gwildmat(de->name.c_str(), namext) : gwildmati(de->name.c_str(), namext))
                        name = de->name.c_str();
                }

                if (name) strarr.push_back(name);
            }
        }

        // sort files in array by swapping their pointers
        std::sort(strarr.begin(), strarr.end(), compare);

        // let user pick file
        if (strarr.size())
        {
            picked = wpickstr(srow, scol, erow, ecol, btype, bordattr, winattr, barattr, strarr, 0, disp_title);
        }

        if (picked == -1 or !strarr.size())
        {
            gchdir(tcwdp);
            return false;
        }

        // see if a directory was selected. if so save
        // directory name, otherwise build whole path name
        const char *slash = strchr(strarr[picked].c_str(), GOLD_SLASH_CHR);
        if (slash)
        {
            finished = false;
            strcpy(dir, strarr[picked].c_str());
            r = strrchr(dir, GOLD_SLASH_CHR);
            if (r) *r = NUL;
        }
        else
        {
            finished = true;
            PathCopy(filespec, cwd);
            filespec += strarr[picked].c_str();
        }

        strarr.clear();
    }
    while(not finished);  // if a directory was selected, go back and do again

    gchdir(tcwd); // change back to current drive and directory
    return true;  // return normally
}


//  ------------------------------------------------------------------

