
/*
 *@@sourcefile xfpgmf.c:
 *      This file contains the following major XFolder parts:
 *
 *      --  XFldProgramFile SOM stuff
 *
 *      Check the other files starting with xf* for the
 *      other XFolder classes.
 *
 *      XFldProgram is only responsible for changing the
 *      default icons of executable files.
 *
 *      Installation of this class is optional.
 *
 *@@somclass XFldProgramFile xfpgmf_
 *@@somclass M_XFldProgramFile xfpgmfM_
 */

/*
 *      Copyright (C) 1997-99 Ulrich M”ller.
 *      This file is part of the XFolder source package.
 *      XFolder is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published
 *      by the Free Software Foundation, in version 2 as it comes in the
 *      "COPYING" file of the XFolder main distribution.
 *      This program 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 General Public License for more details.
 */

/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitctm: 2.41
 */

#ifndef SOM_Module_xfpgmf_Source
#define SOM_Module_xfpgmf_Source
#endif
#define XFldProgramFile_Class_Source
#define M_XFldProgramFile_Class_Source

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  SOM headers which work with precompiled header files
 *  4)  headers in /helpers
 *  5)  headers in /main with dlgids.h and common.h first
 *  6)  #pragma hdrstop to prevent VAC++ crashes
 *  7)  other needed SOM headers
 *  8)  for non-SOM-class files: corresponding header (e.g. classlst.h)
 */

#define INCL_DOSSESMGR          // DosQueryAppType
#define INCL_DOSERRORS
#define INCL_WINPROGRAMLIST     // needed for WPProgram
#define INCL_WINPOINTERS
#include <os2.h>

// C library headers
#include <stdio.h>

// headers in /helpers

// SOM headers which don't crash with prec. header files

// other SOM headers
#pragma hdrstop                 // VAC++ keeps crashing otherwise
#include "xfpgmf.ih"

// headers in /main
#include "common.h"             // the majestic XFolder include file


/* ******************************************************************
 *                                                                  *
 *   Global variables                                               *
 *                                                                  *
 ********************************************************************/


/* ******************************************************************
 *                                                                  *
 *   here come the XFldProgramFile instance methods                 *
 *                                                                  *
 ********************************************************************/

/*
 *@@ xfQueryProgType:
 *           this returns the PROG_* flag signalling the executable
 *           type of the program file.
 *           Note that in addition to the PROG_* flags defined in
 *           PROGDETAILS, this may also return the following:
 *               PROG_XF_DLL     for dynamic link libraries
 *               PROG_XF_DRIVER  for virtual or physical device drivers;
 *                               most files ending in .SYS will be
 *                               recognized as DLL's though.
 */

SOM_Scope ULONG  SOMLINK xfpgmf_xfQueryProgType(XFldProgramFile *somSelf)
{
    PPROGDETAILS    pProgDetails;
    ULONG           ulSize;

    XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_xfQueryProgType");

    #ifdef DEBUG_ASSOCS
        _Pmpf(("  xfQueryProgType %s, before: 0x%lX",
            _wpQueryTitle(somSelf), _ulAppType));
    #endif

    if (_ulAppType == -1)
    {
        // not queried yet:

        // get program object data
        if ((_wpQueryProgDetails(somSelf, (PPROGDETAILS)NULL, &ulSize))) {
            if ((pProgDetails = (PPROGDETAILS)malloc(ulSize)) != NULL) {
                if ((_wpQueryProgDetails(somSelf, pProgDetails, &ulSize)))
                {
                    // we base our assumptions on what OS/2 thinks
                    // the app type is
                    _ulAppType = pProgDetails->progt.progc;

                    #ifdef DEBUG_ASSOCS
                        _Pmpf(("    progdtls.progc: 0x%lX",
                                    _ulAppType));
                    #endif

                    // and we modify a few of these assumptions
                    switch (_ulAppType)
                    {
                        case PROG_PDD:
                        case PROG_VDD:
                            // these two types are documented in pmshl.h,
                            // but I'm not sure they're ever used; convert
                            // them to our own driver type
                            _ulAppType = PROG_XF_DRIVER;
                        break;

                        // Windows:
                        case PROG_WINDOW_REAL         :
                        case PROG_30_STD              :
                        case PROG_WINDOW_AUTO         :
                        case PROG_30_STDSEAMLESSVDM   :
                        case PROG_30_STDSEAMLESSCOMMON:
                        case PROG_31_STDSEAMLESSVDM   :
                        case PROG_31_STDSEAMLESSCOMMON:
                        case PROG_31_ENHSEAMLESSVDM   :
                        case PROG_31_ENHSEAMLESSCOMMON:
                        case PROG_31_ENH              :
                        case PROG_31_STD              :
                        {
                            // for all the Windows app types, we check
                            // for whether the extension of the file is
                            // DLL or 386; if so, we change the type to
                            // DLL. Otherwise,  all Windows DLL's get
                            // some default windoze icon.
                            CHAR    szProgramFile[CCHMAXPATH];
                            if (_wpQueryFilename(somSelf, szProgramFile, FALSE))
                            {
                                PSZ     pLastDot = strrchr(szProgramFile, '.');
                                strupr(szProgramFile);
                                if (strcmp(pLastDot, ".DLL") == 0)
                                    // DLL found:
                                    _ulAppType = PROG_XF_DLL;
                            }
                        break; }

                        case PROG_DEFAULT:  // == 0; OS/2 isn't sure what this is
                        {
                            CHAR        szProgramFile[CCHMAXPATH];
                            APIRET      arc;

                            if (_wpQueryFilename(somSelf, szProgramFile, TRUE))
                            {
                                // no type available: get it ourselves
                                arc = DosQueryAppType(szProgramFile, &(_ulDosAppType));
                                if (arc == NO_ERROR) {
                                    if (_ulDosAppType == 0)
                                        _ulAppType = PROG_FULLSCREEN;
                                    else if (   (_ulDosAppType & 0x40)
                                             || (_ulDosAppType & 0x80)
                                            )
                                        // some driver bit set
                                        _ulAppType = PROG_XF_DRIVER;
                                    else if ((_ulDosAppType & 0xF0) == 0x10)
                                        // DLL bit set
                                        _ulAppType = PROG_XF_DLL;
                                    else if (_ulDosAppType & 0x20)
                                        // DOS bit set?
                                        _ulAppType = PROG_WINDOWEDVDM;
                                    else if ((_ulDosAppType & 0x0003) == 0x0003) // "Window-API" == PM
                                        _ulAppType = PROG_PM;
                                    else if (   ((_ulDosAppType & 0xFFFF) == 0x1000) // windows program (?!?)
                                             || ((_ulDosAppType & 0xFFFF) == 0x0400) // windows program (?!?)
                                            )
                                        _ulAppType = PROG_31_ENH;
                                    else if ((_ulDosAppType & 0x03) == 0x02)
                                        _ulAppType = PROG_WINDOWABLEVIO;
                                    else if ((_ulDosAppType & 0x03) == 0x01)
                                        _ulAppType = PROG_FULLSCREEN;
                                }
                            }
                        break; }

                        // the other values are OK, leave them as is

                    } // end switch (_ulAppType)
                }
                free(pProgDetails);
            }
        }
    }

    #ifdef DEBUG_ASSOCS
        _Pmpf(("  End of xfQueryProgType, returning: 0x%lX",
                _ulAppType));
    #endif

    return (_ulAppType);

}

/*
 *@@ wpInitData:
 *           initialize instance data for a program file
 */

SOM_Scope void  SOMLINK xfpgmf_wpInitData(XFldProgramFile *somSelf)
{
    XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpInitData");

    // initialize instance data
    _ulDosAppType = -1;
    _ulAppType = -1;
    _fProgIconSet = FALSE;
    _hptrThis = NULLHANDLE;

    XFldProgramFile_parent_WPProgramFile_wpInitData(somSelf);
}

/*
 *@@ wpObjectReady:
 *           this is called upon an object when its creation
 *           or awakening is complete. This is the last method
 *           which gets called during instantiation of a
 *           WPS object.
 *           For XFldProgramFile, we need this notification to
 *           reset the icon data in our instance data, because
 *           otherwise we get wrong icons when copying program
 *           files.
 */

SOM_Scope void  SOMLINK xfpgmf_wpObjectReady(XFldProgramFile *somSelf,
                                             ULONG ulCode, WPObject* refObject)
{
    XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpObjectReady");

    // _Pmpf(("  %s: wpObjectReady", _wpQueryTitle(somSelf) ));
    // reset our app type flags, because when program files
    // are _copied_, wpSetProgIcon gets called one time too early
    // (between wpInitData and wpObjectReady; at this point,
    // the PROGDETAILS have no meaningful values, and xfQueryProgType
    // has returned garbage data),
    // and a second time in time (after wpObjectReady);
    // for this second time we need to pretend that we haven't
    // queried the app type yet, because for the second call
    // of wpSetProgIcon, the icon will then be set correctly
    _ulDosAppType = -1;
    _ulAppType = -1;

    XFldProgramFile_parent_WPProgramFile_wpObjectReady(somSelf,
                                                       ulCode,
                                                       refObject);
    // _Pmpf(("  End of wpObjectReady"));
}

/*
 *@@ wpQueryStyle:
 *           this instance method returns the object style flags.
 */

SOM_Scope ULONG  SOMLINK xfpgmf_wpQueryStyle(XFldProgramFile *somSelf)
{
    ULONG ulStyle = 0;
    // XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpQueryStyle");

    ulStyle = XFldProgramFile_parent_WPProgramFile_wpQueryStyle(somSelf);

    #ifdef DEBUG_ASSOCS
        _Pmpf(("%s: wpQueryStyle: 0x%lX %s %s",
                    _wpQueryTitle(somSelf),
                    ulStyle,
                    (ulStyle & OBJSTYLE_NOTDEFAULTICON) ? "OBJSTYLE_NOTDEFAULTICON" : "",
                    (ulStyle & OBJSTYLE_CUSTOMICON) ? "OBJSTYLE_CUSTOMICON" : ""));
    #endif
    return (ulStyle /* & ~OBJSTYLE_CUSTOMICON */);
}

/*
 *@@ wpSetIcon:
 *           this instance method sets the visual icon for
 *           this program file. This is not stored in the
 *           persistent data (which is only done in
 *           wpSetIconData), but only changes the visual
 *           appearance of the object.
 */

SOM_Scope BOOL  SOMLINK xfpgmf_wpSetIcon(XFldProgramFile *somSelf,
                                         HPOINTER hptrNewIcon)
{
    BOOL brc = TRUE;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpSetIcon");

    #ifdef DEBUG_ASSOCS
        _Pmpf(("    %s wpSetIcon", _wpQueryTitle(somSelf) ));
    #endif
    // icon replacements allowed?
    /* if (pGlobalSettings->ReplIcons) {
        XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
        // we only allow the icon to be changed if
        // this is a call from _wpSetProgIcon (which
        // we have overriden) or if the WPS calls this
        // method for the first time, e.g. because it is
        // being set by some method other than wpSetProgIcon,
        // which happens if the WPS has determined the icon
        // from the executable or .ICON EA's.
        if (    (_hptrThis == NULLHANDLE)
             || (_fProgIconSet)
           )
        {
            _hptrThis = hptrNewIcon;
            brc = XFldProgramFile_parent_WPProgramFile_wpSetIcon(somSelf,
                                                                   hptrNewIcon);
            // prohibit subsequent calls
            _fProgIconSet = FALSE;
        }
        // else: ignore the call. The WPS keeps messing with
        // program icons from methods other than _wpSetProgIcon,
        // which we must ignore.

    } else */
        brc = XFldProgramFile_parent_WPProgramFile_wpSetIcon(somSelf,
                                                               hptrNewIcon);

    return (brc);
}

/*
 *@@ wpSetProgIcon:
 *           this instance method sets the visual icon for
 *           this program file to the appropriate custom
 *           or default icon. We override this to change
 *           the default icons for program files using
 *           /ICONS/ICONS.DLL, if the global settings allow
 *           this.
 *           The following methods are called by the WPS when
 *           an icon is to be determined for a WPProgramFile:
 *           -- if the file has its own icon, e.g. from the
 *              .ICON EAs: only wpSetIcon, this method does
 *              _not_ get called then.
 *           -- otherwise (no .ICON):
 *              1)  wpQueryIcon, which calls
 *              2)  wpSetProgIcon, which per default calls
 *              3)  wpSetIcon
 *           We must return an individual icon in this method,
 *           so we load the icons from /ICONS/ICONS.DLL every
 *           time we arrive here.
 *           If we return a "global" icon handle which could
 *           have been loaded in wpclsInitData, unfortunately
 *           the WPS will destroy that "global" icon, ruining
 *           the icons of all other program files also.
 */

SOM_Scope BOOL  SOMLINK xfpgmf_wpSetProgIcon(XFldProgramFile *somSelf,
                                             PFEA2LIST pfeal)
{
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    HPOINTER    hptr = NULLHANDLE;

    XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpSetProgIcon");

    // icon replacements allowed?
    if (pGlobalSettings->ReplIcons) {
        CHAR        szProgramFile[CCHMAXPATH];
        HMODULE     hmodIconsDLL = cmnQueryIconsDLL();
        APIRET      arc = NO_ERROR;

        #ifdef DEBUG_ASSOCS
            _Pmpf(("%s: wpSetProgIcon",
                        _wpQueryTitle(somSelf) ));
        #endif

        if (_wpQueryFilename(somSelf, szProgramFile, TRUE))
        {

            // first: check if an .ICO file of the same filestem
            // exists in the folder. If so, _always_ use that icon.
            PSZ p = strrchr(szProgramFile, '.');
            if (p) {
                CHAR szIconFile[CCHMAXPATH];
                strncpy(szIconFile, szProgramFile, (p-szProgramFile));
                strcpy(szIconFile + (p-szProgramFile), ".ico");
                #ifdef DEBUG_ASSOCS
                    _Pmpf(("   Icon file: %s", szIconFile));
                #endif
                hptr = WinLoadFileIcon(szIconFile, TRUE);
            }

            if (!hptr)
            {
                // no such .ICO file exists:
                // examine the application type we have
                switch (_xfQueryProgType(somSelf))
                {

                    // PM:
                    case PROG_PM                  :
                    // Windows:
                    case PROG_WINDOW_REAL         :
                    case PROG_30_STD              :
                    case PROG_WINDOW_AUTO         :
                    case PROG_30_STDSEAMLESSVDM   :
                    case PROG_30_STDSEAMLESSCOMMON:
                    case PROG_31_STDSEAMLESSVDM   :
                    case PROG_31_STDSEAMLESSCOMMON:
                    case PROG_31_ENHSEAMLESSVDM   :
                    case PROG_31_ENHSEAMLESSCOMMON:
                    case PROG_31_ENH              :
                    case PROG_31_STD              :
                    {
                        // have PM determine the icon
                        hptr = WinLoadFileIcon(szProgramFile, TRUE);
                    break; }

                    case PROG_WINDOWABLEVIO:
                    {
                        // "window compatible":
                        // OS/2 window icon
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               108);
                    break; }

                    case PROG_FULLSCREEN:
                    {
                        // "not window compatible":
                        // OS/2 fullscreen icon
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               107);
                    break; }

                    case PROG_WINDOWEDVDM:
                    {
                        // DOS window
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               105);
                    break; }

                    case PROG_VDM: // == PROG_REAL
                    {
                        // DOS fullscreen
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               104);
                    break; }

                    case PROG_XF_DLL:
                    {   // DLL flag set: load DLL icon
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               103);
                    break; }

                    case PROG_XF_DRIVER:
                    {
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               106);
                    break; }

                    default:
                    {
                        // unknown:
                        hptr = WinLoadPointer(HWND_DESKTOP, hmodIconsDLL,
                               102);
                    }

                }
            }
        }
    }

    if (hptr == NULLHANDLE) {
        // replacement icon does not exist in /ICONS
        // or Global Settings do not allow replacements:
        // call default parent method
        return (XFldProgramFile_parent_WPProgramFile_wpSetProgIcon(somSelf,
                                                           pfeal));
    }
    // else:

    // set a flag for our wpSetIcon override
    _fProgIconSet = TRUE;

    // some icon from /ICONS found: set it
    _wpSetIcon(somSelf, hptr);

    #ifdef DEBUG_ASSOCS
        _Pmpf(("End of xfpgmf_wpSetProgIcon"));
    #endif

    return (TRUE);
}

/*
 *@@ wpQueryDefaultView:
 *           this returns the default view of an object, that
 *           is, which view is opened if the program file is
 *           double-clicked upon. This is also used to mark
 *           the default view in the "Open" context submenu.
 *           For WPProgramFile, the WPS always returns
 *           OPEN_RUNNING (0x04), which doesn't make sense
 *           for DLL's and drivers, which cannot be executed.
 *           We therefore return the value for "first associated
 *           program", which is 0x1000.
 *           Oh yes, as usual, this value is undocumented. ;-)
 */

SOM_Scope ULONG  SOMLINK xfpgmf_wpQueryDefaultView(XFldProgramFile *somSelf)
{
    ULONG ulView;
    ULONG ulProgType = _xfQueryProgType(somSelf);

    XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf);
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpQueryDefaultView");

    #ifdef DEBUG_ASSOCS
        _Pmpf(( "wpQueryDefaultView for %s", _wpQueryTitle(somSelf) ));
    #endif

    ulView = XFldProgramFile_parent_WPProgramFile_wpQueryDefaultView(somSelf);

    if (    (ulProgType == PROG_XF_DLL)
         || (ulProgType == PROG_XF_DRIVER)
         || (ulProgType == PROG_DEFAULT)
       )
        if (ulView == OPEN_RUNNING)
            // we can neither run DLL's nor drivers, so we
            // pass the first context menu item
            ulView = 0x1000;        // this is the WPS internal code
                                    // for the first association view

    return (ulView);
}

/*
 *@@ wpFilterPopupMenu:
 *           remove the "Program" context menu entry for
 *           DLL's and drivers
 */

SOM_Scope ULONG  SOMLINK xfpgmf_wpFilterPopupMenu(XFldProgramFile *somSelf,
                                                  ULONG ulFlags,
                                                  HWND hwndCnr,
                                                  BOOL fMultiSelect)
{
    ULONG ulFilter;
    ULONG ulProgType = _xfQueryProgType(somSelf);

    /* XFldProgramFileData *somThis = XFldProgramFileGetData(somSelf); */
    XFldProgramFileMethodDebug("XFldProgramFile","xfpgmf_wpFilterPopupMenu");

    ulFilter = XFldProgramFile_parent_WPProgramFile_wpFilterPopupMenu(somSelf,
                                                                   ulFlags,
                                                                   hwndCnr,
                                                                   fMultiSelect);
    if (    (ulProgType == PROG_XF_DLL)
         || (ulProgType == PROG_XF_DRIVER)
         || (ulProgType == PROG_DEFAULT)
       )
        ulFilter &= ~ CTXT_PROGRAM;

    return (ulFilter);
}

/* ******************************************************************
 *                                                                  *
 *   here come the XFldProgramFile class methods                    *
 *                                                                  *
 ********************************************************************/

/*
 *@@ wpclsInitData:
 *           we override this to initialize the path for the
 *           custom XFolder icons from the /ICONS directory.
 */

SOM_Scope void  SOMLINK xfpgmfM_wpclsInitData(M_XFldProgramFile *somSelf)
{
    // M_XFldProgramFileData *somThis = M_XFldProgramFileGetData(somSelf);
    M_XFldProgramFileMethodDebug("M_XFldProgramFile","xfpgmfM_wpclsInitData");

    M_XFldProgramFile_parent_M_WPProgramFile_wpclsInitData(somSelf);
}

CHAR szInstanceFilter[100];

/*
 *@@ wpclsQueryInstanceFilter:
 *           this class method determines which file-system objects
 *           will be instances of WPProgramFile/XFldProgramFile
 *           by specifying a file title filter. To avoid the annoying
 *           behavior of OS/2 Warp 4 that some DLL's are instances
 *           of WPProgramFile and some are not, we make all DLL's
 *           instances of WPProgramFile by specifying "*.DLL" too.
 *           This does not work using wpclsQueryInstance type,
 *           because the WPS seems to be using some default file
 *           type of "Executable", which is determined in some hidden
 *           place.
 */

SOM_Scope PSZ  SOMLINK xfpgmfM_wpclsQueryInstanceFilter(M_XFldProgramFile *somSelf)
{
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    /* M_XFldProgramFileData *somThis = M_XFldProgramFileGetData(somSelf); */
    M_XFldProgramFileMethodDebug("M_XFldProgramFile","xfpgmfM_wpclsQueryInstanceFilter");

    if (    (somSelf == _XFldProgramFile)
         && (pGlobalSettings->ReplIcons)
       )
    {
        strcpy(szInstanceFilter, "*.ADD,*.COM,*.DLL,*.DMD,*.EXE,*.FLT,*.IFS,*.SNP,*.SYS");
        return (szInstanceFilter);
    }
    else
        return (M_XFldProgramFile_parent_M_WPProgramFile_wpclsQueryInstanceFilter(somSelf));
}

