/////////////////////////////////////////////////////////////////////////////
// Name:        filedlg.cpp
// Purpose:     wxFileDialog
// Author:      David Webster
// Modified by:
// Created:     10/05/99
// RCS-ID:      $Id: FILEDLG.CPP,v 1.8 2002/08/21 04:12:31 DW Exp $
// Copyright:   (c) David Webster
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/utils.h"
    #include "wx/msgdlg.h"
    #include "wx/dialog.h"
    #include "wx/filedlg.h"
    #include "wx/intl.h"
    #include "wx/log.h"
    #include "wx/app.h"
#endif

#define INCL_PM
#include <os2.h>

#include "wx/os2/private.h"

#include <math.h>
#include <stdlib.h>
#include <string.h>

#include "wx/tokenzr.h"

#define wxMAXPATH                    1024
#define wxMAXFILE                    1024
#define wxMAXEXT                        5

#ifndef MAXPATH
# define MAXPATH                      400
#endif

#ifndef MAXDRIVE
# define MAXDRIVE                       3
#endif

#ifndef MAXFILE
# define MAXFILE                        9
#endif

#ifndef MAXEXT
# define MAXEXT                         5
#endif
IMPLEMENT_CLASS(wxFileDialog, wxDialog)

// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------

wxString wxFileSelector(
  const char*                       pzTitle
, const char*                       pzDefaultDir
, const char*                       pzDefaultFileName
, const char*                       pzDefaultExtension
, const char*                       pzFilter
, int                               nFlags
, wxWindow*                         pParent
, int                               nX
, int                               nY
)
{
    wxString                        sFilter("");
    wxString                        sDefaultDirString;
    wxString                        sDefaultFilenameString;

    //
    // If there's a default extension specified but no filter, we create
    // a suitable filter.
    //
    if (pzDefaultExtension && !pzFilter)
        sFilter = wxString("*.") + wxString(pzDefaultExtension);
    else if (pzFilter)
        sFilter = pzFilter;

    if (pzDefaultDir)
        sDefaultDirString = pzDefaultDir;
    else
        sDefaultDirString = "";

    if (pzDefaultFileName)
        sDefaultFilenameString = pzDefaultFileName;
    else
        sDefaultFilenameString = "";

    wxFileDialog                    vFileDialog( pParent
                                                ,pzTitle
                                                ,sDefaultDirString
                                                ,sDefaultFilenameString
                                                ,sFilter
                                                ,nFlags
                                                ,wxPoint(nX, nY)
                                               );

    if (wxStrlen(pzDefaultExtension) != 0)
    {
        int                         nFilterFind = 0;
        int                         nFilterIndex = 0;

        for (unsigned int i = 0; i < sFilter.Len(); i++)
        {
            if (sFilter.GetChar(i) == wxT('|'))
            {
                //
                // Save the start index of the new filter
                unsigned int        uIs = i++;

                //
                // Find the end of the filter
                //
                for(; i < sFilter.Len(); i++)
                {
                    if(sFilter[i] == wxT('|'))
                        break;
                }

                if( i - uIs - 1 > 0 && uIs + 1 < sFilter.Len() )
                {
                    if(sFilter.Mid(uIs + 1, i - uIs - 1).Contains(pzDefaultExtension))
                    {
                        nFilterFind = nFilterIndex;
                        break;
                    }
                }
                nFilterIndex++;
            }
        }
        vFileDialog.SetFilterIndex(nFilterFind);
    }
    if (vFileDialog.ShowModal() == wxID_OK)
    {
        return vFileDialog.GetPath();
    }
    else
        return wxEmptyString;
} // end of wxFileSelector

wxString wxFileSelectorEx (
  const char*                       pzTitle
, const char*                       pzDefaultDir
, const char*                       pzDefaultFileName
, int*                              pnDefaultFilterIndex
, const char*                       pzFilter
, int                               nFlags
, wxWindow*                         pParent
, int                               nX
, int                               nY
)
{
    wxFileDialog                    vFileDialog( pParent
                                                ,pzTitle ? pzTitle : ""
                                                ,pzDefaultDir ? pzDefaultDir : ""
                                                ,pzDefaultFileName ? pzDefaultFileName : ""
                                                ,pzFilter ? pzFilter : ""
                                                ,nFlags
                                                ,wxPoint(nX, nY)
                                               );

    if (vFileDialog.ShowModal() == wxID_OK)
    {
        *pnDefaultFilterIndex = vFileDialog.GetFilterIndex();
        return vFileDialog.GetPath();
    }
    else
        return wxEmptyString;
} // end of wxFileSelectorEx

// ----------------------------------------------------------------------------
// CLASS wxFileDialog
// ----------------------------------------------------------------------------

wxFileDialog::wxFileDialog (
  wxWindow*                         pParent
, const wxString&                   rsMessage
, const wxString&                   rsDefaultDir
, const wxString&                   rsDefaultFileName
, const wxString&                   rsWildCard
, long                              lStyle
, const wxPoint&                    rPos
)
{
    m_sMessage     = rsMessage;
    m_lDialogStyle = lStyle;
    if ((m_lDialogStyle & wxMULTIPLE) && (m_lDialogStyle & wxSAVE))
        m_lDialogStyle &= ~wxMULTIPLE;
    m_pParent      = pParent;
    m_sPath        = "";
    m_sFileName    = rsDefaultFileName;
    m_sDir         = rsDefaultDir;
    m_sWildCard    = rsWildCard;
    m_nFilterIndex = 1;
    m_vPos         = rPos;
} // end of wxFileDialog::wxFileDialog

void wxFileDialog::GetPaths (
  wxArrayString&                    rasPaths
) const
{
    wxString                        sDir(m_sDir);
    size_t                          nCount = m_asFileNames.GetCount();

    rasPaths.Empty();
    if (m_sDir.Last() != _T('\\'))
        sDir += _T('\\');

    for ( size_t n = 0; n < nCount; n++ )
    {
        rasPaths.Add(sDir + m_asFileNames[n]);
    }
} // end of wxFileDialog::GetPaths

int wxFileDialog::ShowModal()
{
    wxString                        sTheFilter;
    wxString                        sFilterBuffer;
    wxChar*                         pzFilterBuffer;
    static wxChar                   zFileNameBuffer[wxMAXPATH];           // the file-name
    HWND                            hWnd = 0;
    wxChar                          zTitleBuffer[wxMAXFILE + 1 + wxMAXEXT];  // the file-name, without path
    wxString                        sDir;
    size_t                          i;
    size_t                          nLen = m_sDir.length();
    int                             nCount = 0;
    FILEDLG                         vFileDlg;
    ULONG                           lFlags = 0L;

    memset(&vFileDlg, '\0', sizeof(FILEDLG));
    if (m_pParent)
        hWnd = (HWND) m_pParent->GetHWND();
    if (!hWnd && wxTheApp->GetTopWindow())
        hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();


    *zFileNameBuffer = wxT('\0');
    *zTitleBuffer    = wxT('\0');

    if (m_lDialogStyle & wxSAVE)
        lFlags = FDS_SAVEAS_DIALOG;
    else
        lFlags = FDS_OPEN_DIALOG;

    if ((m_lDialogStyle & wxHIDE_READONLY) || (m_lDialogStyle & wxSAVE))
        lFlags |= FDS_SAVEAS_DIALOG;
    if (m_lDialogStyle & wxMULTIPLE )
        lFlags |= FDS_OPEN_DIALOG | FDS_MULTIPLESEL;

    vFileDlg.cbSize = sizeof(FILEDLG);
    vFileDlg.fl = lFlags;
    vFileDlg.pszTitle = zTitleBuffer;

    //
    // Convert forward slashes to backslashes (file selector doesn't like
    // forward slashes) and also squeeze multiple consecutive slashes into one
    // as it doesn't like two backslashes in a row neither
    //
    sDir.reserve(nLen);
    for ( i = 0; i < nLen; i++ )
    {
        wxChar                      ch = m_sDir[i];

        switch (ch)
        {
            case _T('/'):
                //
                // Convert to backslash
                //
                ch = _T('\\');

                //
                // Fall through
                //
            case _T('\\'):
                while (i < nLen - 1)
                {
                    wxChar          chNext = m_sDir[i + 1];

                    if (chNext != _T('\\') && chNext != _T('/'))
                        break;

                    //
                    // Ignore the next one, unless it is at the start of a UNC path
                    //
                    if (i > 0)
                        i++;
                    else
                        break;
                }

                //
                // Fall through
                //

            default:
                //
                // Normal char
                sDir += ch;
        }
    }
    if ( wxStrlen(m_sWildCard) == 0 )
        sTheFilter = "";
    else
        sTheFilter = m_sWildCard;

    pzFilterBuffer = strtok((char*)sTheFilter.c_str(), "|");
    while(pzFilterBuffer != NULL)
    {
        if (nCount > 0 && !(nCount % 2))
            sDir += wxT(";");
        if (nCount % 2)
        {
            sDir += pzFilterBuffer;
        }
        pzFilterBuffer = strtok(NULL, "|");
        nCount++;
    }
    if (nCount == 0)
        sDir += m_sFileName;
    if (sDir.IsEmpty())
        sDir = "*.*";
    wxStrcpy(vFileDlg.szFullFile, sDir.c_str());
    sFilterBuffer = sDir;

    hWnd = ::WinFileDlg( HWND_DESKTOP
                        ,GetHwndOf(m_pParent)
                        ,&vFileDlg
                       );
    if (hWnd && vFileDlg.lReturn == DID_OK)
    {
        m_asFileNames.Empty();
        if ((m_lDialogStyle & wxMULTIPLE ) && vFileDlg.ulFQFCount > 1)
        {
            for (int i = 0; i < vFileDlg.ulFQFCount; i++)
            {
                if (i == 0)
                {
                    m_sDir = wxPathOnly(wxString((const char*)*vFileDlg.papszFQFilename[0]));
                    m_sPath = (const char*)*vFileDlg.papszFQFilename[0];
                }
                m_sFileName = wxFileNameFromPath(wxString((const char*)*vFileDlg.papszFQFilename[i]));
                m_asFileNames.Add(m_sFileName);
            }
            ::WinFreeFileDlgList(vFileDlg.papszFQFilename);
        }
        else if (!(m_lDialogStyle & wxSAVE))
        {
            m_sPath = vFileDlg.szFullFile;
            m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
            m_sDir = wxPathOnly(vFileDlg.szFullFile);
        }
        else // save file
        {
            const wxChar*           pzExtension = NULL;

            wxStrcpy(zFileNameBuffer, vFileDlg.szFullFile);

            int                     nIdx = wxStrlen(zFileNameBuffer) - 1;
            wxString                sExt;

            wxSplitPath( zFileNameBuffer
                        ,&m_sPath
                        ,&m_sFileName
                        ,&sExt
                       );
            if (zFileNameBuffer[nIdx] == wxT('.') || sExt.IsEmpty())
            {
                zFileNameBuffer[nIdx] = wxT('\0');

                //
                // User has typed a filename without an extension:
                //
                // A filename can end in a "." here ("abc."), this means it
                // does not have an extension. Because later on a "." with
                // the default extension is appended we remove the "." if
                // filename ends with one (We don't want files called
                // "abc..ext")
                //
                pzExtension = sFilterBuffer.c_str();

                for( int i = 0; i < sFilterBuffer.length(); i++ )
                {
                    //
                    // Get extension
                    //
                    pzExtension = wxStrrchr(pzExtension, wxT('.'));
                    if ( pzExtension                      &&
                        !wxStrrchr(pzExtension, wxT('*')) &&
                        !wxStrrchr(pzExtension, wxT('?')) &&
                        pzExtension[1]                    &&
                        pzExtension[1] != wxT(' ')
                       )              // != "blabla. "
                    {
                        //
                        // Now concat extension to the fileName:
                        //
                        m_sPath = wxString(zFileNameBuffer) + pzExtension;
                    }
                }
            }
            else
            {
                m_sPath = vFileDlg.szFullFile;
            }
            m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
            m_sDir = wxPathOnly(vFileDlg.szFullFile);

            //
            // === Simulating the wxOVERWRITE_PROMPT >>============================
            //
            if ((m_lDialogStyle & wxOVERWRITE_PROMPT) &&
                (m_lDialogStyle & wxSAVE) &&
                (wxFileExists(m_sPath.c_str())))
            {
                wxString            sMessageText;

                sMessageText.Printf( _("File '%s' already exists.\nDo you want to replace it?")
                                    ,m_sPath.c_str()
                                   );
                if (wxMessageBox( sMessageText
                                 ,wxT("Save File As")
                                 ,wxYES_NO | wxICON_EXCLAMATION
                                ) != wxYES)
                {
                    return wxID_CANCEL;
                }
            }
        }
        return wxID_OK;
    }
    return wxID_CANCEL;
} // end of wxFileDialog::ShowModal

//
// Generic file load/save dialog
//
static wxString wxDefaultFileSelector (
  bool                              bLoad
, const char*                       pzWhat
, const char*                       pzExtension
, const char*                       pzDefaultName
, wxWindow*                         pParent
)
{
    char*                           pzExt = (char *)pzExtension;
    char                            zPrompt[50];
    wxString                        sStr;
    char                            zWild[60];

    if (bLoad)
        sStr = "Load %s file";
    else
        sStr = "Save %s file";
    sprintf(zPrompt, wxGetTranslation(sStr), pzWhat);

    if (*pzExt == '.')
        pzExt++;
    sprintf(zWild, "*.%s", pzExt);
    return wxFileSelector ( zPrompt
                           ,NULL
                           ,pzDefaultName
                           ,pzExt
                           ,zWild
                           ,0
                           ,pParent
                          );
} // end of wxDefaultFileSelector

//
// Generic file load dialog
//
wxString wxLoadFileSelector (
  const char*                       pzWhat
, const char*                       pzExtension
, const char*                       pzDefaultName
, wxWindow*                         pParent
)
{
    return wxDefaultFileSelector( TRUE
                                 ,pzWhat
                                 ,pzExtension
                                 ,pzDefaultName
                                 ,pParent
                                );
} // end of wxLoadFileSelector


//
// Generic file save dialog
//
wxString wxSaveFileSelector (
  const char*                       pzWhat
, const char*                       pzExtension
, const char*                       pzDefaultName
, wxWindow*                         pParent
)
{
    return wxDefaultFileSelector( FALSE
                                 ,pzWhat
                                 ,pzExtension
                                 ,pzDefaultName
                                 ,pParent
                                );
} // end of wxSaveFileSelector

