/* filedlgs.c - Handles the Windows 3.1 common dialogs.
 *
 * Created by Microsoft Corporation.
 */

#include "packager.h"
#include <commdlg.h>


static CHAR szCustFilterSpec[CBFILTERMAX];
static CHAR szFilterSpec[CBFILTERMAX];
static CHAR szLinkCaption[CBMESSAGEMAX];
static CHAR szImportFile[CBMESSAGEMAX];
static CHAR szExportFile[CBMESSAGEMAX];
static OPENFILENAME gofn;


static VOID AddExtension(LPOPENFILENAME lpOFN);



/* OfnInit() - Initializes the standard file dialog gofn structure.
 */
VOID
OfnInit(
    VOID
    )
{
    LPSTR lpstr;

    gofn.lStructSize         = sizeof(OPENFILENAME);
    gofn.hInstance           = ghInst;
    gofn.nMaxCustFilter      = CBFILTERMAX;
    gofn.nMaxFile            = CBPATHMAX;
    gofn.lCustData           = 0;
    gofn.lpfnHook            = NULL;
    gofn.lpTemplateName      = NULL;
    gofn.lpstrFileTitle      = NULL;

    LoadString(ghInst, IDS_IMPORTFILE, szImportFile, CBMESSAGEMAX);
    LoadString(ghInst, IDS_EXPORTFILE, szExportFile, CBMESSAGEMAX);
    LoadString(ghInst, IDS_CHANGELINK, szLinkCaption, CBMESSAGEMAX);
    LoadString(ghInst, IDS_ALLFILTER,  szFilterSpec, CBMESSAGEMAX);

    StringCchCat(szFilterSpec, ARRAYSIZE(szFilterSpec), "*.*");
}



/* OfnGetName() - Calls the standard file dialogs to get a file name
 */
BOOL
OfnGetName(
    HWND hwnd,
    UINT msg
    )
{
    gofn.hwndOwner           = hwnd;
    gofn.nFilterIndex        = 1;
    gofn.lpstrCustomFilter   = szCustFilterSpec;
    gofn.lpstrDefExt         = NULL;
    gofn.lpstrFile           = gszFileName;
    gofn.lpstrFilter         = szFilterSpec;
    gofn.lpstrInitialDir     = NULL;
    gofn.Flags               = OFN_HIDEREADONLY;

    Normalize(gszFileName);

    switch (msg)
    {
        case IDM_IMPORT:
            gofn.lpstrTitle = szImportFile;
            gofn.Flags |= OFN_FILEMUSTEXIST;

            return GetOpenFileName(&gofn);

        case IDM_EXPORT:
            gofn.lpstrTitle = szExportFile;
            gofn.Flags |= (OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN);

            return GetSaveFileName(&gofn);

        default:
            break;
    }

    return FALSE;
}



/* OfnGetNewLinkName() - Sets up the "Change Link..." dialog box
 */
HANDLE
OfnGetNewLinkName(
    HWND hwnd,
    HANDLE hData
    )
{
    BOOL fSuccess = FALSE;
    HANDLE hData2 = NULL;
    HANDLE hData3 = NULL;
    LPSTR lpstrData = NULL;
    LPSTR lpstrFile = NULL;
    LPSTR lpstrLink = NULL;
    LPSTR lpstrPath = NULL;
    LPSTR lpstrTemp = NULL;
    CHAR szDocFile[CBPATHMAX];
    CHAR szDocPath[CBPATHMAX];
    CHAR szServerFilter[4 * CBPATHMAX];

    // this may have to GlobalAlloc(), if a class supports
    // multiple extensions, like Pbrush then we could be in
    // trouble. I covered PBRUSH case by making array size 256

    // Get the link information
    if (!(lpstrData = GlobalLock(hData)))
        goto Error;

    // Figure out the link's path name and file name
    lpstrTemp = lpstrData;
    while (*lpstrTemp++)
        ;

    lpstrPath = lpstrFile = lpstrTemp;

    while (*(lpstrTemp = CharNext(lpstrTemp)))
    {
        if (*lpstrTemp == '\\')
            lpstrFile = lpstrTemp + 1;
    }

    // Copy the document name
    StringCchCopy(szDocFile, ARRAYSIZE(szDocFile), lpstrFile);
    *(lpstrFile - 1) = 0;

    // Copy the path name
    StringCchCopy(szDocPath, ARRAYSIZE(szDocPath), ((lpstrPath != lpstrFile) ? lpstrPath : ""));

    // If no directory, be sure the path points to the root
    if (lstrlen(szDocPath) == 2)
        StringCchCat(szDocPath, ARRAYSIZE(szDocPath), "\\");

    if (lpstrPath != lpstrFile)                 /* Restore the backslash */
        *(lpstrFile - 1) = '\\';

    while (*lpstrFile != '.' && *lpstrFile)     /* Get the extension */
        lpstrFile++;

    // Make a filter that respects the link's class name
    gofn.hwndOwner           = hwnd;
    gofn.nFilterIndex        = RegMakeFilterSpec(lpstrData, lpstrFile, szServerFilter);
    gofn.lpstrDefExt         = NULL;
    gofn.lpstrFile           = szDocFile;
    gofn.lpstrFilter         = szServerFilter;
    gofn.lpstrInitialDir     = szDocPath;
    gofn.lpstrTitle          = szLinkCaption;
    gofn.lpstrCustomFilter   = szCustFilterSpec;
    gofn.Flags               = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;

    // If we get a file...
    if (GetOpenFileName(&gofn))
    {
        if (!(hData2 = GlobalAlloc(GMEM_ZEROINIT, CBPATHMAX *
            2)) || !(lpstrLink = lpstrTemp = GlobalLock(hData2)))
            goto Error;

        // ...add on the correct extension
        AddExtension(&gofn);

        // ... copy the server name
        while (*lpstrTemp++ = *lpstrData++)
            ;

        // ... copy the document name
        lstrcpy(lpstrTemp, szDocFile);
        lpstrTemp += lstrlen(lpstrTemp) + 1;
        lpstrData += lstrlen(lpstrData) + 1;

        // ... copy the item name
        while (*lpstrTemp++ = *lpstrData++)
            ;

        *lpstrTemp = 0;

        // ... and compress the memory block to minimal size
        GlobalUnlock(hData2);
        hData3 = GlobalReAlloc(hData2, (DWORD)(lpstrTemp - lpstrLink + 1), 0);

        if (!hData3)
            hData3 = hData2;

        fSuccess = TRUE;
    }

Error:
    if (!fSuccess)
    {
        if (lpstrLink)
            GlobalUnlock(hData2);

        if (hData2)
            GlobalFree(hData2);

        hData3 = NULL;
    }

    if (lpstrData)
        GlobalUnlock(hData);

    return hData3;
}



/* Normalize() - Removes the path specification from the file name.
 *
 * Note:  It isn't possible to get "<drive>:<filename>" as input because
 *        the path received will always be fully qualified.
 */
VOID
Normalize(
    LPSTR lpstrFile
    )
{
    LPSTR lpstrBackslash = NULL;
    LPSTR lpstrTemp = lpstrFile;
    BOOL fInQuote = FALSE;
    BOOL fQState = FALSE;

    while (*lpstrTemp)
    {
        if (*lpstrTemp == CHAR_QUOTE)
            fInQuote = !fInQuote;

        if (*lpstrTemp == '\\') {
            fQState = fInQuote;
            lpstrBackslash = lpstrTemp;
        }

        if (gbDBCS)
        {
            lpstrTemp = CharNext(lpstrTemp);
        }
        else
        {
            lpstrTemp++;
        }
    }

    if (lpstrBackslash) {
        if (fQState)
            *lpstrFile++ = CHAR_QUOTE;

        MoveMemory(lpstrFile, lpstrBackslash + 1,
            lstrlen(lpstrBackslash) * sizeof(lpstrBackslash[0]) );
    }
}



/* AddExtension() - Adds the extension corresponding to the filter dropdown.
 */
static VOID
AddExtension(
    LPOPENFILENAME lpOFN
    )
{
    LPSTR lpstrFilter = (LPSTR)lpOFN->lpstrFilter;

    // If the user didn't specify an extension, use the default
    if (lpOFN->nFileExtension == (UINT)lstrlen(lpOFN->lpstrFile)
        && lpOFN->nFilterIndex)
    {
        // Skip to the appropriate filter
        while (*lpstrFilter && --lpOFN->nFilterIndex)
        {
            while (*lpstrFilter++)
                ;

            while (*lpstrFilter++)
                ;
        }

        // If we got to the filter, retrieve the extension
        if (*lpstrFilter)
        {
            while (*lpstrFilter++)
                ;

            lpstrFilter++;

            // Copy the extension
            if (lpstrFilter[1] != '*')
                lstrcat(lpOFN->lpstrFile, lpstrFilter);
        }
    }
}
