
#include "priv.h"       

HINSTANCE g_hinst;

#define APP_VERSION         "Version 0.4"


// Don't link to shlwapi.dll so this is a stand-alone tool

/*----------------------------------------------------------
Purpose: If a path is contained in quotes then remove them.

*/
void
PathUnquoteSpaces(
    LPTSTR lpsz)
{
    int cch;

    cch = lstrlen(lpsz);

    // Are the first and last chars quotes?
    if (lpsz[0] == TEXT('"') && lpsz[cch-1] == TEXT('"'))
    {
        // Yep, remove them.
        lpsz[cch-1] = TEXT('\0');
        hmemcpy(lpsz, lpsz+1, (cch-1) * SIZEOF(TCHAR));
    }
}


#define CH_WHACK TEXT(FILENAME_SEPARATOR)

LPTSTR
PathFindExtension(
    LPCTSTR pszPath)
{
    LPCTSTR pszDot = NULL;

    if (pszPath)
    {
        for (; *pszPath; pszPath = CharNext(pszPath))
        {
            switch (*pszPath) {
            case TEXT('.'):
                pszDot = pszPath;         // remember the last dot
                break;
            case CH_WHACK:
            case TEXT(' '):         // extensions can't have spaces
                pszDot = NULL;       // forget last dot, it was in a directory
                break;
            }
        }
    }

    // if we found the extension, return ptr to the dot, else
    // ptr to end of the string (NULL extension) (cast->non const)
    return pszDot ? (LPTSTR)pszDot : (LPTSTR)pszPath;
}



__inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
{
    /* Most of the time this won't match, so test it first for speed.
    */
    if (LOBYTE(w1) == LOBYTE(wMatch))
    {
        if (IsDBCSLeadByte(LOBYTE(w1)))
        {
            return(w1 != wMatch);
        }
        return FALSE;
    }
    return TRUE;
}


LPSTR FAR PASCAL StrChrA(LPCSTR lpStart, WORD wMatch)
{
    for ( ; *lpStart; lpStart = AnsiNext(lpStart))
    {
        if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch))
            return((LPSTR)lpStart);
    }
    return (NULL);
}

BOOL
StrTrim(
    IN OUT LPSTR  pszTrimMe,
    IN     LPCSTR pszTrimChars)
    {
    BOOL bRet = FALSE;
    LPSTR psz;
    LPSTR pszStartMeat;
    LPSTR pszMark = NULL;

    ASSERT(IS_VALID_STRING_PTRA(pszTrimMe, -1));
    ASSERT(IS_VALID_STRING_PTRA(pszTrimChars, -1));

    if (pszTrimMe)
    {
        /* Trim leading characters. */

        psz = pszTrimMe;

        while (*psz && StrChrA(pszTrimChars, *psz))
            psz = CharNextA(psz);

        pszStartMeat = psz;

        /* Trim trailing characters. */

        // (The old algorithm used to start from the end and go
        // backwards, but that is piggy because DBCS version of
        // CharPrev iterates from the beginning of the string
        // on every call.)

        while (*psz)
            {
            if (StrChrA(pszTrimChars, *psz))
                {
                pszMark = psz;
                }
            else
                {
                pszMark = NULL;
                }
            psz = CharNextA(psz);
            }

        // Any trailing characters to clip?
        if (pszMark)
            {
            // Yes
            *pszMark = '\0';
            bRet = TRUE;
            }

        /* Relocate stripped string. */

        if (pszStartMeat > pszTrimMe)
        {
            /* (+ 1) for null terminator. */
            MoveMemory(pszTrimMe, pszStartMeat, CbFromCchA(lstrlenA(pszStartMeat) + 1));
            bRet = TRUE;
        }
        else
            ASSERT(pszStartMeat == pszTrimMe);

        ASSERT(IS_VALID_STRING_PTRA(pszTrimMe, -1));
    }

    return bRet;
    }



void PrintSyntax(void)
{
    fprintf(stderr, "cleaninf.exe  " APP_VERSION "\n\n"
                    "Cleans up an inf, html, or script file for public distribution or for packing\n"
                    "into a resource.  Without any options, this removes all comments.  This\n"
                    "tool recognizes .inf, .htm, .hta, .js and .htc files by default.\n\n"
                    "Syntax:  cleaninf [-w] [-inf | -htm | -js | -htc] sourceFile destFile\n\n"
                    "          -w     Strip whitespace\n\n"
                    "         These flags are mutually exclusive, and will treat the file\n"
                    "         accordingly, regardless of extension:\n"
                    "          -inf   Treat file as a .inf file\n"
                    "          -htm   Treat file as a .htm file\n"
                    "          -js    Treat file as a .js file\n"
                    "          -htc   Treat file as a .htc file\n");
}    


/*----------------------------------------------------------
Purpose: Worker function to do the work

*/
int
DoWork(int cArgs, char * rgszArgs[])
{
    LPSTR psz;
    LPSTR pszSrc = NULL;
    LPSTR pszDest = NULL;
    DWORD dwFlags = 0;
    int i;
    int nRet = 0;

    // (The first arg is actually the exe.  Skip that.)

    for (i = 1; i < cArgs; i++)
    {
        psz = rgszArgs[i];

        // Check for options
        if ('/' == *psz || '-' == *psz)
        {
            psz++;
            switch (*psz)
            {
            case '?':
                // Help
                PrintSyntax();
                return 0;

            case 'w':
                dwFlags |= PFF_WHITESPACE;
                break;

            default:
                if (0 == strncmp(psz, "inf", 3))
                {
                    dwFlags |= PFF_INF;
                }
                else if (0 == strncmp(psz, "htm", 3))
                {
                    dwFlags |= PFF_HTML;
                }
                else if (0 == strncmp(psz, "js", 2))
                {
                    dwFlags |= PFF_JS;
                }
                else if (0 == strncmp(psz, "htc", 3))
                {
                    dwFlags |= PFF_HTC;
                }
                else
                {
                    // unknown
                    fprintf(stderr, "Invalid option -%c\n", *psz);
                    return -1;
                }
                break;
            }
        }
        else if (!pszSrc)
            pszSrc = rgszArgs[i];
        else if (!pszDest)
            pszDest = rgszArgs[i];
        else
        {
            fprintf(stderr, "Ignoring invalid parameter - %s\n", rgszArgs[i]);
        }
    }

    if (!pszSrc || !pszDest)
    {
        PrintSyntax();
        return -2;
    }

    // Has the file type already been explicitly specified?
    if ( !(dwFlags & (PFF_INF | PFF_HTML | PFF_JS | PFF_HTC)) )
    {
        // No; determine it based on the extension
        LPTSTR pszExt = PathFindExtension(pszSrc);

        if (pszExt)
        {
            if (0 == lstrcmpi(pszExt, ".htm") || 0 == lstrcmpi(pszExt, ".hta"))
                dwFlags |= PFF_HTML;
            else if (0 == lstrcmpi(pszExt, ".js"))
                dwFlags |= PFF_JS;
            else if (0 == lstrcmpi(pszExt, ".htc"))
                dwFlags |= PFF_HTC;
        }
    }
    
    // Open the files
    PathUnquoteSpaces(pszSrc);
    PathUnquoteSpaces(pszDest);

    FILE * pfileSrc = fopen(pszSrc, "r");

    if (NULL == pfileSrc)
    {
        fprintf(stderr, "\"%s\" could not be opened", pszSrc);
        nRet = -3;
    }
    else
    {
        FILE * pfileDest = fopen(pszDest, "w");

        if (NULL == pfileDest)
        {
            fprintf(stderr, "\"%s\" could not be created", pszDest);
            nRet = -4;
        }
        else
        {
            CParseFile parsefile;

            parsefile.Parse(pfileSrc, pfileDest, dwFlags);
            
            fclose(pfileDest);
        }
        
        fclose(pfileSrc);
    }
    return nRet;
}


#ifdef UNIX

EXTERN_C
HINSTANCE MwMainwinInitLite(int argc, char *argv[], void* lParam);

EXTERN_C
HINSTANCE mainwin_init(int argc, char *argv[])
{
          return MwMainwinInitLite(argc, argv, NULL);
}

#endif

int __cdecl main(int argc, char * argv[])
{
    return DoWork(argc, argv);
}    

