
/*
 *@@sourcefile xfdataf.c:
 *      This file contains SOM code for the following XWorkplace classes:
 *
 *      --  XFldDataFile (WPDataFile replacement)
 *
 *      XFldDataFile is responsible for menu manipulation
 *      and default icon replacements for data files.
 *      Since we should not override WPFileSystem to implement
 *      this functionality for folders and data files altogether,
 *      we must add this to WPDataFile separately.
 *
 *      Installation of this class is now optional (V0.9.0).
 *
 *      Starting with V0.9.0, the files in classes\ contain only
 *      i.e. the methods themselves.
 *      The implementation for this class is mostly in filesys\filesys.c
 *      and (for extended file types) in filesys\filetype.c.
 *
 *      <B>Extended File Associations</B>
 *
 *      -- To get the new associated programs into the "Open" menu,
 *         we override wpDisplayMenu (Warp 3) and wpModifyMenu
 *         (Warp 4).
 *
 *      -- For general WPS support (including icons), we override
 *         XFldDataFile::wpQueryAssociatedProgram.
 *
 *      -- The new selections are intercepted in XFldDataFile::wpOpen.
 *
 *@@somclass XFldDataFile xdf_
 *@@somclass M_XFldDataFile xdfM_
 */

/*
 *      Copyright (C) 1997-2013 Ulrich M”ller.
 *      This file is part of the XWorkplace source package.
 *      XWorkplace 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 XWorkplace 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_xfdataf_Source
#define SOM_Module_xfdataf_Source
#endif
#define XFldDataFile_Class_Source
#define M_XFldDataFile_Class_Source

#pragma strings(readonly)

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  setup.h (code generation and debugging options)
 *  4)  headers in helpers\
 *  5)  at least one SOM implementation header (*.ih)
 *  6)  dlgids.h, headers in shared\ (as needed)
 *  7)  headers in implementation dirs (e.g. filesys\, as needed)
 *  8)  #pragma hdrstop and then more SOM headers which crash with precompiled headers
 */

#define INCL_DOSPROCESS
#define INCL_DOSEXCEPTIONS
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS

#define INCL_WINPOINTERS
#define INCL_WINMENUS
#define INCL_WINPROGRAMLIST     // needed for wppgm.h
#include <os2.h>

// C library headers
#include <stdio.h>
#include <setjmp.h>

// generic headers
#include "setup.h"                      // code generation and debugging options

// headers in /helpers
#include "helpers\dosh.h"               // Control Program helper routines
#include "helpers\except.h"             // exception handling
#include "helpers\linklist.h"           // linked list helper routines
#include "helpers\standards.h"          // some standard macros
#include "helpers\winh.h"               // PM helper routines

// SOM headers which don't crash with prec. header files
#include "xfdataf.ih"

// XWorkplace implementation headers
#include "dlgids.h"                     // all the IDs that are shared with NLS
#include "shared\classtest.h"           // some cheap funcs for WPS class checks
#include "shared\common.h"              // the majestic XWorkplace include file
#include "shared\helppanels.h"          // all XWorkplace help panel IDs
#include "shared\kernel.h"              // XWorkplace Kernel
#include "shared\notebook.h"            // generic XWorkplace notebook handling
#include "shared\wpsh.h"                // some pseudo-SOM functions (WPS helper routines)

#include "filesys\filesys.h"            // various file-system object implementation code
#include "filesys\fileops.h"            // file operations implementation
#include "filesys\filetype.h"           // extended file types implementation
#include "filesys\folder.h"             // XFolder implementation
#include "filesys\fdrcommand.h"         // folder command handling
#include "filesys\fdrhotky.h"           // folder hotkey handling
#include "filesys\fdrmenus.h"           // shared folder menu logic
#include "filesys\icons.h"              // icons handling
// #include "filesys\object.h"             // XFldObject implementation
#include "filesys\program.h"            // program implementation; WARNING: this redefines macros

// other SOM headers
#pragma hdrstop                 // VAC++ keeps crashing otherwise

/* ******************************************************************
 *
 *   XFldDataFile instance methods
 *
 ********************************************************************/

/*
 *@@ wpInitData:
 *      this WPObject instance method gets called when the
 *      object is being initialized (on wake-up or creation).
 *      We initialize our additional instance data here.
 *      Always call the parent method first.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

SOM_Scope void  SOMLINK xdf_wpInitData(XFldDataFile *somSelf)
{
    XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpInitData");

    XFldDataFile_parent_WPDataFile_wpInitData(somSelf);

    _fHasIconEA = FALSE;

    // cache this V0.9.19 (2002-06-15) [umoeller]
    _fIsIconOrPointer =    (ctsIsIcon(somSelf))
                        || (ctsIsPointer(somSelf));
}

/*
 *@@ wpUnInitData:
 *
 *@@added V0.9.18 (2002-03-24) [umoeller]
 *@@changed V1.0.10 (2013-03-15) [pr]: @@fixes 336
 */

SOM_Scope void  SOMLINK xdf_wpUnInitData(XFldDataFile *somSelf)
{
    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpUnInitData");

    // we have a problem with our replacement icons in that
    // the WPS frees the pointer handle in WPObject::wpUnInitData
    // if the object has the OBJSTYLE_NOTDEFAULTICON or OBJSTYLE_TEMPLATE
    // flags set... so in these cases, check if the object has one
    // of our standard icons WHICH MUST NOT BE FREED under any circumstances,
    // or the shared icon would disappear globally
    // V0.9.16 (2001-12-31) [umoeller]
    #ifdef __DEBUG__
    {
        PMINIRECORDCORE pmrc = _wpQueryCoreRecord(somSelf);
        PMPF_ICONREPLACEMENTS(("[%s] OBJSTYLE_NOTDEFAULTICON %lX",
                _wpQueryTitle(somSelf),
                _wpQueryStyle(somSelf) & OBJSTYLE_NOTDEFAULTICON));
        PMPF_ICONREPLACEMENTS(("    OBJSTYLE_TEMPLATE %lX",
                _wpQueryStyle(somSelf) & OBJSTYLE_TEMPLATE));
        PMPF_ICONREPLACEMENTS(("    hptrIcon %lX",
                pmrc->hptrIcon));
        PMPF_ICONREPLACEMENTS(("    cmnIsStandardIcon %lX",
                cmnIsStandardIcon(pmrc->hptrIcon)));
    }
    #endif

    icomUnqueueLazyIcon(somSelf);  // V1.0.10
    XFldDataFile_parent_WPDataFile_wpUnInitData(somSelf);
}

/*
 *@@ wpDestroyObject:
 *      this undocumented WPObject method gets called during
 *      wpFree processing to destroy the physical storage of
 *      an object (for file-system objects, the file or folder,
 *      for abstracts, the INI data).
 *
 *      Starting with V0.9.20, we are now able to override this
 *      undocumented WPS method too, so the previous overhead
 *      with xwpDestroyStorage has been removed.
 *
 *      This implementation actually deletes the data file using
 *      DosDelete.
 *
 *      As opposed to the WPS, we are smart enough NOT to
 *      display a message box here if deletion failed. In
 *      addition, if the file is already gone, we return
 *      TRUE, since the file was obviously already deleted.
 *
 *@@added V0.9.20 (2002-07-25) [umoeller]
 *@@changed V1.0.0 (2002-09-09) [umoeller]: added wpSetError on errors
 */

SOM_Scope BOOL  SOMLINK xdf_wpDestroyObject(XFldDataFile *somSelf)
{
    BOOL    brc = FALSE;
    CHAR    szFilename[CCHMAXPATH];

    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpDestroyObject");

    if (_wpQueryFilename(somSelf, szFilename, TRUE))
    {
        // use DosForceDelete if the file is in \trash
        // V0.9.20 (2002-07-12) [umoeller]
        APIRET arc;
        if (fopsUseForceDelete(szFilename))
            arc = DosForceDelete(szFilename);
        else
            arc = DosDelete(szFilename);

        PMPF_FOPS(("DosDelete(%s) returned %d", szFilename, arc));

        switch (arc)
        {
            case NO_ERROR:
            case ERROR_FILE_NOT_FOUND:
            case ERROR_PATH_NOT_FOUND:
                brc = TRUE;
            break;

            default:
                // anything else is truly an error, so set an error
                // code on the object so fops_bottom.c can figure
                // out what went wrong; wpFree has called
                // wpSetError(NO_ERROR) previously
                // V1.0.0 (2002-09-09) [umoeller]
                _wpSetError(somSelf, arc);
        }
    }

    PMPF_FOPS(("returning %s", (brc) ? "TRUE" : "FALSE"));

    return brc;

    // return (XFldDataFile_parent_WPDataFile_wpDestroyObject(somSelf));
}

/*
 *@@ wpRestoreState:
 *      this WPObject instance method gets called during object
 *      initialization (after wpInitData) to restore the data
 *      which was stored with wpSaveState.
 *
 *      The WPDataFile implementation has a _major_ bug in here
 *      in that it turns _on_ the OBJSTYLE_NOTDEFAULTICON bit
 *      even if no icon was loaded from the EAs. As a result,
 *      another rewrite was in order here.
 *
 *      The interesting thing is that the ulReserved parameter
 *      points to a MAKEAWAKEFS structure (filesys.h) which
 *      was passed to wpclsMakeAwake by wpPopulate. As a result,
 *      we can use it to build an icon from the EAs that were
 *      loaded during populate.
 *
 *@@added V0.9.16 (2001-12-08) [umoeller]
 *@@changed V0.9.18 (2002-03-24) [umoeller]: fixed disappearing standard icons on copy
 */

SOM_Scope BOOL  SOMLINK xdf_wpRestoreState(XFldDataFile *somSelf,
                                           ULONG ulReserved)
{
    ULONG brc;
    somTD_WPObject_wpRestoreState pwpRestoreState = NULL;

    XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpRestoreState");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))
    {
        PMAKEAWAKEFS pFSData = (PMAKEAWAKEFS)ulReserved;

        PMPF_ICONREPLACEMENTS(("pre: hptr: 0x%lX, OBJSTYLE_NOTDEFAULTICON: %lX",
                _wpQueryCoreRecord(somSelf)->hptrIcon,
                _wpQueryStyle(somSelf) & OBJSTYLE_NOTDEFAULTICON));

        // find the WPFileSystem method by skipping the
        // buggy WPDataFile implementation
        if (pwpRestoreState = (somTD_WPObject_wpRestoreState)wpshResolveFor(
                                     somSelf,
                                     _WPFileSystem,     // class to resolve for
                                     "wpRestoreState"))
        {
            // found it: then it's safe to run our replacement
            PMINIRECORDCORE prec = _wpQueryCoreRecord(somSelf);
            APIRET arc;
            HPOINTER hptrNew;
            ULONG flNewStyle = 0;

            PMPF_ICONREPLACEMENTS(("obj 0x%lX: pFSData is 0x%lX", somSelf, pFSData));

            if (    (!prec->hptrIcon)
                 && (pFSData)
                 && (pFSData->pFea2List)
                 && (!(arc = icoBuildPtrFromFEA2List(pFSData->pFea2List,
                                                     &hptrNew,
                                                     NULL,
                                                     NULL)))
               )
            {
                _wpSetIcon(somSelf, hptrNew);

                // set icon style below
                // V0.9.18 (2002-03-24) [umoeller]
                flNewStyle = OBJSTYLE_NOTDEFAULTICON;

                PMPF_ICONREPLACEMENTS(("    custom prec->hptrIcon is 0x%lX", prec->hptrIcon));

                // set our instance data flag so that we know that
                // we should NEVER EVER use an association icon
                // here... dumb WPS keeps looking for the
                // OBJSTYLE_NOTDEFAULTICON and always assumes that
                // if this is set, the data file uses an assoc
                // icon, which is simply not true any more
                // V0.9.18 (2002-03-19) [umoeller]
                _fHasIconEA = TRUE;
            }

            brc = pwpRestoreState(somSelf, ulReserved);

            // moved this down here because parent restore state
            // overwrites this sucker, and then we might have
            // an erroneous OBJSTYLE_NOTDEFAULTICON set that
            // causes icons to be freed during copy...
            // V0.9.18 (2002-03-24) [umoeller]
            // situation was this:
            // copy command file via ctrl-drag
            // 1) wpCopyObject first instantiates a new SOM object
            // 2) calls wpRestoreState (this one here) to
            //    set up the new object's instance data
            // 3) checks if the source object has a non-default icon;
            //    if so, it is copied again... unfortunately, if we
            //    had the OBJSTYLE_NOTDEFAULTICON bit set here,
            //    our standard icon was nuked!!
            // This only happened for files with .ICON EAs, where
            // first we set a standard icon (!) and then the parent
            // wpRestoreState set the OBJSTYLE_NOTDEFAULTICON flag --
            // not a good idea.

            // Long story: set the flag only below so it will be
            // correct when we come out of restore.
            _wpModifyStyle(somSelf,
                           OBJSTYLE_NOTDEFAULTICON,
                           flNewStyle);
        }
        else
            cmnLog(__FILE__, __LINE__, __FUNCTION__,
                   "Cannot resolve WPFileSystem::wpRestoreState.");

        PMPF_ICONREPLACEMENTS(("post: hptr: 0x%lX, OBJSTYLE_NOTDEFAULTICON: %lX",
                _wpQueryCoreRecord(somSelf)->hptrIcon,
                _wpQueryStyle(somSelf) & OBJSTYLE_NOTDEFAULTICON));
    }

    if (!pwpRestoreState)
#endif
        brc = XFldDataFile_parent_WPDataFile_wpRestoreState(somSelf,
                                                            ulReserved);

    return brc;
}

/*
 *@@ wpQueryIcon:
 *      this WPObject instance method returns the HPOINTER
 *      with the current icon of the object. For some WPS
 *      classes, icon loading is deferred until the first
 *      call to this method.
 *      See icons.c for an introduction.
 *
 *      With data files and all subclasses, this turns out
 *      to be a major mess. When being made awake, all
 *      data files initially receive a NULLHANDLE pointer.
 *      In WPDataFile::wpRestoreState, the WPS checks if
 *      the file-system data has an .ICON EA so this can
 *      be quickly set.
 *      Only in that case will the icon already be set
 *      when wpQueryIcon is called for the first time.
 *
 *      So I guess what is done here is the following:
 *
 *      --  If the icon has already been set (either in
 *          wpRestoreState or by a previous call to
 *          wpQueryIcon), return it.
 *
 *      --  If not, call wpSetIcon with the return value
 *          from wpQueryAssociatedProgram or, if no association
 *          exists, from wpclsQueryIcon of the file's class.
 *          Then return that new icon.
 *
 *          With V0.9.20, lazy icon loading was introduced.
 *          If enabled, in this case, we pass the object to
 *          the "lazy icons" thread to defer icon loading and
 *          only set a temporary default icon here.
 *
 *      Unfortunately the WPS always sets OBJSTYLE_NOTDEFAULTICON
 *      in here, which is not a good idea with our replacement
 *      associations.
 *
 *      Remarks for WPProgramFile:
 *
 *      --  WPProgramFile apparently overrides this method
 *          to call wpSetProgIcon directly. It also overrides
 *          wpSetAssociatedFileIcon to call wpSetProgIcon.
 *
 *      --  We thus "only" have to override XWPProgramFile::wpSetProgIcon
 *          to replace the executable icons. However, with V0.9.20
 *          we override XWPProgramFile::wpQueryIcon also to
 *          support lazy icons there too.
 *
 *      --  Since WPCommandFile is derived from WPProgramFile,
 *          this affects command files as well.
 *
 *      What a mess.
 *
 *@@added V0.9.16 (2001-12-08) [umoeller]
 */

SOM_Scope HPOINTER  SOMLINK xdf_wpQueryIcon(XFldDataFile *somSelf)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpQueryIcon");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        HPOINTER hptrReturn = NULLHANDLE;
        PMINIRECORDCORE prec = _wpQueryCoreRecord(somSelf);

        PMPF_ICONREPLACEMENTS(("obj 0x%lX: prec->hptrIcon is 0x%lX", somSelf, prec->hptrIcon));

        TRY_LOUD(excpt1)
        {
            // do we have an icon yet?
            // this is set if either
            // -- the icon was already set from an .ICON EA in wpRestoreState or
            // -- this is not the first call to wpQueryIcon
            if (!(hptrReturn = prec->hptrIcon))
            {
                ULONG flNewStyle = 0;
                XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
                // first call, and icon wasn't set in wpRestoreState:
                // be smart now...

                // 1) if we're an icon or pointer file, load
                //    the icon from there
                if (_fIsIconOrPointer)
                {
                    CHAR szFilename[CCHMAXPATH];
                    _wpQueryFilename(somSelf, szFilename, TRUE);
                    if (!icoLoadICOFile(szFilename,
                                        &hptrReturn,
                                        NULL,
                                        NULL))
                        flNewStyle = OBJSTYLE_NOTDEFAULTICON;
                }

                // no need to do special checks for WPProgramFile
                // because it overrides wpQueryIcon to call wpSetProgIcon
                // instead

                if (    (!hptrReturn)
                     && (!(hptrReturn = _wpQueryAssociatedFileIcon(somSelf)))
                                 // this makes the icon global,
                                 // but does not set the icon or the
                                 // NOTDEFAULTICON flag
                   )
                    // no association found:
                    hptrReturn = _wpclsQueryIcon(_somGetClass(somSelf));

                _wpSetIconHandle(somSelf, hptrReturn);
                _wpSetIcon(somSelf, hptrReturn);
                _wpModifyStyle(somSelf,
                               OBJSTYLE_NOTDEFAULTICON,
                               flNewStyle);
            }
        }
        CATCH(excpt1)
        {
        } END_CATCH();

        return hptrReturn;
    }

#endif

    return XFldDataFile_parent_WPDataFile_wpQueryIcon(somSelf);
}

/*
 *@@ wpQueryIconData:
 *      this WPObject instance method can be called to find out the
 *      object's icon data.
 *
 *      See XWPProgramFile::wpQueryIconData for more information.
 *
 *      We need to override this too to fully support our replacement
 *      extended association icons in the WPS. Up to V0.9.18, the "Icon"
 *      notebook page was severly broken for data files.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xdf_wpQueryIconData(XFldDataFile *somSelf,
                                             PICONINFO pIconInfo)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpQueryIconData");

#ifndef __NOTURBOFOLDERS__
    // turbo folders enabled?
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        ULONG           cbRequired = sizeof(ICONINFO);

        TRY_LOUD(excpt1)
        {
            BOOL            fFound = FALSE;
            CHAR            szFilename[CCHMAXPATH];

            // FIRST of all, check if we have a non-default icon
            // from an .ICON EA... if so, this overrides anything else
            if (_wpQueryFilename(somSelf, szFilename, TRUE))
                if (!icoBuildPtrFromEAs(szFilename,
                                        NULL,              // no HPOINTER
                                        &cbRequired,
                                        pIconInfo))        // can be NULL
                        // returns NO_ERROR only if we have an .ICON EA
                    fFound = TRUE;

            if (!fFound)
            {
                // .ICON EA not found, or bad data:
                XFldDataFileData *somThis = XFldDataFileGetData(somSelf);

                // if we're an icon or pointer file, support
                // ICON_DATA format for compatibility
                if (_fIsIconOrPointer)
                {
                    PBYTE pbData = NULL;
                    ULONG cbData;
                    if (pIconInfo)
                        pbData = (PBYTE)(pIconInfo + 1);

                    if (!icoLoadICOFile(szFilename,
                                        NULL,
                                        &cbData,
                                        pbData))     // can be NULL
                    {
                        cbRequired += cbData;

                        if (pIconInfo)
                        {
                            ZERO(pIconInfo);
                            pIconInfo->cb = cbRequired;
                            pIconInfo->fFormat = ICON_DATA;
                            pIconInfo->cbIconData = cbData;
                            pIconInfo->pIconData = pbData;
                        }

                        fFound = TRUE;
                    }
                }

                if (!fFound)
                {
                    // not icon file, or format not supported:
                    // check if we have an association
                    ULONG ulView = _wpQueryDefaultView(somSelf);
                                // should return 0x1000 unless the user
                                // has changed the data file's default view
                    WPObject *pobjAssoc = ftypQueryAssociatedProgram(somSelf,
                                                                     &ulView,
                                                                     // do not use "plain text" as default,
                                                                     // this affects the icon:
                                                                     FALSE);
                                            // locks the object

                    if (pobjAssoc)
                    {
                        // call the assoc object's wpQueryIconData
                        cbRequired = _wpQueryIconData(pobjAssoc,
                                                      pIconInfo);

                        _wpUnlockObject(pobjAssoc);
                    }
                    else
                    {
                        // no assoc object:
                        // use class default
                        cbRequired = _wpclsQueryIconData(_somGetClass(somSelf),
                                                         pIconInfo);
                    }
                }
            }
        }
        CATCH(excpt1)
        {
            cbRequired = 0;
        } END_CATCH();

        return cbRequired;
    }
#endif

    return XFldDataFile_parent_WPDataFile_wpQueryIconData(somSelf,
                                                          pIconInfo);
}

/*
 *@@ wpSetIconData:
 *      this WPObject method sets a new persistent icon for
 *      the object and stores the new icon permanently.
 *
 *      We need to override this for our icon replacements
 *      because the WPS will do evil things to our standard
 *      icons again.
 *
 *      Note that we only handle the ICON_CLEAR case here
 *      to reload the exe default icon. The other cases
 *      are handled by our XWPFileSystem::wpSetIconData
 *      override.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 *@@changed V1.0.0 (2002-09-12) [umoeller]: fixed missing _fHasIconEA adjustment
 */

SOM_Scope BOOL  SOMLINK xdf_wpSetIconData(XFldDataFile *somSelf,
                                          PICONINFO pIconInfo)
{
    CHAR        szFilename[CCHMAXPATH];
    BOOL        fExt;

    XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpSetIconData");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        if (    (pIconInfo)
             && (pIconInfo->fFormat == ICON_CLEAR)
             && (_wpQueryFilename(somSelf, szFilename, TRUE))
           )
        {
            // this case is now overridden by XFldDataFile
            // and XWPProgramFile
            if (WinSetFileIcon(szFilename, pIconInfo))
            {
                // clear private flag so that
                // _wpSetAssociatedFileIcon works
                _fHasIconEA = FALSE;
                // use default assoc icon
                _wpSetAssociatedFileIcon(somSelf);
                return TRUE;
            }
        }
    }
#endif

    // all other cases, or icon replacements disabled:
    // call parent, which will end up in XWPFileSystem
    // (WPProgramFile doesn't override this)
    if (XFldDataFile_parent_WPDataFile_wpSetIconData(somSelf,
                                                     pIconInfo))
    {
        // success:
        if (    (pIconInfo)
             && (pIconInfo->fFormat != ICON_CLEAR)
           )
            _fHasIconEA = TRUE;     // V1.0.0 (2002-09-12) [umoeller]

        return TRUE;
    }

    return FALSE;
}

/*
 *@@ wpQueryAssociatedProgram:
 *      this method returns the associated WPProgram or
 *      WPProgramFile object for the specified view ID of
 *      a data file.
 *
 *      The WPS docs say that this should be overridden
 *      to introduce new association mechanisms.
 *
 *      Yeah, right. Per default, this gets called from
 *      XFldDataFile::wpQueryAssociatedFileIcon -- that
 *      is, only while a folder is being populated, but
 *      _not_ when a context menu is opened. There seems
 *      to be a second association mechanism in wpModifyPopupMenu
 *      somewhere to add all the associated programs to
 *      the "Open" submenu. I have tested this by returning
 *      NULL in this method, and all the program objects
 *      still appear in the "Open" menu -- it's just the
 *      data file icons which get set to the default icon
 *      then.
 *
 *      Soooo... to give the data files new icons, we need
 *      to override this method since it gets called from
 *      wpQueryAssociatedFileIcon (which normally gets called
 *      during folder populate).
 *
 *      See XFldDataFile::wpQueryIcon for an introduction
 *      to the data file icon mess.
 *
 *      From what I see, ulView is normally 0x1000, which
 *      is the WPS-internal code for the first associated
 *      program. This is only > 1000 if the default
 *      association has been changed on the "Menu" page
 *      of a data file (1001 for the second assoc, 1002
 *      for the third, etc.).
 *
 *      However, this also needs to support OPEN_RUNNING
 *      and OPEN_DEFAULT.
 *
 *      This returns NULL if there's no associated program
 *      for the specified view. Otherwise it returns a
 *      WPProgram or WPProgramFile, which has been locked
 *      once.
 *
 *      The caller should unlock the object after it's
 *      done using it. AFAIK, WPS wpQueryAssociatedFileIcon
 *      does this.
 *
 *@@added V0.9.0 [umoeller]
 */

SOM_Scope WPObject*  SOMLINK xdf_wpQueryAssociatedProgram(XFldDataFile *somSelf,
                                                          ULONG ulView,
                                                          PULONG pulHowMatched,
                                                          PSZ pszMatchString,
                                                          ULONG cbMatchString,
                                                          PSZ pszDefaultType)
{
    WPObject* pobj = 0;

    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    // XFldDataFileMethodDebug("XFldDataFile","xdf_wpQueryAssociatedProgram");

    PMPF_ASSOCS(("Entering wpQueryAssociatedProgram for %s; ulView = %lX, "
               "*pulHowMatched = 0x%lX, "
               "pszMatchString = %s, pszDefaultType = %s",
               _wpQueryTitle(somSelf),
               ulView,
               (    (pulHowMatched)
                            ? (*pulHowMatched)
                            : 0
               ),
               pszMatchString, pszDefaultType
               ));

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        // "extended associations" allowed:
        // use our replacement mechanism...
        // this does NOT use "plain text" as the default
        ULONG   ulView2 = ulView;
        pobj = ftypQueryAssociatedProgram(somSelf,
                                          &ulView2,
                                          // do not use "plain text" as default,
                                          // this affects the icon:
                                          FALSE);
                        // locks the object
    }
    else
#endif
        pobj = XFldDataFile_parent_WPDataFile_wpQueryAssociatedProgram(somSelf,
                                                                       ulView,
                                                                       pulHowMatched,
                                                                       pszMatchString,
                                                                       cbMatchString,
                                                                       pszDefaultType);

    PMPF_ASSOCS(("End of wpQueryAssociatedProgram for %s", _wpQueryTitle(somSelf)));

    return pobj;
}

/*
 *@@ wpQueryAssociatedFileIcon:
 *      this WPDataFile method should return the icon of
 *      the program that the data file is associated with
 *      or NULLHANDLE if we can't find an association.
 *
 *      This gets called on the first call to wpQueryIcon,
 *      even if turbo folders are not enabled.
 *
 *      See XFldDataFile::wpQueryIcon for an introduction
 *      to the data file icon mess.
 *
 *      We override this for speed to call
 *      ftypQueryAssociatedProgram directly.
 *
 *@@added V0.9.16 (2002-01-26) [umoeller]
 *@@changed V0.9.18 (2002-02-06) [umoeller]: fixed broken icons in PMMail
 *@@changed V0.9.20 (2002-07-25) [umoeller]: now using XFldObject::xwpShareIcon
 */

SOM_Scope HPOINTER  SOMLINK xdf_wpQueryAssociatedFileIcon(XFldDataFile *somSelf)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpQueryAssociatedFileIcon");

    PMPF_ASSOCS(("[%s] entering",
            _wpQueryTitle(somSelf)));

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        HPOINTER hptr = NULLHANDLE;

        TRY_LOUD(excpt1)
        {
            ULONG ulView = _wpQueryDefaultView(somSelf);
                        // should return 0x1000 unless the user
                        // has changed the data file's default view

            WPObject *pobjAssoc;

            PMPF_ASSOCS(("   getting associated program for default view 0x%lX", ulView));

            if (pobjAssoc = ftypQueryAssociatedProgram(somSelf,
                                                       &ulView,
                                                       // do not use "plain text" as default,
                                                       // this affects the icon:
                                                       FALSE))
                    // locks the object
            {
                PMPF_ASSOCS(("   got associated program [%s]", _wpQueryTitle(pobjAssoc)));

                // get the assoc icon
                // V0.9.20 (2002-07-25) [umoeller]
                // now using the new icon sharing mechanism!
                hptr = icomShareIcon(pobjAssoc,
                                     somSelf,
                                     TRUE);         // make global

                // we have locked the object twice now (once in
                // ftypQueryAssociatedProgram, once in icomShareIcon),
                // so unlock once now
                _wpUnlockObject(pobjAssoc);
            }
        }
        CATCH(excpt1)
        {
        } END_CATCH();

        PMPF_ASSOCS(("done, returning 0x%lX",
                     hptr));

        return hptr;      // NULLHANDLE still for "plain text"
    }
#endif

    return XFldDataFile_parent_WPDataFile_wpQueryAssociatedFileIcon(somSelf);
}

/*
 *@@ wpSetAssociatedFileIcon:
 *      this method gets called by the WPS when a data
 *      file object is being initialized, to have it
 *      set its icon to that of the default association.
 *
 *      This gets called from various places in the WPS
 *      whenever data file attributes change so that
 *      the association might have changed. Note that
 *      WPDataFile::wpQueryIcon does _not_ call this,
 *      but wpQueryAssociatedFileIcon instead.
 *
 *      The problem with this method is that it appears
 *      to check internally for the OBJSTYLE_NOTDEFAULTICON
 *      flag, which is rarely set any more since we
 *      share the association icons with the executables.
 *
 *      Since WPProgramFile overrides this method (but not
 *      wpQueryAssociatedFileIcon), this never gets called
 *      for program files.
 *
 *      See XFldDataFile::wpQueryIcon for an introduction
 *      to the data file icon mess.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

SOM_Scope void  SOMLINK xdf_wpSetAssociatedFileIcon(XFldDataFile *somSelf)
{
    XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpSetAssociatedFileIcon");

#ifndef __NOTURBOFOLDERS__
    // only call the parent if we don't have an .ICON EA,
    // otherwise do nothing
    // V0.9.18 (2002-03-19) [umoeller]
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        if (!_fHasIconEA)
        {
            // for WPIcon and WPPointer, we want no association icons
            // (_wpQueryIcon loads the icon then)
            if (!_fIsIconOrPointer)
            {
                HPOINTER hptr;

                if (!(hptr = _wpQueryAssociatedFileIcon(somSelf)))
                    // use class icon then
                    hptr = _wpclsQueryIcon(_somGetClass(somSelf));

                if (hptr)
                {
                    _wpSetIcon(somSelf, hptr);

                    // make sure this is turned off!!!
                    _wpModifyStyle(somSelf,
                                   OBJSTYLE_NOTDEFAULTICON,
                                   0);
                }
            }

            return;
        }
    }
#endif

    XFldDataFile_parent_WPDataFile_wpSetAssociatedFileIcon(somSelf);
}

/*
 *@@ wpFilterPopupMenu:
 *      this WPObject instance method allows the object to
 *      filter out unwanted menu items from the context menu.
 *      This gets called before wpModifyPopupMenu.
 *
 *      We remove default entries according to Global Settings;
 *      even though XFldObject does this already, we need to
 *      override this for XFldDataFile again, because the
 *      WPS does it too for WPDataFile.
 *
 *      Also we need to do some fiddling with the "Open"
 *      submenu for the extended associations mechanism.
 *
 *@@changed V0.9.19 (2002-04-17) [umoeller]: adjusted for new menu handling
 */

SOM_Scope ULONG  SOMLINK xdf_wpFilterPopupMenu(XFldDataFile *somSelf,
                                               ULONG ulFlags,
                                               HWND hwndCnr,
                                               BOOL fMultiSelect)
{
    ULONG ulMenuFilter = 0;
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpFilterPopupMenu");

    ulMenuFilter = XFldDataFile_parent_WPDataFile_wpFilterPopupMenu(somSelf,
                                                                    ulFlags,
                                                                    hwndCnr,
                                                                    fMultiSelect);

    PMPF_MENUS(("flags %08X, parent flags: %08X, ", ulFlags, ulMenuFilter));
    // now suppress default menu items according to
    // Global Settings;
    // the DefaultMenuItems field in pGlobalSettings is
    // ready-made for this function; the "Workplace Shell"
    // notebook page for removing menu items sets this field with
    // the proper CTXT_xxx flags
    ulMenuFilter &= ~(cmnQuerySetting(mnuQueryMenuWPSSetting(somSelf)));

    return ulMenuFilter;
}

/*
 *@@ wpModifyMenu:
 *      this WPObject instance method was new with Warp 4 and
 *      allows the object to manipulate its menu in a more
 *      fine-grained way than wpModifyPopupMenu.
 *
 *      With V1.0.0, while adding support for the split view
 *      to the menu methods, I finally got tired of all the
 *      send-msg hacks to get Warp 4 menu items to work and
 *      decided to finally break Warp 3 support for XWorkplace.
 *      It's been fun while it lasted, but enough is enough.
 *      We are now overriding this method directly through
 *      the IDL files.
 *
 *      ulMenuType will be one of the following:
 *
 *      --  MENU_OBJECTPOPUP: Pop-up menu for the object icon.
 *          This can come in for any object.
 *
 *      --  MENU_OPENVIEWPOPUP: Pop-up menu for an open view.
 *          I think this can reasonably only come in for folders,
 *          although it seems to be handled by the WPObject method.
 *
 *      --  MENU_FOLDERPULLDOWN: Pull-down menu for a folder.
 *          This comes in for folders only.
 *
 *      --  MENU_EDITPULLDOWN: Pull-down menu for the Edit menu option.
 *          This comes in TWICE, first on the selected object in
 *          the view's container (if any) with ulView == CLOSED_ICON,
 *          and then a second time on the view's folder with ulView
 *          set to the folder's current view.
 *
 *      --  MENU_VIEWPULLDOWN: Pull-down menu for the View menu option.
 *          This comes in for folders only.
 *
 *      --  MENU_SELECTEDPULLDOWN: Pull-down menu for the Selected menu option.
 *          This comes in for non-folder objects also to let the object
 *          decide what options it wants to present in the folder's
 *          "Selected" pulldown.
 *
 *      --  MENU_HELPPULLDOWN: Pull-down menu for the Help menu option.
 *          This comes in for folders only.
 *
 *      --  MENU_TITLEBARPULLDOWN: this is listed in the toolkit headers,
 *          but not described in WPSREF. I think this is what comes in
 *          if the system menu is being built for an open object view.
 *
 *@@added V1.0.0 (2002-08-31) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xdf_wpModifyMenu(XFldDataFile *somSelf,
                                         HWND hwndMenu,
                                         HWND hwndCnr,
                                         ULONG iPosition,
                                         ULONG ulMenuType,
                                         ULONG ulView,
                                         ULONG ulReserved)
{
    BOOL    brc;

    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpModifyMenu");

    if (brc = XFldDataFile_parent_WPDataFile_wpModifyMenu(somSelf,
                                                          hwndMenu,
                                                          hwndCnr,
                                                          iPosition,
                                                          ulMenuType,
                                                          ulView,
                                                          ulReserved))
    {
        PMPF_MENUS(("[%s]",
                    _wpQueryTitle(somSelf)));
        PMPF_MENUS(("   type = 0x%lX (%s), view = 0x%lX (%s)",
                    ulMenuType,
                    (ulMenuType == MENU_OBJECTPOPUP) ? "MENU_OBJECTPOPUP"
                    : (ulMenuType == MENU_OPENVIEWPOPUP) ? "MENU_OPENVIEWPOPUP"
                    : (ulMenuType == MENU_TITLEBARPULLDOWN) ? "MENU_TITLEBARPULLDOWN"
                    : (ulMenuType == MENU_TITLEBARPULLDOWNINT) ? "MENU_TITLEBARPULLDOWNINT"
                    : (ulMenuType == MENU_FOLDERPULLDOWN) ? "MENU_FOLDERPULLDOWN"
                    : (ulMenuType == MENU_VIEWPULLDOWN) ? "MENU_VIEWPULLDOWN"
                    : (ulMenuType == MENU_HELPPULLDOWN) ? "MENU_HELPPULLDOWN"
                    : (ulMenuType == MENU_EDITPULLDOWN) ? "MENU_EDITPULLDOWN"
                    : (ulMenuType == MENU_SELECTEDPULLDOWN) ? "MENU_SELECTEDPULLDOWN"
                    : (ulMenuType == MENU_FOLDERMENUBAR) ? "MENU_FOLDERMENUBAR"
                    : (ulMenuType == MENU_USER) ? "MENU_USER"
                    : "unknown",
                    ulView,
                    mnuQueryViewName(ulView)
                    ));

        // now check which type of menu we have
        switch (ulMenuType)
        {
            case MENU_OPENVIEWPOPUP:
            case MENU_TITLEBARPULLDOWN:
            case MENU_OBJECTPOPUP:
            case MENU_SELECTEDPULLDOWN:

                mnuModifyDataFilePopupMenu(somSelf,
                                           hwndMenu,
                                           hwndCnr);

#ifndef __NOTURBOFOLDERS__
                if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
                {
                    // extended assocs have been enabled:
                    // this means we need to manually tweak some of the data file
                    // settings, as WPDataFile would normally do it...
                    MENUITEM        mi;

                    // find "Open" submenu
                    if (WinSendMsg(hwndMenu,
                                   MM_QUERYITEM,
                                   MPFROM2SHORT(WPMENUID_OPEN, TRUE),
                                   (MPARAM)&mi))
                    {
                        // found:

                        // check for program files hack
                        LONG    lDefaultView = _wpQueryDefaultView(somSelf);

                        if (    (lDefaultView == OPEN_RUNNING)
                             && (!progIsProgramOrProgramFile(somSelf))
                           )
                        {
                            // this is not a program file,
                            // but this doesn't have its default view set yet:
                            // set it then
                            _wpSetDefaultView(somSelf, 0x1000);
                            lDefaultView = 0x1000;
                        }
                        // but skip program files with OPEN_RUNNING

                        ftypModifyDataFileOpenSubmenu(somSelf,
                                                      mi.hwndSubMenu,
                                                      TRUE);        // delete existing
                    }
                }
#endif
            break;
        }

        fdrAddHotkeysToMenu(somSelf,
                            hwndCnr,
                            hwndMenu,
                            ulMenuType);
    }

    return brc;
}

/*
 *@@ wpMenuItemSelected:
 *      this handles the 'File attributes' and 'Copy filename'
 *      menuitems under special circumstances:  when this object
 *      has not been inserted into a container controlled by
 *      XWP.  See fcmdSpecialMenuItemSelected in fdrcommand.c
 *      for additional details.
 *
 *      All other items on a datafile's menu are either handled
 *      directly by XWP without invoking this method, or are
 *      passed on to the parent class for default handling.
 *
 *@@added V1.0.9 (2011-09-18) [rwalsh]
 */

SOM_Scope BOOL  SOMLINK xdf_wpMenuItemSelected(XFldDataFile *somSelf,
                                               HWND hwndFrame,
                                               ULONG ulMenuId)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpMenuItemSelected");

    // call the special handler - returns TRUE if it handled the command
    if (fcmdSpecialMenuItemSelected(somSelf, hwndFrame, ulMenuId))
        return TRUE;

    // else: not one of our menu items, call default
    return XFldDataFile_parent_WPDataFile_wpMenuItemSelected(somSelf,
                                                             hwndFrame,
                                                             ulMenuId);
}

/*
 *@@ wpMenuItemHelpSelected:
 *      display help for a context menu item.
 */

SOM_Scope BOOL  SOMLINK xdf_wpMenuItemHelpSelected(XFldDataFile *somSelf,
                                                   ULONG MenuId)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpMenuItemHelpSelected");

    // call the common help processor in fdrmenus.c;
    if (fcmdMenuItemHelpSelected(somSelf, MenuId))
        // if this returns TRUE, help was requested for one
        // of the new menu items
        return TRUE;

    // else: none of our menu items, call default
    return XFldDataFile_parent_WPDataFile_wpMenuItemHelpSelected(somSelf,
                                                                 MenuId);
}

/*
 *@@ wpOpen:
 *      this WPObject instance method gets called when
 *      a new view needs to be opened. Normally, this
 *      gets called after wpViewObject has scanned the
 *      object's USEITEMs and has determined that a new
 *      view is needed.
 *
 *      This _normally_ runs on thread 1 of the WPS, but
 *      this is not always the case. If this gets called
 *      in response to a menu selection from the "Open"
 *      submenu or a double-click in the folder, this runs
 *      on the thread of the folder (which _normally_ is
 *      thread 1). However, if this results from WinOpenObject
 *      or an OPEN setup string, this will not be on thread 1.
 *
 *      Of course, for data files, the "views" are the
 *      various associations in the "Open" submenu, which
 *      have ulView IDs >= 0x1000. If the default view
 *      has been manually set for the object, wpOpen
 *      always receives this ID.
 *
 *      By contrast, we can also get OPEN_RUNNING or
 *      OPEN_DEFAULT. I think OPEN_RUNNING comes in
 *      for "standard" data files which have been
 *      double-clicked on.
 *
 *      There are two more problems with starting the
 *      associated program (damn it, IBM, do you ever
 *      read the specs that you've written yourself?):
 *
 *      --  The WPS always uses its internal list of
 *          associations, no matter what we return from
 *          XFldDataFile::wpQueryAssociatedProgram, so
 *          we need to override this method as well and
 *          intercept the new menu items that we have changed.
 *
 *      --  We cannot use the WPProgram/WPProgramFile classes
 *          to start the associated programs. These things do
 *          not accept parameters, and of course there's no
 *          export for resolving all the parameter placeholders.
 *          So we need to start the program ourselves with
 *          the data file as the parameter, using progOpenProgram.
 *
 *@@added V0.9.6 (2000-10-16) [umoeller]
 *@@changed V1.0.5 (2006-05-14) [pr]: Call parent if Ext. Assocs. enabled and no. assoc. found @@fixes 14
 */

SOM_Scope HWND  SOMLINK xdf_wpOpen(XFldDataFile *somSelf,
                                   HWND hwndCnr,
                                   ULONG ulView,
                                   ULONG param)
{
    HWND        hwnd = NULLHANDLE;
    BOOL        fCallParent = TRUE;
    ULONG       ulView2 = ulView;
    WPObject    *pAssocObject;
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpOpen");

    PMPF_ASSOCS(("[%s] entering, ulView: 0x%lX", _wpQueryTitle(somSelf), ulView));

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        // "extended associations" allowed:
        if (    ((ulView >= 0x1000) && (ulView < 0x1100))
             || (ulView == OPEN_RUNNING)    // double-click on data file... what's this, IBM?
             || (ulView == OPEN_DEFAULT)
           )
            // use our replacement mechanism
            fCallParent = FALSE;
    }

    // V1.0.5 (2006-05-14) [pr]: Rejigged this to call the parent if no assoc. found
    if (!fCallParent)
    {
        // replacement desired:
        pAssocObject = ftypQueryAssociatedProgram(somSelf,
                                                  &ulView2,
                                                  // use "plain text" as default:
                                                  TRUE);
                                                     // we've used "plain text" as default
                                                     // in wpModifyMenu, so we need to do
                                                     // the same again here
                            // object is locked

        if (!pAssocObject)
            fCallParent = TRUE;
    }

    if (!fCallParent)
    {
        CHAR szFailing[CCHMAXPATH];
        APIRET arc;

        if (arc = progOpenProgram(pAssocObject,
                                  somSelf,
                                  ulView2,
                                  &hwnd,
                                  sizeof(szFailing),
                                  szFailing))
        {
            if (cmnProgramErrorMsgBox(NULLHANDLE,
                                      pAssocObject,
                                      szFailing,
                                      arc)
                        == MBID_YES)
                krnPostThread1ObjectMsg(T1M_OPENOBJECTFROMPTR,
                                        (MPARAM)pAssocObject,
                                        (MPARAM)OPEN_SETTINGS);
        }
                // _wpUnlockObject(pAssocObject);
                // do not unlock the assoc object...
                // this is still needed in the use list!!!
    }
    else
#endif
        hwnd = XFldDataFile_parent_WPDataFile_wpOpen(somSelf,
                                                     hwndCnr,
                                                     ulView,
                                                     param);

    PMPF_ASSOCS(("[%s] returning hwnd 0x%lX", _wpQueryTitle(somSelf), hwnd));

    return hwnd;

}

/*
 *@@ wpAddFile1Page:
 *      this WPFileSystem method normally adds the first
 *      "File" page to the file's settings notebook; since we
 *      combine the three "File" pages into one,
 *      we'll remove this page, if allowed.
 *
 *      We cannot override this in XWPFileSystem because
 *      WPFolder overrides this too.
 *
 *@@added V0.9.0
 */

SOM_Scope ULONG  SOMLINK xdf_wpAddFile1Page(XFldDataFile *somSelf,
                                            HWND hwndNotebook)
{
    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpAddFile1Page");

#ifndef __ALWAYSREPLACEFILEPAGE__
    if (cmnQuerySetting(sfReplaceFilePage))
    {
#endif
        return fsysInsertFilePages(somSelf,
                                   hwndNotebook);
#ifndef __ALWAYSREPLACEFILEPAGE__
    }

    return XFldDataFile_parent_WPDataFile_wpAddFile1Page(somSelf,
                                                         hwndNotebook);
#endif
}

/*
 *@@ wpAddFile2Page:
 *      this WPFileSystem method normally adds the second
 *      "File" page to the file's settings notebook; since we
 *      combine the three "File" pages into one,
 *      we'll remove this page, if allowed.
 *
 *      We cannot override this in XWPFileSystem because
 *      WPFolder overrides this too.
 *
 *@@added V0.9.0
 */

SOM_Scope ULONG  SOMLINK xdf_wpAddFile2Page(XFldDataFile *somSelf,
                                            HWND hwndNotebook)
{
    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpAddFile2Page");

#ifndef __ALWAYSREPLACEFILEPAGE__
    if (cmnQuerySetting(sfReplaceFilePage))
#endif
        return SETTINGS_PAGE_REMOVED;

#ifndef __ALWAYSREPLACEFILEPAGE__
    return XFldDataFile_parent_WPDataFile_wpAddFile2Page(somSelf,
                                                         hwndNotebook);
#endif
}

/*
 *@@ wpAddFile3Page:
 *      this WPFileSystem method normally adds the third
 *      "File" page to the file's settings notebook; since we
 *      combine the three "File" pages into one,
 *      we'll remove this page, if allowed.
 *
 *      We cannot override this in XWPFileSystem because
 *      WPFolder overrides this too.
 *
 *@@added V0.9.0
 */

SOM_Scope ULONG  SOMLINK xdf_wpAddFile3Page(XFldDataFile *somSelf,
                                            HWND hwndNotebook)
{
    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpAddFile3Page");

#ifndef __ALWAYSREPLACEFILEPAGE__
    if (cmnQuerySetting(sfReplaceFilePage))
#endif
        return SETTINGS_PAGE_REMOVED;

#ifndef __ALWAYSREPLACEFILEPAGE__
    return XFldDataFile_parent_WPDataFile_wpAddFile3Page(somSelf,
                                                         hwndNotebook);
#endif
}

/*
 *@@ wpAddFileTypePage:
 *      this WPDataFile method normally adds the "Type"
 *      page to a data file's settings notebook.
 *
 *      If extended associations are enabled, we replace
 *      this with our own version to allow the user to
 *      view the automatic and explicit types separately.
 *
 *@@added V0.9.9 (2001-03-27) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xdf_wpAddFileTypePage(XFldDataFile *somSelf,
                                               HWND hwndNotebook)
{
    /* XFldDataFileData *somThis = XFldDataFileGetData(somSelf); */
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpAddFileTypePage");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        INSERTNOTEBOOKPAGE inbp;
        memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
        inbp.somSelf = somSelf;
        inbp.hwndNotebook = hwndNotebook;
        inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
        inbp.ulDlgID = ID_XSD_DATAF_TYPES;
        inbp.ulPageID = SP_DATAFILE_TYPES;
        inbp.pampControlFlags = G_pampDatafileTypesPage;
        inbp.cControlFlags = G_cDatafileTypesPage;
        inbp.usPageStyleFlags = BKA_MAJOR;
        inbp.pcszName = cmnGetString(ID_XSSI_FILETYPESPAGE);  // pszFileTypesPage
        inbp.ulDefaultHelpPanel  = ID_XSH_DATAFILE_TYPES;
        inbp.pfncbInitPage    = ftypDatafileTypesInitPage;
        inbp.pfncbItemChanged = ftypDatafileTypesItemChanged;

        return ntbInsertPage(&inbp);
    }
#endif

    return XFldDataFile_parent_WPDataFile_wpAddFileTypePage(somSelf,
                                                            hwndNotebook);
}

/*
 *@@ wpSetRealName:
 *      this WPFileSystem instance method sets the real name
 *      for the object.
 *
 *      This code normally only gets called by WPS-internal
 *      implementations to update the internal representation
 *      of the file. When this gets called, the file has
 *      already been renamed on disk, I think.
 *
 *      See XWPFileSystem::wpSetRealName for details.
 *
 *      We might need to update the associated file icon
 *      here, which previously didn't work.
 *
 *@@added V0.9.19 (2002-04-17) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xdf_wpSetRealName(XFldDataFile *somSelf,
                                          PSZ pszName)
{
    BOOL brc;
    PMINIRECORDCORE prec;

    XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpSetRealName");

    if (brc = XFldDataFile_parent_WPDataFile_wpSetRealName(somSelf,
                                                           pszName))
#ifndef __NOTURBOFOLDERS__
        if (    (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
             && (prec = _wpQueryCoreRecord(somSelf))
             && (prec->hptrIcon)
             // avoid this if we have an .ICON EA
             && (!_fHasIconEA)
           )
            _wpSetAssociatedFileIcon(somSelf)
#endif
        ;

    return brc;
}

/*
 *@@ wpCreateFromTemplate:
 *      this WPObject method creates a new object from
 *      somSelf, which is assumed to be a template.
 *
 *      The WPFileSystem override of this kills our
 *      shared icons, so this had to be rewritten as
 *      well for WPDataFile. Note that WPFolder still
 *      uses the original implementation so we do not
 *      have to bother with any subfolders here.
 *
 *@@added V0.9.18 (2002-03-24) [umoeller]
 */

SOM_Scope WPObject*  SOMLINK xdf_wpCreateFromTemplate(XFldDataFile *somSelf,
                                                      WPFolder* folder,
                                                      BOOL fLock)
{
    // XFldDataFileData *somThis = XFldDataFileGetData(somSelf);
    XFldDataFileMethodDebug("XFldDataFile","xdf_wpCreateFromTemplate");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))     // V1.0.1 (2002-12-14) [umoeller]
    {
        WPObject *pNew = NULL;

        // all this doesn't make sense if we aren't a template
        // in the first place
        if (_wpQueryStyle(somSelf) & OBJSTYLE_TEMPLATE)
        {
            // I can't get this to work any other way...
            // apparently, create from template is so full of
            // ugly hacks that this is the best way to do it
            if (pNew = _wpCopyObject(somSelf,
                                     folder,
                                     fLock))
            {
                _wpModifyStyle(pNew,
                               OBJSTYLE_TEMPLATE,
                               0);
            }
        }

        return pNew;
    }
#endif

    return XFldDataFile_parent_WPDataFile_wpCreateFromTemplate(somSelf,
                                                               folder,
                                                               fLock);
}

/* ******************************************************************
 *
 *   XFldDataFile class methods
 *
 ********************************************************************/

/*
 *@@ wpclsInitData:
 *      this WPObject class method gets called when a class
 *      is loaded by the WPS (probably from within a
 *      somFindClass call) and allows the class to initialize
 *      itself.
 *
 *      We also manually patch the class method table to
 *      override some WPDataFile methods that IBM didn't
 *      want us to see.
 *
 *@@changed V0.9.0 [umoeller]: added class object to KERNELGLOBALS
 *@@changed V0.9.6 (2000-10-16) [umoeller]: added method tables override
 */

SOM_Scope void  SOMLINK xdfM_wpclsInitData(M_XFldDataFile *somSelf)
{
    // M_XFldDataFileData *somThis = M_XFldDataFileGetData(somSelf);
    M_XFldDataFileMethodDebug("M_XFldDataFile","xdfM_wpclsInitData");

    M_XFldDataFile_parent_M_WPDataFile_wpclsInitData(somSelf);

    krnClassInitialized(G_pcszXFldDataFile);

    /*
     *  Manually patch method tables of this class...
     *
     */

#if 0       // V1.0.0 (2002-08-31) [umoeller]
    // this gets called for subclasses too, so patch
    // this only for the parent class...
    // descendant classes will inherit this anyway
    // if (somSelf == _XFldDataFile)
    {
        if (G_fIsWarp4)
        {
            // on Warp 4, override wpModifyMenu (Warp 4-specific method)
            wpshOverrideStaticMethod(somSelf, // _XFldDataFile,
                                     "wpModifyMenu",
                                     (somMethodPtr)xdf_wpModifyMenu);
        }
    }
#endif
}

/*
 *@@ wpclsCreateDefaultTemplates:
 *      this WPObject class method is called by the
 *      Templates folder to allow a class to
 *      create its default templates.
 *
 *      The default WPS behavior is to create new templates
 *      if the class default title is different from the
 *      existing templates.
 *
 *      Since we are replacing the class, we will have to
 *      suppress this in order not to crowd the Templates
 *      folder.
 */

SOM_Scope BOOL  SOMLINK xdfM_wpclsCreateDefaultTemplates(M_XFldDataFile *somSelf,
                                                         WPObject* Folder)
{
    // M_XFldDataFileData *somThis = M_XFldDataFileGetData(somSelf);
    M_XFldDataFileMethodDebug("M_XFldDataFile","xdfM_wpclsCreateDefaultTemplates");

    // we only override this class method if it is
    // being called for the _XFldDataFile class object itself.
    // If this is being called for a subclass, we use
    // the parent method, because we do not want to
    // break the default behavior for subclasses.
    // this is not working on Warp 3
    if (somSelf == _XFldDataFile)
        return TRUE;
        // means that the Templates folder should _not_ create templates
        // by itself; we pretend that we've done this

    return M_XFldDataFile_parent_M_WPDataFile_wpclsCreateDefaultTemplates(somSelf,
                                                                          Folder);

}

/*
 *@@ wpclsQueryTitle:
 *      this WPObject class method tells the WPS the clear
 *      name of a class, which is shown in the third column
 *      of a Details view and also used as the default title
 *      for new objects of a class.
 *
 *      We override the standard folder class name only if
 *      the user has enabled "fix class titles" in XWPSetup.
 *
 *@@added V0.9.12 (2001-05-22) [umoeller]
 */

SOM_Scope PSZ  SOMLINK xdfM_wpclsQueryTitle(M_XFldDataFile *somSelf)
{
    /* M_XFldDataFileData *somThis = M_XFldDataFileGetData(somSelf); */
    M_XFldDataFileMethodDebug("M_XFldDataFile","xdfM_wpclsQueryTitle");

#ifndef __ALWAYSFIXCLASSTITLES__
    if (!cmnQuerySetting(sfFixClassTitles))
        return M_XFldDataFile_parent_M_WPDataFile_wpclsQueryTitle(somSelf);
#endif

    return cmnGetString(ID_XSSI_CLASSTITLE_DATAFILE);
}

/*
 *@@ wpclsQueryDefaultHelp:
 *      this WPObject class method returns the default help
 *      panel for objects of this class. This gets called
 *      from WPObject::wpQueryDefaultHelp if no instance
 *      help settings (HELPLIBRARY, HELPPANEL) have been
 *      set for an individual object. It is thus recommended
 *      to override this method instead of the instance
 *      method to change the default help panel for a class
 *      in order not to break instance help settings (fixed
 *      with 0.9.20).
 *
 *      We replace the default data file help because,
 *      frankly, it sucks. The replacement was added
 *      with V0.9.16, but we rather have overridden the
 *      class method instead.
 *
 *@@added V0.9.19 (2002-04-17) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xdfM_wpclsQueryDefaultHelp(M_XFldDataFile *somSelf,
                                                   PULONG pHelpPanelId,
                                                   PSZ pszHelpLibrary)
{
    /* M_XFldDataFileData *somThis = M_XFldDataFileGetData(somSelf); */
    M_XFldDataFileMethodDebug("M_XFldDataFile","xdfM_wpclsQueryDefaultHelp");

    strcpy(pszHelpLibrary, cmnQueryHelpLibrary());
    *pHelpPanelId = ID_XSH_DATAFILE_MAIN;
    return TRUE;
}

/*
 *@@ wpclsQueryIconData:
 *      this WPObject class method must return information
 *      about how to build the default icon for objects
 *      of a class. This gets called from various other
 *      methods whenever a class default icon is needed;
 *      most importantly, M_WPObject::wpclsQueryIcon
 *      calls this to build a class default icon, which
 *      is then cached in the class's instance data.
 *      If a subclass wants to change a class default icon,
 *      it should always override _this_ method instead of
 *      wpclsQueryIcon.
 *
 *      Note that the default WPS implementation does not
 *      allow for specifying the ICON_FILE format here,
 *      which is why we have overridden
 *      M_XFldObject::wpclsQueryIcon too. This allows us
 *      to return icon _files_ for theming too. For details
 *      about the WPS's crappy icon management, refer to
 *      src\filesys\icons.c.
 *
 *      We give data files a new default icon, if icon
 *      replacements are enabled. Note that this only
 *      affects data files that have no associations.
 */

SOM_Scope ULONG  SOMLINK xdfM_wpclsQueryIconData(M_XFldDataFile *somSelf,
                                                 PICONINFO pIconInfo)
{
    // M_XFldDataFileData *somThis = M_XFldDataFileGetData(somSelf);
    M_XFldDataFileMethodDebug("M_XFldDataFile","xdfM_wpclsQueryIconData");

#ifndef __NOICONREPLACEMENTS__
    if (cmnQuerySetting(sfIconReplacements))
    {
        // now using cmnGetStandardIcon
        // V0.9.16 (2002-01-13) [umoeller]
        ULONG cb = 0;
        if (!cmnGetStandardIcon(STDICON_DATAFILE,
                                NULL,            // no hpointer
                                &cb,
                                pIconInfo))      // can be NULL
            return cb;

        return 0;
    }
#endif

    // icon replacements not allowed: call default
    return M_XFldDataFile_parent_M_WPDataFile_wpclsQueryIconData(somSelf,
                                                                 pIconInfo);
}

