home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: WPS_PM
/
WPS_PM.zip
/
xfld085s.zip
/
main
/
xfldr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-23
|
254KB
|
6,294 lines
/*
*@@sourcefile xfldr.c:
* This file contains the following major XFolder parts:
*
* -- XFolder class
* -- XFldStartup (startup folder) class
* -- XFldShutdown (shutdown folder) class
*
* Check the other files starting with xf* for the
* other XFolder classes.
*
* XFolder is probably the most complex class of this
* package. Not only are context menus manipulated, but
* open folder view windows are also subclassed to
* introduce additional functionality (fnwpSubclassedFolderFrame).
*
* Most of the code in this file is "responsive" in that
* it is only called upon invocation of folder SOM methods.
* However, this also hooks a lot of functionality into
* the WPS using the subclassed folder frame proc.
*
* The XFolder class must always be installed.
* Installation of XFldStartup and XFldShutdown is
* optional.
*
*@@somclass XFolder xf_
*@@somclass M_XFolder xfM_
*@@somclass XFldStartup xfstup_
*@@somclass M_XFldStartup xfstupM_
*@@somclass XFldShutdown xfshut_
*@@somclass M_XFldShutdown xfshutM_
*/
/*
* 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_xfldr_Source
#define SOM_Module_xfldr_Source
#endif
#define XFolder_Class_Source
#define M_XFolder_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_DOSFILEMGR
#define INCL_DOSMODULEMGR
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS // DosSleep, priorities, PIDs etc.
#define INCL_DOSSEMAPHORES // needed for xthreads.h
#define INCL_DOSEXCEPTIONS
#define INCL_DOSERRORS
#define INCL_DOSMISC // DosGetMessage etc.
#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR // WM_FORMATFRAME, SC_CLOSE etc.
#define INCL_WINSYS // presparams, WinQuerySysValue()
#define INCL_WININPUT // Focus, WM_BUTTON1DOWN, WM_CONTEXTMENU etc.
#define INCL_WINSHELLDATA // profile funcs
#define INCL_WINPROGRAMLIST // needed for WPProgram
#define INCL_WINTIMER
#define INCL_WINPOINTERS
#define INCL_WINERRORS
#define INCL_WINRECTANGLES // rcl functions
#define INCL_WINMESSAGEMGR // WinQueryMsgPos
#define INCL_WINDIALOGS
#define INCL_WINSTATICS
#define INCL_WINMENUS // needed for menus.h
#define INCL_WINENTRYFIELDS
#define INCL_WINBUTTONS
#define INCL_WINLISTBOXES
#define INCL_WINSTDCNR // needed for winh.h
#define INCL_WINSTDBOOK // notebooks
#define INCL_WINSTDFILE // file dialog
#define INCL_WINMLE // multi-line entry field
#define INCL_WINWORKPLACE
#define INCL_GPILOGCOLORTABLE
#define INCL_GPIPRIMITIVES
#include <os2.h>
// C library headers
#include <stdio.h> // needed for except.h
#include <setjmp.h> // needed for except.h
#include <assert.h> // needed for except.h
#pragma hdrstop // VAC++ keeps crashing otherwise
// headers in /helpers
#include "dosh.h" // Control Program helper routines
#include "winh.h" // PM helper routines
#include "gpih.h" // GPI helper routines
#include "eas.h" // extended attributes helper routines
#include "linklist.h" // linked list helper routines
#include "wphandle.h" // Henk Kelder's HOBJECT handling
// SOM headers which don't crash with prec. header files
#include "xfldr.ih"
// headers in /main
#include "dlgids.h" // all the IDs that are shared with NLS
#include "common.h" // the majestic XFolder include file
#include "cnrsort.h" // container sort comparison functions
#include "except.h" // XFolder exception handling
#include "menus.h" // common XFolder context menu logic
#include "module.h" // XFolder main DLL information
#include "notebook.h" // generic XFolder notebook handling
#include "sound.h" // declarations for SOUND.DLL
#include "statbars.h" // status bar translation logic
#include "xthreads.h" // XFolder threads; this includes threads.h
// other SOM headers
#include <wppgm.h> // WPProgram
#include <wprootf.h> // WPRootFolder
#include <wpshadow.h> // WPShadow
#include "xfobj.h"
#include "xfdesk.h"
#include "xfdisk.h"
#include "xwps.h" // XFolder pseudo SOM functions
/* ******************************************************************
* *
* Global variables *
* *
********************************************************************/
// roots of linked lists for favorite/quick-open folders
PCONTENTMENULISTITEM pcmliFavoriteFolders = NULL,
pcmliQuickOpenFolders = NULL;
// mutex semaphores for these lists
HMTX hmtxFavoriteFolders = NULLHANDLE,
hmtxQuickOpenFolders = NULLHANDLE;
CHAR szXFolderVersion[100];
// forward declarations
MRESULT EXPENTRY fnwpSupplObject(HWND hwndObject, ULONG msg, MPARAM mp1, MPARAM mp2);
// SORTBYICONPOS:
// structure for GetICONPOS
typedef struct _SORTBYICONPOS {
CHAR szRealName[CCHMAXPATH];
PBYTE pICONPOS;
USHORT usICONPOSSize;
} SORTBYICONPOS, *PSORTBYICONPOS;
/* ******************************************************************
* *
* Common routines used by several XFolder methods *
* *
********************************************************************/
/*
*@@ QuerySortFunc:
* this returns the sort comparison function for
* the specified sort criterion. See XFolder::xfSortViewOnce
* for details.
*/
PFN QuerySortFunc(USHORT usSort)
{
USHORT usSort2 = usSort;
if (usSort == SET_DEFAULT)
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
usSort2 = pGlobalSettings->DefaultSort;
}
switch (usSort2) {
case SV_TYPE: return ((PFN)fnCompareType);
case SV_CLASS: return ((PFN)fnCompareClass);
case SV_REALNAME: return ((PFN)fnCompareRealName);
case SV_SIZE: return ((PFN)fnCompareSize);
case SV_LASTWRITEDATE: return ((PFN)fnCompareLastWriteDate);
case SV_LASTACCESSDATE: return ((PFN)fnCompareLastAccessDate);
case SV_CREATIONDATE: return ((PFN)fnCompareCreationDate);
case SV_EXT: return ((PFN)fnCompareExt);
case SV_FOLDERSFIRST: return ((PFN)fnCompareFoldersFirst);
};
// default:
return ((PFN)fnCompareName);
}
/*
*@@ SetOneFrameWndTitle:
* this changes the window title of a given folder frame window
* to the full path of the folder; this method does NOT check
* the respective XFolder settings any more, so this has to be
* done by the caller.
*/
BOOL SetOneFrameWndTitle(XFolder *somSelf, HWND hwndFrame)
{
PSZ pFirstSlash, pSrchSlash, pNextSlash;
CHAR szTemp[CCHMAXPATH];
XFolderData *somThis = XFolderGetData(somSelf);
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
BOOL brc;
if ( (_bFullPath == 1)
|| ((_bFullPath == 2) && (pGlobalSettings->FullPath))
)
{
// settings allow full path in title for this folder:
// get real name (= full path), if allowed)
_wpQueryFilename(somSelf, szTemp, TRUE);
// now truncate path if it's longer than allowed by user
pFirstSlash = strchr(szTemp, '\\');
if ((pFirstSlash) && (pGlobalSettings->MaxPathChars > 10)) {
pSrchSlash = pFirstSlash+3;
while (strlen(szTemp) > pGlobalSettings->MaxPathChars) {
pNextSlash = strchr(pSrchSlash, '\\');
if (pNextSlash) {
strcpy(pFirstSlash+4, pNextSlash);
pFirstSlash[1] = '.';
pFirstSlash[2] = '.';
pFirstSlash[3] = '.';
pSrchSlash = pFirstSlash+5;
}
else break;
}
}
// now either append the full path in brackets to or replace window title
if (pGlobalSettings->KeepTitle) {
CHAR szFullPathTitle[CCHMAXPATH*2];
sprintf(szFullPathTitle, "%s (%s)",
_wpQueryTitle(somSelf),
szTemp);
WinSetWindowText(hwndFrame, szFullPathTitle);
}
else
WinSetWindowText(hwndFrame, szTemp);
brc = TRUE;
} else {
// settings DON'T allow full path in title for this folder:
// set to title only
WinSetWindowText(hwndFrame, _wpQueryTitle(somSelf));
brc = FALSE;
}
return (brc);
}
/* ******************************************************************
* *
* here come the XFolder instance methods *
* *
********************************************************************/
/*
*@@ xfUpdateAllFrameWndTitles:
* this method sets the frame wnd titles for all currently
* open views of a given folder to the full path;
* it is called on the Worker thread after XFolder's replacements
* of wpMoveObject, wpSetTitle, or wpRefresh have been called.
* It does check the respective Global / folder settings.
*/
SOM_Scope BOOL SOMLINK xf_xfUpdateAllFrameWndTitles(XFolder *somSelf)
{
HWND hwndFrame;
BOOL brc = FALSE;
if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_CONTENTS)) {
SetOneFrameWndTitle(somSelf, hwndFrame);
brc = TRUE;
}
if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_DETAILS)) {
SetOneFrameWndTitle(somSelf, hwndFrame);
brc = TRUE;
}
if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_TREE)) {
SetOneFrameWndTitle(somSelf, hwndFrame);
brc = TRUE;
}
ntbUpdateVisiblePage(somSelf, SP_XFOLDER_FLDR);
return (brc);
}
/*
*@@ xfSnapToGrid:
* makes all objects in the folder "snap" on a grid whose
* coordinates are to be defined in the "system" object.
* This method checks if an Icon view of the folder is
* currently open; if not and fNotify == TRUE, it displays
* a message box.
*/
SOM_Scope BOOL SOMLINK xf_xfSnapToGrid(XFolder *somSelf,
BOOL fNotify)
{
// WPObject *obj;
HWND hwndFrame = 0,
hwndCnr = 0;
PMINIRECORDCORE pmrc;
LONG lNewX, lNewY;
BOOL brc = FALSE;
// if Shift is pressed, move all the objects, otherwise
// only the selected ones
BOOL fShiftPressed = doshQueryShiftState();
BOOL fMoveThisObject = FALSE;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfSnapToGrid");
// first we need the frame handle of a currently open icon view;
// all others don't make sense */
hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_CONTENTS);
if (hwndFrame) {
// now get the container handle
hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
if (hwndCnr)
{
// now begin iteration over the folder's objects; we don't
// use the WPS method (wpQueryContent) because this is too
// slow. Instead, we query the container directly.
pmrc = NULL;
do {
if (fShiftPressed)
// shift pressed: move all objects, so loop
// thru the whole container content
pmrc =
(PMINIRECORDCORE)WinSendMsg(hwndCnr,
CM_QUERYRECORD,
(MPARAM)pmrc, // NULL at first loop
MPFROM2SHORT(
(pmrc)
? CMA_NEXT // not first loop: get next object
: CMA_FIRST, // first loop: get first objecct
CMA_ITEMORDER)
);
else
// shift _not_ pressed: move selected objects
// only, so loop thru these objects
pmrc =
(PMINIRECORDCORE)WinSendMsg(hwndCnr,
CM_QUERYRECORDEMPHASIS,
(pmrc) // NULL at first loop
? (MPARAM)pmrc
: (MPARAM)CMA_FIRST, // flag for getting first selected
(MPARAM)(CRA_SELECTED)
);
if (pmrc) {
// record found:
// the WPS shares records among views, so we need
// to update the record core info first
WinSendMsg(hwndCnr,
CM_QUERYRECORDINFO,
(MPARAM)&pmrc,
(MPARAM)1); // one record only
// un-display the new object at the old (default) location
WinSendMsg(hwndCnr,
CM_ERASERECORD,
// this only changes the visibility of the
// record without changing the recordcore;
// this msg is intended for drag'n'drop and such
(MPARAM)pmrc,
NULL);
// now play with the objects coordinates
lNewX =
( (
( (pmrc->ptlIcon.x - pGlobalSettings->GridX)
+ (pGlobalSettings->GridCX / 2)
)
/ pGlobalSettings->GridCX ) * pGlobalSettings->GridCX )
+ pGlobalSettings->GridX;
lNewY =
( (
( (pmrc->ptlIcon.y - pGlobalSettings->GridY)
+ (pGlobalSettings->GridCY / 2)
)
/ pGlobalSettings->GridCY ) * pGlobalSettings->GridCY )
+ pGlobalSettings->GridY;
// update the record core
if ( (lNewX) && (lNewX != pmrc->ptlIcon.x) ) {
pmrc->ptlIcon.x = lNewX; // X
}
if ( (lNewY) && (lNewY != pmrc->ptlIcon.y) ) {
pmrc->ptlIcon.y = lNewY; // Y
}
// repaint at new position
WinSendMsg(hwndCnr,
CM_INVALIDATERECORD,
(MPARAM)&pmrc,
MPFROM2SHORT(1, // one record only
CMA_REPOSITION | CMA_ERASE));
}
} while (pmrc);
brc = TRUE; // "OK" flag
} // end if (hwndCnr)
} // end if (hwndFrame)
else { // no open icon view: complain
if (fNotify) {
cmnSetHelpPanel(-1); // disable F1
WinDlgBox(HWND_DESKTOP,
HWND_DESKTOP, // owner is desktop
(PFNWP)fnwpDlgGeneric, // common.c
NLS_MODULE, // load from resource file
ID_XFD_NOICONVIEW, // dialog resource id
(PVOID)NULL);
}
}
return (brc);
}
/*
*@@ xfQueryFldrSort:
* this returns the folder's sort settings into the specified
* USHORT variables. These are set to SET_DEFAULT if no instance
* data has been defined; you will then need to query the Global
* Settings' values.
*/
SOM_Scope BOOL SOMLINK xf_xfQueryFldrSort(XFolder *somSelf,
PUSHORT pusDefaultSort,
PUSHORT pusAlwaysSort)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfQueryFldrSort");
if ((pusDefaultSort) && (pusAlwaysSort)) {
*pusDefaultSort = (USHORT)_DefaultSort;
*pusAlwaysSort = (USHORT)_AlwaysSort;
return (TRUE);
} else
return (FALSE);
}
/*
* fncbSortAllViews:
* callback function for sorting all folder views.
* This is called by xf(cls)ForEachOpenView, which also passes
* the parameters to this func.
*/
MRESULT EXPENTRY fncbSortAllViews(HWND hwndView, // open folder view frame hwnd
ULONG ulSort, // sort flag
MPARAM mpView, // OPEN_xxx flag
MPARAM mpFolder) // XFolder*
{
XFolder *somSelf = (XFolder*)mpFolder;
MRESULT mrc = (MPARAM)FALSE;
if ( ((ULONG)mpView == OPEN_CONTENTS)
|| ((ULONG)mpView == OPEN_TREE)
|| ((ULONG)mpView == OPEN_DETAILS)
)
{
_xfSortViewOnce(somSelf, hwndView, ulSort);
mrc = (MPARAM)TRUE;
}
return (mrc);
}
/*
* fncbUpdateFolderSorts:
* callback function for updating all folder sorts.
* This is called by xf(cls)ForEachOpenView, which also passes
* the parameters to this func.
*/
MRESULT EXPENTRY fncbUpdateFolderSorts(HWND hwndView, // frame wnd handle
ULONG ulDummy,
MPARAM mpView, // OPEN_xxx flag for this view
MPARAM mpFolder) // somSelf
{
XFolder *somSelf = (XFolder*)mpFolder;
MRESULT mrc = (MPARAM)FALSE;
#ifdef DEBUG_SORT
_Pmpf(( "fncbUpdateFolderSorts: %s", _wpQueryTitle(somSelf) ));
#endif
if ( ((ULONG)mpView == OPEN_CONTENTS)
|| ((ULONG)mpView == OPEN_TREE)
|| ((ULONG)mpView == OPEN_DETAILS)
)
{
_xfSetCnrSort(somSelf, xwpsQueryCnrFromFrame(hwndView), FALSE);
mrc = (MPARAM)TRUE;
}
return (mrc);
}
/*
*@@ xfSetFldrSort:
* this is the new XFolder method for setting the sort data
* for a certain folder.
*
* usDefaultSort should be one of the SV_ constants as in
* XFolder::xfSortViewOnce or SET_DEFAULT for resetting the folder's
* default sort criterion to the Global Settings's value.
*
* usAlwaysSort can be 0 or 1 or SET_DEFAULT also.
*
* This method updates all open folder views with the new
* sort settings.
* This method returns TRUE if any visible change occured as
* a result to the new settings.
*/
SOM_Scope BOOL SOMLINK xf_xfSetFldrSort(XFolder *somSelf,
USHORT usDefaultSort,
USHORT usAlwaysSort)
{
BOOL Update = FALSE;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfSetFldrSort");
#ifdef DEBUG_SORT
_Pmpf(("xfSetFldrSort %s", _wpQueryTitle(somSelf)));
_Pmpf((" Old: Default %d, Always %d", _DefaultSort, _AlwaysSort));
_Pmpf((" New: Default %d, Always %d", usDefaultSort, usAlwaysSort));
#endif
if (usDefaultSort != _DefaultSort) {
_DefaultSort = usDefaultSort;
Update = TRUE;
}
if (usAlwaysSort != _AlwaysSort) {
_AlwaysSort = usAlwaysSort;
// if _wpRestoreState has found the pointer to the
// WPFOlder-internal sort structure, we will update
// this one also, because otherwise the WPS keeps
// messing with the container attributes
if (_pFldrSortInfo)
(_pFldrSortInfo)->fAlwaysSort = ALWAYS_SORT;
Update = TRUE;
}
if (Update) {
// update open views of this folder
_xfForEachOpenView(somSelf, 0, &fncbUpdateFolderSorts);
_wpSaveDeferred(somSelf);
// update folder "Sort" notebook page, if open
ntbUpdateVisiblePage(somSelf, SP_FLDRSORT_FLDR);
}
return (Update);
}
/*
*@@ xfSetCnrSort:
* this is the most central function of XFolder's
* extended sorting capabilities. This is called
* every time the container in an open folder view
* needs to have its sort settings updated. In other
* words, this function evaluates the current folder
* sort settings and finds out the corresponding
* container sort comparison functions and other
* settings.
*
* Parameters:
* -- HWND hwndCnr cnr of open view of somSelf
* -- BOOL fForce TRUE: always update the cnr
* settings, even if they have
* not changed
*
* This function gets called:
* 1) from our wpOpen override to set folder sort
* when a new folder view opens;
* 2) from our wpSetFldrSort override (see notes
* there);
* 3) after folder sort settings have been changed
* using xfSetFldrSort.
*
* It is usually not necessary to call this method
* directly. To sort folders, you should call
* XFolder::xfSetFldrSort or XFolder::xfSortViewOnce
* instead.
*
* Note that XFolder does not use the WPS's sort
* mechanisms at all. Instead, we set our own
* container sort comparison functions directly
* _always_. Those functions are all in cnrsort.c.
*
* See the XFolder Programming Guide for an
* overview of how XFolder sorting works.
*/
SOM_Scope void SOMLINK xf_xfSetCnrSort(XFolder *somSelf, HWND hwndCnr,
BOOL fForce)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfSetCnrSort");
if (hwndCnr) {
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(somSelf);
// use our macro for determining this folder's always-sort flag;
// this is TRUE if "Always sort" is on either locally or globally
BOOL AlwaysSort = ALWAYS_SORT;
// get our sort comparison func
PFN pfnSort = (AlwaysSort)
? QuerySortFunc(DEFAULT_SORT)
: NULL
;
CNRINFO CnrInfo;
BOOL Update = FALSE;
winhQueryCnrInfo(hwndCnr, CnrInfo);
#ifdef DEBUG_SORT
_Pmpf(( "_xfSetCnrSort: %s", _wpQueryTitle(somSelf) ));
_Pmpf(( " _Always: %d, Global->Always: %d", _AlwaysSort, pGlobalSettings->AlwaysSort ));
_Pmpf(( " _Default: %d, Global->Default: %d", _DefaultSort, pGlobalSettings->DefaultSort ));
#endif
// for icon views, we need extra precautions
if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON)
{
// for some reason, cnr icon views need to have "auto arrange" on
// when sorting, or the cnr will allow to drag'n'drop icons freely
// within the same cnr, which is not useful when auto-sort is on
ULONG ulStyle = WinQueryWindowULong(hwndCnr, QWL_STYLE);
if (AlwaysSort) {
// always sort: we need to set CCS_AUTOPOSITION, if not set
if ((ulStyle & CCS_AUTOPOSITION) == 0) {
#ifdef DEBUG_SORT
_Pmpf(( " New ulStyle = %lX", ulStyle | CCS_AUTOPOSITION ));
#endif
WinSetWindowULong(hwndCnr, QWL_STYLE, (ulStyle | CCS_AUTOPOSITION));
Update = TRUE;
}
} else {
// NO always sort: we need to unset CCS_AUTOPOSITION, if set
if ((ulStyle & CCS_AUTOPOSITION) != 0) {
#ifdef DEBUG_SORT
_Pmpf(( " New ulStyle = %lX", ulStyle & (~CCS_AUTOPOSITION) ));
#endif
WinSetWindowULong(hwndCnr, QWL_STYLE, (ulStyle & (~CCS_AUTOPOSITION)));
Update = TRUE;
}
}
}
// now also update the internal WPFolder sort info, because otherwise
// the WPS will keep reverting the cnr attrs; we have obtained the pointer
// to this structure in wpRestoreData
if (_pFldrSortInfo)
_pFldrSortInfo->fAlwaysSort = AlwaysSort;
// finally, set the cnr sort function: we perform these checks
// to avoid cnr flickering
if ( // sort function changed?
(CnrInfo.pSortRecord != (PVOID)pfnSort)
// CCS_AUTOPOSITION flag changed above?
|| (Update)
|| (fForce)
)
{
#ifdef DEBUG_SORT
_Pmpf(( " Resetting pSortRecord to %lX", CnrInfo.pSortRecord ));
#endif
// set the cnr sort function; if this is != NULL, the
// container will always sort the records. If auto-sort
// is off, pfnSort has been set to NULL above.
CnrInfo.pSortRecord = (PVOID)pfnSort;
// now update the CnrInfo, which will repaint the cnr also
WinSendMsg(hwndCnr,
CM_SETCNRINFO,
(MPARAM)&CnrInfo,
(MPARAM)CMA_PSORTRECORD);
}
}
}
/*
*@@ xfSortViewOnce:
* sorts the content of given folder.
* As opposed to xfSetFldrSort, this does not change the
* folder sort settings, but only sorts the view once.
* This is used by the context menu entries in the "Sort"
* menu.
*
* ulSort must be one of the following:
* -- SV_NAME
* -- SV_TYPE
* -- SV_CLASS (new: sort by object class)
* -- SV_REALNAME
* -- SV_SIZE
* -- SV_LASTWRITEDATE
* -- SV_LASTACCESSDATE
* -- SV_CREATIONDATE
* -- SV_EXT (new: sort by extension)
* -- SV_FOLDERSFIRST (new: sort folders first)
*/
/*
*@@ xfSortViewOnce:
* sorts the content of given folder.
* As opposed to XFolder::xfSetFldrSort, this does not
* change the folder sort settings, but only sorts the view
* once.
* This is used by the context menu entries in the "Sort"
* menu.
*
* ulSort must be one of the following:
* -- SV_NAME
* -- SV_TYPE
* -- SV_CLASS (new: sort by object class)
* -- SV_REALNAME
* -- SV_SIZE
* -- SV_LASTWRITEDATE
* -- SV_LASTACCESSDATE
* -- SV_CREATIONDATE
* -- SV_EXT (new: sort by extension)
* -- SV_FOLDERSFIRST (new: sort folders first)
*/
SOM_Scope BOOL SOMLINK xf_xfSortViewOnce(XFolder *somSelf, HWND hwndFrame,
USHORT usSort)
{
BOOL rc = FALSE;
HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfSortByExt");
if (hwndCnr) {
CNRINFO CnrInfo;
ULONG ulStyle = 0;
winhQueryCnrInfo(hwndCnr, CnrInfo);
if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON) {
// for some reason, icon views need to have "auto arrange" on,
// or nothing will happen
ulStyle = WinQueryWindowULong(hwndCnr, QWL_STYLE);
WinSetWindowULong(hwndCnr, QWL_STYLE, ulStyle | CCS_AUTOPOSITION);
}
// send sort msg with proper sort (comparison) func
WinSendMsg(hwndCnr, CM_SORTRECORD,
(MPARAM)QuerySortFunc(usSort),
MPNULL);
if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON)
// restore old cnr style
WinSetWindowULong(hwndCnr, QWL_STYLE, ulStyle);
rc = TRUE;
}
return (rc);
}
/*
*@@ xfQueryIconPos:
* this new instance method retrieves the icon position of an
* object in a currently populated folder; you need to initialize
* the pICONPOS structure first, whose size you need to pass in
* ulICONPOSSize; the ICONPOS data will be copied to pipReturn.
* The method returns FALSE if something went wrong.
*/
SOM_Scope BOOL SOMLINK xf_xfGetIconPos(XFolder *somSelf,
WPObject *pObject,
PBYTE pICONPOS, USHORT usICONPOSSize,
PICONPOS pipReturn)
{
USHORT usStartPos;
PICONPOS pip;
CHAR szKey[100],
szPath[CCHMAXPATH];
HOBJECT hObject = _wpQueryHandle(pObject);
PSZ pszClass = _somGetClassName(pObject);
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfGetIconPos");
usStartPos = 21; // with OS/2 2.1 and above, Henk Kelder says
/* first step: the icon position of each object within a given
.ICONPOS EA starts with a string identifying the object; so
first, we need to compose this string depending on the type
of the passed object */
if (IsObjectAbstract(hObject))
sprintf(szKey, "%s:A%lX", pszClass, LOUSHORT(hObject));
else
{ // file system object
WPFileSystem *pobjFile;
if (pobjFile = _wpclsQueryObject(_WPObject, hObject)) {
if (_wpQueryFilename(pobjFile, szPath, FALSE)) {
sprintf(szKey, "%s:%c%s", pszClass,
(_somIsA(pobjFile, _WPFolder) ? 'D' : 'F'),
szPath);
} else
return FALSE;
} else
return FALSE;
}
// now we have the key to search for within the .ICONPOS EA
if ((pICONPOS) && (pipReturn))
{
/* now we go through the .ICONPOS data that was given to us
and check each item in there if it matches the key we
composed above */
for (pip = (PICONPOS)( pICONPOS + usStartPos );
(PBYTE)pip < pICONPOS + usICONPOSSize; )
{
if (!stricmp(pip->szIdentity, szKey))
{
*pipReturn = *pip;
return TRUE;
}
pip = (PICONPOS)( (PBYTE)pip + sizeof(POINTL) + strlen(pip->szIdentity) + 1 );
}
}
return FALSE;
}
/*
* GetICONPOS:
*
*/
PICONPOS GetICONPOS(PORDEREDLISTITEM poli, PSORTBYICONPOS psip)
{
PICONPOS pip;
CHAR *p;
USHORT usStartPos = 21; // OS/2 2.1 and above, says Henk
// ICONPOS is defined in PMWP.H as folllows:
// typedef struct _ICONPOS
// {
// POINTL ptlIcon;
// CHAR szIdentity[1];
// } ICONPOS;
// typedef ICONPOS *PICONPOS;
// now compare all the objects in the .ICONPOS structure
// to the identity string of the search object
for ( pip = (PICONPOS)( psip->pICONPOS + usStartPos );
(PBYTE)pip < (psip->pICONPOS + psip->usICONPOSSize);
)
{ // pip now points to an ICONPOS structure
// go beyond the class name
p = strchr(pip->szIdentity, ':');
if (p) {
/* #ifdef DEBUG_ORDEREDLIST
_Pmpf((" Identities: %s and %s...", p, poli->szIdentity));
#endif */
if (stricmp(p, poli->szIdentity) == 0)
// object found: return the ICONPOS address
return (pip);
else
// not identical: go to next ICONPOS structure
pip = (PICONPOS)( (PBYTE)pip + sizeof(POINTL) + strlen(pip->szIdentity) + 1 );
} else
break;
}
return (NULL);
}
/*
* fnSortByICONPOS:
* callback sort function for lstSort to sort the
* menu items according to a folder's ICONPOS EAs.
* pICONPOS points to the ICONPOS data.
*/
SHORT fnSortByICONPOS(PVOID pItem1, PVOID pItem2, PVOID psip)
{
/* #ifdef DEBUG_ORDEREDLIST
_Pmpf((" Comparing %s and %s...",
_wpQueryTitle(((PORDEREDLISTITEM)pItem1)->pObj),
_wpQueryTitle(((PORDEREDLISTITEM)pItem2)->pObj)
));
#endif */
if ((pItem1) && (pItem2)) {
PICONPOS pip1 = GetICONPOS(((PORDEREDLISTITEM)pItem1), psip),
pip2 = GetICONPOS(((PORDEREDLISTITEM)pItem2), psip);
if ((pip1) && (pip2))
if (pip1 < pip2)
return (-1);
else return (1);
else if (pip1)
return (-1);
else if (pip2)
return (1);
}
return (0);
}
/*
* InvalidateOrderedContent:
*
*/
BOOL InvalidateOrderedContent(XFolderData *somThis)
{
BOOL brc = FALSE;
if (_hmtxOrderedContent == NULLHANDLE) {
DosCreateMutexSem(NULL, // unnamed
&(_hmtxOrderedContent),
0, // unshared
FALSE); // unowned
}
if (_pliOrderedContentFirst)
{
BOOL fSemOwned = FALSE;
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
if (fSemOwned)
lstClear((PLISTITEM*)&(_pliOrderedContentFirst),
(PLISTITEM*)&(_pliOrderedContentLast));
else
_Pmpf(("Could not request sem, InvalidateOrderedContent"));
brc = TRUE;
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(_hmtxOrderedContent);
fSemOwned = FALSE;
}
}
return (brc);
}
/*
*@@ xfInvalidateOrderedContent:
* this deletes the ordered content list so that it will
* be rebuilt when it's needed. This is necessary if
* objects in the folder have changed.
*/
SOM_Scope BOOL SOMLINK xf_xfInvalidateOrderedContent(XFolder *somSelf)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfInvalidateOrderedContent");
return (InvalidateOrderedContent(somThis));
}
/*
* UpdateOrderedContent:
* this is called by the xfUpdateOrderedContent method
* just below. We needed to extract this code because
* it is accessed from xfQueryOrderedContent without
* the semaphore handling.
*/
BOOL UpdateOrderedContent(XFolder *somSelf, XFolderData *somThis, BOOL fReqSem)
{
BOOL brc = FALSE;
PORDEREDLISTITEM poliNew;
PEABINDING peab;
WPObject *pObj;
SORTBYICONPOS sip;
ULONG ulrc;
BOOL fSemOwned = FALSE;
if (_hmtxOrderedContent == NULLHANDLE) {
DosCreateMutexSem(NULL, // unnamed
&(_hmtxOrderedContent),
0, // unshared
FALSE); // unowned
}
TRY_LOUD(excpt1)
{
if (fReqSem)
fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
if ((fSemOwned) || (!fReqSem))
{
// first clean up
if (_pliOrderedContentFirst)
lstClear((PLISTITEM*)&(_pliOrderedContentFirst),
(PLISTITEM*)&(_pliOrderedContentLast));
if (_pICONPOS)
{
_wpFreeMem(somSelf, _pICONPOS);
_pICONPOS = NULL;
}
// build new list:
// get the folder's content as the WPS delivers it.
// This is unsorted. Apparently, the WPS returns items
// in the following order:
// a) first: file-system objects in the order returned
// by the file system (i.e. alphabetically on HPFS)
// b) then all abstract objects in the order they were
// placed in this folder.
for ( pObj = _wpQueryContent(somSelf, NULL, (ULONG)QC_FIRST);
(pObj);
pObj = _wpQueryContent(somSelf, pObj, (ULONG)QC_NEXT)
)
{
poliNew = malloc(sizeof(ORDEREDLISTITEM));
poliNew->pObj = pObj;
// Each ICONPOS struct's identity string has the following format:
// <class>:<t><identity>
// with: <class> being the class of the object
// <t> == A for abstracts, D for folders, F for files
// <identity> for abstract objects: the handle
// for file-system objects: the filename
// now create the identity string for the search object
if (_somIsA(pObj, _WPAbstract)) {
// for abstract objects, this is the low word
// of the object handle
HOBJECT hobjSearch = _wpQueryHandle(pObj);
sprintf(poliNew->szIdentity, ":A%lX", (hobjSearch & 0xFFFF));
} else {
// for file-system objects, this is the object's real name
ULONG ulSize = sizeof(poliNew->szIdentity)-2;
if (_somIsA(pObj, _WPFolder))
strcpy(poliNew->szIdentity, ":D");
else
strcpy(poliNew->szIdentity, ":F");
// append real name
_wpQueryRealName(pObj, (poliNew->szIdentity)+2, &ulSize, FALSE);
}
lstAppendItem((PLISTITEM*)&(_pliOrderedContentFirst),
(PLISTITEM*)&(_pliOrderedContentLast),
(PLISTITEM)poliNew);
}
// read .ICONPOS extended attributes of this folder
_wpQueryFilename(somSelf, sip.szRealName, TRUE);
if (peab = eaPathReadOneByName(sip.szRealName, ".ICONPOS"))
{
// typedef struct
// {
// BYTE bFlags;
// BYTE bNameLength;
// USHORT usValueLength;
// PSZ pszName;
// PSZ pszValue;
// } EABINDING, *PEABINDING;
_pICONPOS = _wpAllocMem(somSelf, peab->usValueLength+100, &ulrc);
if (_pICONPOS) {
memcpy(_pICONPOS, peab->pszValue+4, peab->usValueLength-3);
_ulICONPOSSize = (peab->usValueLength)-5;
eaFreeBinding(peab);
// finally, we have the ICONPOS data in _pICONPOS;
// now we pass the ICONPOS data to the sort function
// defined above
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" Sorting..."));
#endif
sip.pICONPOS = _pICONPOS;
sip.usICONPOSSize = _ulICONPOSSize;
lstQuickSort((PLISTITEM*)&(_pliOrderedContentFirst),
(PLISTITEM*)&(_pliOrderedContentLast),
fnSortByICONPOS,
&sip);
}
}
brc = TRUE;
} else
_Pmpf(("Could not request sem, UpdateOrderedContent, Req: %d, hmtx: 0x%lX",
fReqSem,
_hmtxOrderedContent));
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(_hmtxOrderedContent);
fSemOwned = FALSE;
}
return (brc);
}
/*
*@@ xfUpdateOrderedContent:
* this new instance methods builds or updates a list of the
* folder contents in memory. The root of the list is saved
* in the folder instance data.
*
* This method is called by XFolder::xfQueryOrderedContent if the
* list in memory has not been built yet. You do not need to call this
* method manually.
*/
SOM_Scope BOOL SOMLINK xf_xfUpdateOrderedContent(XFolder *somSelf)
{
BOOL fSemOwned = FALSE;
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfUpdateOrderedContent");
#ifdef DEBUG_ORDEREDLIST
_Pmpf(("Entering xf_xfUpdateOrderedContent for %s", _wpQueryTitle(somSelf) ));
#endif
return (UpdateOrderedContent(somSelf, somThis,
TRUE)); // request semaphore
}
/*
*@@ xfQueryOrderedContent:
* this new instance method has the same parameters als wpQueryContent,
* but it returns items from the list built by
* XFolder::xfUpdateOrderedContent.
*
* As opposed to the list returned by wpQueryContent, the objects
* in this list are in the same order as in the name or details views,
* because the list is built according to the .ICONPOS EAs.
*/
SOM_Scope WPObject* SOMLINK xf_xfQueryOrderedContent(XFolder *somSelf,
WPObject* Object,
ULONG ulOption)
{
WPObject *pobjReturn = NULL;
PORDEREDLISTITEM poli;
BOOL fSemOwned = FALSE;
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfQueryOrderedContent");
#ifdef DEBUG_ORDEREDLIST
_Pmpf(("xfQueryOrderedContent for %s, ulOption: %d",
_wpQueryTitle(somSelf),
ulOption));
#endif
xwpsCheckIfPopulated(somSelf);
if ( (ulOption == QC_FIRST)
&& (_pliOrderedContentFirst == NULL)
)
{
UpdateOrderedContent(somSelf, somThis,
TRUE); // request semaphore
}
TRY_LOUD(excpt1)
{
if (_pliOrderedContentFirst)
{
fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
if (fSemOwned)
{
poli = _pliOrderedContentFirst;
if (poli) {
switch (ulOption) {
case QC_FIRST: {
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" returning first"));
#endif
pobjReturn = poli->pObj;
break; }
case QC_NEXT: {
while (poli)
if (poli->pObj == Object)
{
BOOL fValid = TRUE;
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" found just-before"));
_Pmpf((" Title: %s",
_wpQueryTitle(poli->pObj) ));
#endif
if (poli->pNext) {
pobjReturn = (poli->pNext->pObj);
// check validity of object
fValid = xwpsCheckObject(pobjReturn);
if (fValid)
fValid = (_wpQueryTitle(pobjReturn) != NULL);
}
if (fValid) {
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" found valid next"));
if (pobjReturn)
_Pmpf((" Title: %s",
_wpQueryTitle(pobjReturn) ));
else
_Pmpf((" NULL"));
_Pmpf((" Returning."));
#endif
break; // while
} else {
// invalid object: restart search, since
// we've changed the list
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" rebuilding list"));
#endif
// if the object we found is not a valid SOM object
// any more, we will delete it from the list
/* lstRemoveItem((PLISTITEM*)&(_pliOrderedContentFirst),
(PLISTITEM*)&(_pliOrderedContentLast),
(PLISTITEM)poli,
0, 0); // we already have the semaphore
*/
UpdateOrderedContent(somSelf, somThis,
FALSE); // we already have the semaphore
poli = _pliOrderedContentFirst;
}
} // end if (poli->pObj == Object)
else {
#ifdef DEBUG_ORDEREDLIST
_Pmpf((" searching next"));
#endif
poli = poli->pNext;
}
break; }
}
}
}
else
_Pmpf(("Could not request sem, xfQueryOrderedContent"));
}
else
pobjReturn = _wpQueryContent(somSelf, Object, ulOption);
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(_hmtxOrderedContent);
fSemOwned = FALSE;
}
return (pobjReturn);
}
/*
*@@ xfBeginProcessOrderedContent:
* this new instance method uses XFolder::xfQueryOrderedContent to open
* all the objects in the given folder. This method returns immediately;
* further processing is done in the background Worker thread.
*
* Parameters:
* -- ULONG ulTiming: the time to wait between starting objects
* in milliseconds; if set to 0, this function
* will work in "Wait" mode, i.e. the next
* object will open the next object only if
* the previous one has been closed again
* (e.g. for XShutdown folder)
* -- PFNWP pfnwpCallback: a callback routine which will be called on
* every object which is started;
* -- ULONG ulCallbackParam: the first parameter to pass to this proc.
*
* pfnwpCallback will be passed the following parameters:
* -- HWND hwnd: will not be a hwnd, but ulCallbackParam;
* -- ULONG msg: will contain the current object of the
* folder on which this mthd is invoked;
* this must be cast manually to (WPObject*)
* -- MPARAM mp1: contains the current object count
* (starting with 1 and increasing for each
* subsequent object);
* -- MPARAM mp2: the (constant) number of objects in the folder.
*
* This callback func may be used for implementing a progress bar.
* You can use ulCallbackParam for the msg window handle and display
* the progress according to mp1 and mp2; the object title may be
* obtained by calling _wpQueryTitle((WPObject*)msg).
*
* After all objects have been processed, the callback will called
* once more with msg == 0 to allow cleaning up. If the folder does
* not contain any objects, callback will only be called this one time.
*
* If you're running in "Wait" mode, the callback must return the
* hwnd of the object which you must have opened with wpViewObject,
* so that XFolder can wait for this window to be closed.
*
* Note that even though the processing of the folder is done in the
* Worker thread, the callback func is actually called on the main
* (Workplace) thread, so you can create your window there and have
* work done on it without having to worry about thread safety. This
* is implemented because wpViewObject is having problems when not
* being called in the Workplace thread.
*
* This method returns a handle which may be used in
* XFolder::xfCancelProcessOrderedContent to abort processing,
* or 0 upon errors.
*/
SOM_Scope ULONG SOMLINK xf_xfBeginProcessOrderedContent(XFolder *somSelf,
ULONG ulTiming,
PFNWP pfnwpCallback,
ULONG ulCallbackParam)
{
PPROCESSCONTENTINFO pPCI;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfBeginProcessOrderedContent");
pPCI = (PPROCESSCONTENTINFO)malloc(sizeof(PROCESSCONTENTINFO));
if (pPCI) {
pPCI->ulObjectNow = 0;
pPCI->ulTiming = ulTiming;
pPCI->pfnwpCallback = pfnwpCallback;
pPCI->ulCallbackParam = ulCallbackParam;
pPCI->fCancelled = FALSE;
xthrPostWorkerMsg(WOM_PROCESSORDEREDCONTENT, (MPARAM)somSelf, pPCI);
return ((ULONG)pPCI);
}
return (0);
}
/*
*@@ xfCancelProcessOrderedContent:
* this method cancels a folder content process started with
* XFolder::xfBeginProcessOrderedContent; hPOC must the handle
* returned by that function.
*
* Warning: After folder content processing has finished, hPOC is
* no longer valid, and calling this function then will simply
* crash the WPS. As a result, your callback function MUST keep
* track if hPOC is still valid; after the callback func has been
* called with msg == 0, calling this function is no longer allowed.
*/
SOM_Scope BOOL SOMLINK xf_xfCancelProcessOrderedContent(XFolder *somSelf,
ULONG hPOC)
{
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfCancelProcessOrderedContent");
((PPROCESSCONTENTINFO)hPOC)->fCancelled = TRUE;
return (TRUE);
}
/*
*@@ xfMakeFavoriteFolder:
* if fInsert is TRUE, this folder will be made a "favorite folder",
* i.e. added to all context menus; if FALSE, it will be removed.
*/
SOM_Scope ULONG SOMLINK xf_xfMakeFavoriteFolder(XFolder *somSelf,
BOOL fInsert)
{
BOOL fSemOwned = FALSE;
CHAR szFavoriteFolders[1000] = "";
PCONTENTMENULISTITEM pcmli, pFound = NULL;
// XFolderData *somThis = XFolderGetData(somSelf);
M_XFolderData *somThat = M_XFolderGetData(_XFolder);
XFolderMethodDebug("XFolder","xf_xfMakeFavoriteFolder");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
pcmli = pcmliFavoriteFolders;
while (pcmli)
if (pcmli->pFolder == somSelf) {
pFound = pcmli;
break;
} else
pcmli = pcmli->pNext;
if (fInsert)
{
if (!pFound) {
pcmli = malloc(sizeof(CONTENTMENULISTITEM));
pcmli->pFolder = somSelf;
lstAppendItem((PLISTITEM*)&(pcmliFavoriteFolders), NULL,
(PLISTITEM)pcmli);
}
}
else
lstRemoveItem((PLISTITEM*)&(pcmliFavoriteFolders), NULL,
(PLISTITEM)pFound);
// write list to INI as a string of handles
pcmli = pcmliFavoriteFolders;
if (pcmli)
{
while (pcmli) {
sprintf(szFavoriteFolders+strlen(szFavoriteFolders),
"%lX ", _wpQueryHandle(pcmli->pFolder));
pcmli = pcmli->pNext;
}
PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
szFavoriteFolders);
} else
{
PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
NULL, 0);
}
}
}
CATCH(excpt1) {} END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(hmtxFavoriteFolders);
fSemOwned = FALSE;
}
return 0;
}
/*
*@@ xfIsFavoriteFolder:
* returns TRUE if somSelf is on the list of "favorite" folders.
*/
SOM_Scope BOOL SOMLINK xf_xfIsFavoriteFolder(XFolder *somSelf)
{
PCONTENTMENULISTITEM pcmli;
BOOL rc = FALSE,
fSemOwned = FALSE;
// XFolderData *somThis = XFolderGetData(somSelf);
M_XFolderData *somThat = M_XFolderGetData(_XFolder);
XFolderMethodDebug("XFolder","xf_xfIsFavoriteFolder");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
pcmli = pcmliFavoriteFolders;
while (pcmli) {
if (pcmli->pFolder == somSelf) {
rc = TRUE;
break;
} else
pcmli = pcmli->pNext;
}
}
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(hmtxFavoriteFolders);
fSemOwned = FALSE;
}
return (rc);
}
/*
*@@ xfSetQuickOpen:
* if fQuickOpen == TRUE, somSelf will automatically be
* populated at WPS bootup.
*/
SOM_Scope ULONG SOMLINK xf_xfSetQuickOpen(XFolder *somSelf,
BOOL fQuickOpen)
{
BOOL fSemOwned = FALSE;
CHAR szQuickOpenFolders[1000] = "";
PCONTENTMENULISTITEM pcmli, pFound = NULL;
// XFolderData *somThis = XFolderGetData(somSelf);
M_XFolderData *somThat = M_XFolderGetData(_XFolder);
XFolderMethodDebug("XFolder","xf_xfSetQuickOpen");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
pcmli = pcmliQuickOpenFolders;
while (pcmli)
if (pcmli->pFolder == somSelf) {
pFound = pcmli;
break;
} else
pcmli = pcmli->pNext;
if (fQuickOpen)
{
if (!pFound) {
pcmli = malloc(sizeof(CONTENTMENULISTITEM));
pcmli->pFolder = somSelf;
lstAppendItem((PLISTITEM*)&(pcmliQuickOpenFolders), NULL,
(PLISTITEM)pcmli);
}
}
else
lstRemoveItem((PLISTITEM*)&(pcmliQuickOpenFolders), NULL,
(PLISTITEM)pFound);
// write list to INI as a string of handles
pcmli = pcmliQuickOpenFolders;
if (pcmli) {
while (pcmli) {
sprintf(szQuickOpenFolders+strlen(szQuickOpenFolders),
"%lX ", _wpQueryHandle(pcmli->pFolder));
pcmli = pcmli->pNext;
}
PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
szQuickOpenFolders);
} else {
PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
NULL, 0);
}
}
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(hmtxQuickOpenFolders);
fSemOwned = FALSE;
}
return 0;
}
/*
*@@ xfQueryQuickOpen:
* returns TRUE if somSelf has the QuickOpen feature ON.
*/
SOM_Scope BOOL SOMLINK xf_xfQueryQuickOpen(XFolder *somSelf)
{
PCONTENTMENULISTITEM pcmli;
BOOL rc = FALSE,
fSemOwned = FALSE;
// XFolderData *somThis = XFolderGetData(somSelf);
M_XFolderData *somThat = M_XFolderGetData(_XFolder);
XFolderMethodDebug("XFolder","xf_xfQueryQuickOpen");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
pcmli = pcmliQuickOpenFolders;
while (pcmli) {
if (pcmli->pFolder == somSelf) {
rc = TRUE;
break;
} else
pcmli = pcmli->pNext;
}
}
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(hmtxQuickOpenFolders);
fSemOwned = FALSE;
}
return (rc);
}
/*
*@@ xfShowStatusBar:
* depending on fShow, this shows or hides the folder status
* bar for a certain folder.
*
* Parameters:
* -- psli: list item of this folder frame from the global
* linked list (of PSUBCLASSEDLISTITEM's); this
* item contains the folder frame window handle
* -- fShow: show / hide flag
*
* This func returns the hwnd of the status bar or NULL if calling
* the func was useless, because the status bar was already
* (de)activated.
* Note that this does _not_ change the folder's visibility
* settings, but only shows or hides the status bar "factually"
* by reformatting the folder frame's PM windows.
* This function _must_ be called only from the same thread
* where the folder frame window is running (normally TID 1),
* otherwise the WPS will crash or PM will hang.
*
* Because of all this, call XFolder::xfSetStatusBarVisibility
* instead if you wish to change folder status bars. That function
* will do the display also.
*/
SOM_Scope HWND SOMLINK xf_xfShowStatusBar(XFolder *somSelf,
PVOID psli,
BOOL fShow)
{
HWND hrc = NULLHANDLE;
BOOL fUpdateNotebook = FALSE;
CHAR szFolderPosKey[50];
ULONG ulIni;
ULONG cbIni;
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfShowStatusBar");
#ifdef DEBUG_STATUSBARS
_Pmpf(("xfShowStatusBar %d", fShow));
#endif
if (psli) {
// we had to declare psli as a PVOID because
// SOM does not know the PSUBCLASSEDLISTITEM struct;
// so we do the conversion per macro
#define psli2 ((PSUBCLASSEDLISTITEM)psli)
// CHAR szINIKey[50];
// HOBJECT hObj = _wpQueryHandle(somSelf);
// ULONG ulDummy;
if (fShow)
{
// show status bar
if (psli2->hwndStatusBar) { // already activated: update only
WinPostMsg(psli2->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
// and quit
}
// else create status bar as a static control
// (which will be subclassed below)
else if (psli2->hwndStatusBar = WinCreateWindow(
psli2->hwndFrame, // parent
WC_STATIC, // wnd class
(cmnQueryNLSStrings())->pszPopulating, // title
(SS_TEXT | DT_LEFT | DT_VCENTER // wnd style flags
| DT_ERASERECT
| WS_VISIBLE | WS_CLIPSIBLINGS),
0L, 0L, -1L, -1L,
psli2->hwndFrame, // owner
HWND_BOTTOM,
0x9001, // ID
(PVOID)NULL,
(PVOID)NULL))
{
BOOL fInflate = FALSE;
SWP swp;
PSZ pszStatusBarFont = cmnQueryStatusBarSetting(SBS_STATUSBARFONT);
// set up window data (QWL_USER) for status bar
PSTATUSBARDATA psbd = malloc(sizeof(STATUSBARDATA));
psbd->somSelf = somSelf;
psbd->psli = psli2;
psbd->idTimer = 0;
psbd->fDontBroadcast = TRUE;
// prevents broadcasting of WM_PRESPARAMSCHANGED
psbd->fFolderPopulated = FALSE;
// suspends updating until folder is populated;
WinSetWindowULong(psli2->hwndStatusBar, QWL_USER, (ULONG)psbd);
// subclass static control to make it a status bar
psbd->pfnwpStatusBarOriginal = WinSubclassWindow(psli2->hwndStatusBar,
fnwpStatusBar);
WinSetPresParam(psli2->hwndStatusBar, PP_FONTNAMESIZE,
(ULONG)strlen(pszStatusBarFont) + 1, (PVOID)pszStatusBarFont);
// now "inflate" the folder frame window if this is the first
// time that this folder view has been opened with a status bar;
// if we didn't do this, the folder frame would be too small
// for the status bar and scroll bars would appear. We store
// a flag in the folder's instance data for each different view
// that we've inflated the folder frame, so that this happens
// only once per view.
// From wpobject.h:
// #define VIEW_CONTENTS 0x00000001
// #define VIEW_SETTINGS 0x00000002
// #define VIEW_HELP 0x00000004
// #define VIEW_RUNNING 0x00000008
// #define VIEW_DETAILS 0x00000010
// #define VIEW_TREE 0x00000020
sprintf(szFolderPosKey, "%d@XFSB",
_wpQueryHandle(psli2->pRealObject));
cbIni = sizeof(ulIni);
if (PrfQueryProfileData(HINI_USER,
WPINIAPP_FOLDERPOS, // "PM_Workplace:FolderPos"
szFolderPosKey,
&ulIni,
&cbIni) == FALSE)
ulIni = 0;
if (ulIni & ( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
))
fInflate = FALSE;
else
fInflate = TRUE;
// _Pmpf(( "Old _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
/* if ( ( _ulSBInflatedFrame
& ( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
)
) == 0) */
// the folder pos entries in OS2.INI have the following
// format:
// <handle>@<view>
// with:
// handle being the decimal string of the five-digit
// object handle (2xxxx for abstract objects);
// key being some code for the view. I'm not
// perfectly sure about this, but from my testing
// I got the following:
// @10 Icon view folder pos
// @1010 Tree view folder pos
// @1020 Details view folder pos
// @ if any fonts were changed;
// might be a WPS bug (?!?)
// so now we check OS2.INI if the key for our view exists
// already, ie. the WPS has already saved a folder pos for
// this folder view
/* sprintf(szFolderPosKey, "%d@%s",
_wpQueryHandle(psli2->pRealObject),
(psli2->ulView == OPEN_CONTENTS) ? "10"
: (psli2->ulView == OPEN_TREE) ? "1010"
: "1020"
);
if (PrfQueryProfileSize(HINI_USER,
WPINIAPP_FOLDERPOS, // "PM_Workplace:FolderPos"
szFolderPosKey,
&ulDummy)
== FALSE)
// key does not exist: inflate!
fInflate = TRUE;
else
fInflate = FALSE; */
if (fInflate)
{
// this view has not been inflated yet:
// inflate now and set flag for this view
ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
WinQueryWindowPos(psli2->hwndFrame, &swp);
// inflate folder frame
WinSetWindowPos(psli2->hwndFrame, 0,
swp.x, (swp.y - ulStatusBarHeight),
swp.cx, (swp.cy + ulStatusBarHeight),
SWP_MOVE | SWP_SIZE);
// mark this folder view as "inflated" in OS2.INI
ulIni |= ( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
);
PrfWriteProfileData(HINI_USER,
WPINIAPP_FOLDERPOS, // "PM_Workplace:FolderPos"
szFolderPosKey,
&ulIni,
sizeof(ulIni));
// finally, set a flag for the subclassed folder frame
// window proc that this folder view needs no additional scrolling
// (this is evaluated in WM_FORMATFRAME msgs)
psli2->fNeedCnrScroll = FALSE;
}
else
// if the folder frame has been inflated already,
// WM_FORMATFRAME _will_ have to scroll the container.
// We do this for icon views only.
if (psli2->ulView == OPEN_CONTENTS)
psli2->fNeedCnrScroll = TRUE;
// enforce reformatting / repaint of frame window
WinSendMsg(psli2->hwndFrame, WM_UPDATEFRAME, (MPARAM)0, MPNULL);
// update status bar contents
WinPostMsg(psli2->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
hrc = psli2->hwndStatusBar;
fUpdateNotebook = TRUE;
}
} else {
// hide status bar:
if (psli2->hwndStatusBar) {
SWP swp;
HWND hwndStatus = psli2->hwndStatusBar;
BOOL fDeflate = FALSE;
psli2->hwndStatusBar = 0;
WinSendMsg(psli2->hwndFrame, WM_UPDATEFRAME, (MPARAM)0, MPNULL);
WinDestroyWindow(hwndStatus);
// decrease the size of the frame window by the status bar height,
// if we did this before
// _Pmpf(( "Old _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
/* if ( ( _ulSBInflatedFrame
& ( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
)
) != 0) */
sprintf(szFolderPosKey, "%d@XFSB",
_wpQueryHandle(psli2->pRealObject));
cbIni = sizeof(ulIni);
if (PrfQueryProfileData(HINI_USER,
WPINIAPP_FOLDERPOS, // "PM_Workplace:FolderPos"
szFolderPosKey,
&ulIni,
&cbIni) == FALSE)
ulIni = 0;
if (ulIni & ( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
))
fDeflate = TRUE;
else
fDeflate = TRUE;
if (fDeflate)
{
ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
WinQueryWindowPos(psli2->hwndFrame, &swp);
WinSetWindowPos(psli2->hwndFrame, 0,
swp.x, (swp.y + ulStatusBarHeight),
swp.cx, (swp.cy - ulStatusBarHeight),
SWP_MOVE | SWP_SIZE);
ulIni &= ~( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
);
PrfWriteProfileData(HINI_USER,
WPINIAPP_FOLDERPOS, // "PM_Workplace:FolderPos"
szFolderPosKey,
&ulIni,
sizeof(ulIni));
// now unset the "inflated" flag for this view
/* _ulSBInflatedFrame &= ~( (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
: (psli2->ulView == OPEN_TREE) ? VIEW_TREE
: VIEW_DETAILS
);
_wpSaveDeferred(somSelf); */
// _Pmpf(( "New _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
}
hrc = psli2->hwndStatusBar;
fUpdateNotebook = TRUE;
}
}
}
return (hrc);
}
/*
* fncbUpdateStatusBars:
* callback func for WOM_UPDATEALLSTATUSBARS in
* XFolder Worker thread (xfdesk.c); should not
* be called directly (it must reside in this file
* to be able to access folder instance data).
* This is called by xf(cls)ForEachOpenView, which also passes
* the parameters to this func.
*/
MRESULT EXPENTRY fncbUpdateStatusBars(HWND hwndView, // folder frame
ULONG ulActivate,
// 1: show/hide status bars according to
// folder/Global settings
// 2: reformat status bars (e.g. because
// fonts have changed)
MPARAM mpView, // OPEN_xxx flag
MPARAM mpFolder) // folder object
{
MRESULT mrc = (MPARAM)FALSE;
#ifdef DEBUG_STATUSBARS
_Pmpf(("fncbUpdateStatusBars ulActivate = %d", ulActivate));
#endif
if (mpFolder != _wpclsQueryActiveDesktop(_WPDesktop))
{
PSUBCLASSEDLISTITEM psli = cmnQueryPSLI(hwndView);
if (psli)
{
if (ulActivate == 2) // "update" flag
WinPostMsg(psli->hwndSupplObject,
SOM_ACTIVATESTATUSBAR,
(MPARAM)2,
(MPARAM)hwndView);
else {
// show/hide flag:
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(mpFolder);
BOOL fVisible = (
( (_bStatusBar == STATUSBAR_ON)
|| ( (_bStatusBar == STATUSBAR_DEFAULT)
&& (pGlobalSettings->StatusBar)
)
)
&&
( ( ((ULONG)mpView == OPEN_CONTENTS)
&& (pGlobalSettings->SBForViews & SBV_ICON)
)
|| ( ((ULONG)mpView == OPEN_TREE)
&& (pGlobalSettings->SBForViews & SBV_TREE)
)
|| ( ((ULONG)mpView == OPEN_DETAILS)
&& (pGlobalSettings->SBForViews & SBV_DETAILS)
)
)
);
if ( fVisible != (psli->hwndStatusBar != NULLHANDLE) )
{
// visibility changed:
// we now post a message to the folder frame's
// supplementary object window;
// because we cannot mess with the windows on
// the Worker thread, we need to have the
// status bar created/destroyed/changed on the
// folder's thread
WinPostMsg(psli->hwndSupplObject,
SOM_ACTIVATESTATUSBAR,
(MPARAM)( (fVisible) ? 1 : 0 ), // show or hide
(MPARAM)hwndView);
mrc = (MPARAM)TRUE;
}
}
}
}
return (mrc);
}
/*
*@@ xfSetStatusBarVisibility:
* this new instance method sets the status bar visibility of
* a folder.
* ulVisibility may be:
* -- STATUSBAR_ON: show status bars
* -- STATUSBAR_OFF: hide status bars
* -- STATUSBAR_DEFAULT: use Global Setting for this folder
*
* If fUpdate is TRUE, XFolder will have the Worker thread search
* for open folder views and update their frame controls accordingly.
* Otherwise the status bar setting will only be changed internally
* for the next time the folder is opened. Might lead to errors.
* Returns TRUE if successful.
*/
SOM_Scope BOOL SOMLINK xf_xfSetStatusBarVisibility(XFolder *somSelf,
ULONG ulVisibility,
BOOL fUpdate)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfSetStatusBarVisibility");
if (_bStatusBar != ulVisibility) {
#ifdef DEBUG_STATUSBARS
_Pmpf(( "xfSetStatusBarVisibility: %d", ulVisibility));
#endif
_bStatusBar = ulVisibility;
if (fUpdate) {
// update open folder views in Worker thread;
// this will call fncbUpdateStatusBars for each
// open folder window
xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
(MPARAM)1, // show/hide flag
MPNULL);
// update "XFolder" notebook page, if open
ntbUpdateVisiblePage(somSelf, SP_XFOLDER_FLDR);
}
}
return (TRUE);
}
/*
*@@ xfQueryStatusBarVisibility:
* this new instance method returns the status bar visibility of
* a folder:
* -- STATUSBAR_ON: status bars visible
* -- STATUSBAR_OFF: status bars invisible
* -- STATUSBAR_DEFAULT: Global Setting used for this folder
*/
SOM_Scope BOOL SOMLINK xf_xfQueryStatusBarVisibility(XFolder *somSelf)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfQueryStatusBarVisibility");
return (_bStatusBar);
}
/*
*@@ xfForEachOpenView:
* this instance method goes through all open views of a folder and calls
* pfnwpCallback for each them (as opposed to xfclsForEachOpenView, which
* goes through all open folders on the system).
*
* The following params are then passed to pfnwpCallback:
* -- hwnd HWND hwndView the hwnd of the view frame window;
* -- mp1 ULONG ulView the view type (as def'd in wpOpen)
* -- mp2 XFolder* pFolder somSelf.
*
* This method does not return until all views have been processed.
* You might want to call this method in a different thread if the task
* will take long.
* This method returns TRUE if the callback returned TRUE at least once.
* Note on disk objects/root folders: the WPS does not maintain an open
* view list for root folders, but only for the corresponding disk object.
* xfForEachOpenView will call open disk views also, but the callback
* will still be passed the root folder in pFolder!
*/
SOM_Scope BOOL SOMLINK xf_xfForEachOpenView(XFolder *somSelf,
ULONG ulMsg,
PFNWP pfnwpCallback)
{
BOOL brc = FALSE;
WPObject *somSelf2;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_xfForEachOpenView");
if (_somIsA(somSelf, _WPRootFolder)) {
// for disk/root folder views: root folders have no
// open view, instead the disk object is registered
// to have the open view. Duh. So we need to find
// the disk object first
somSelf2 = _xfclsQueryDiskObject(_XFldDisk, somSelf);
} else
somSelf2 = somSelf;
if (somSelf2) {
if (_wpFindUseItem(somSelf2, USAGE_OPENVIEW, NULL))
{ // folder has an open view;
// now we go search the open views of the folder and get the
// frame handle of the desired view (ulView) */
PVIEWITEM pViewItem;
for (pViewItem = _wpFindViewItem(somSelf2, VIEW_ANY, NULL);
pViewItem;
pViewItem = _wpFindViewItem(somSelf2, VIEW_ANY, pViewItem))
{
if ((*pfnwpCallback)(
pViewItem->handle,
ulMsg,
(MPARAM)pViewItem->view,
// but even if we have found a disk object
// above, we need to pass it the root folder
// pointer, because otherwise the callback
// might get into trouble
(MPARAM)somSelf)
== (MPARAM)TRUE)
brc = TRUE;
} // end for
} // end if
}
return (brc);
}
/*
* fncbXFolderInitPage:
* "XFolder" page notebook callback function (notebook.c).
* Sets the controls on the page according to a folder's
* instance settings.
*/
VOID fncbXFolderInitPage(PVOID pnbi, // notebook info struct
ULONG ulExtra) // INIT_* flags (notebook.h)
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
XFolderData *somThis = XFolderGetData(pcnbp->somSelf);
if (ulExtra & CBI_INIT)
{
if (pcnbp->pBackup == NULL)
{
// first call: backup instance data for "Undo" button;
// this memory will be freed automatically by the
// common notebook window function (notebook.c) when
// the notebook page is destroyed
pcnbp->pBackup = malloc(sizeof(XFolderData));
memcpy(pcnbp->pBackup, somThis, sizeof(XFolderData));
}
}
if (ulExtra & CBI_SET)
{
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FAVORITEFOLDER,
_xfIsFavoriteFolder(pcnbp->somSelf));
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_QUICKOPEN,
_xfQueryQuickOpen(pcnbp->somSelf));
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SNAPTOGRID,
(MPARAM)( (_bSnapToGridAllowed == 2)
? pGlobalSettings->AddSnapToGridItem
: _bSnapToGridAllowed ));
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FULLPATH,
(MPARAM)( (_bFullPath == 2)
? pGlobalSettings->FullPath
: _bFullPath ));
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ACCELERATORS,
(MPARAM)( (_bAcceleratorsAllowed == 2)
? pGlobalSettings->Accelerators
: _bAcceleratorsAllowed ));
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR,
(MPARAM)( ( (_bStatusBar == STATUSBAR_DEFAULT)
? pGlobalSettings->StatusBar
: _bStatusBar )
// always uncheck for Desktop
&& (pcnbp->somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
));
}
if (ulExtra & CBI_ENABLE)
{
// disable items
winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ACCELERATORS,
(!(pGlobalSettings->NoSubclassing)));
// disable for Desktop
winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR,
( (pcnbp->somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
&& (!(pGlobalSettings->NoSubclassing))
));
}
}
/*
* fncbXFolderItemChanged:
* "XFolder" page notebook callback function (notebook.c).
* Reacts to changes of any of the dialog controls.
*/
MRESULT fncbXFolderItemChanged(PVOID pnbi, // notebook info
USHORT usItemID, USHORT usNotifyCode,
ULONG ulExtra) // for checkboxes: contains new state
{
PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
XFolderData *somThis = XFolderGetData(pcnbp->somSelf);
BOOL fUpdate = TRUE;
switch (usItemID)
{
case ID_XSDI_SNAPTOGRID:
_bSnapToGridAllowed = ulExtra;
break;
case ID_XSDI_FULLPATH:
_bFullPath = ulExtra;
_xfUpdateAllFrameWndTitles(pcnbp->somSelf);
break;
case ID_XSDI_ACCELERATORS:
_bAcceleratorsAllowed = ulExtra;
break;
case ID_XSDI_ENABLESTATUSBAR:
_xfSetStatusBarVisibility(pcnbp->somSelf,
ulExtra,
TRUE); // update open folder views
break;
case ID_XSDI_FAVORITEFOLDER:
_xfMakeFavoriteFolder(pcnbp->somSelf, ulExtra);
break;
case ID_XSDI_QUICKOPEN:
_xfSetQuickOpen(pcnbp->somSelf, ulExtra);
break;
case DID_UNDO:
if (pcnbp->pBackup) {
XFolderData *Backup = (pcnbp->pBackup);
// "Undo" button: restore backed up instance data
_bFullPath = Backup->bFullPath;
_bSnapToGridAllowed = Backup->bSnapToGridAllowed;
_bAcceleratorsAllowed = Backup->bAcceleratorsAllowed;
_xfSetStatusBarVisibility(pcnbp->somSelf,
Backup->bStatusBar,
TRUE); // update open folder views
// have the page updated by calling the callback above
fncbXFolderInitPage(pcnbp, CBI_SHOW | CBI_ENABLE);
_xfUpdateAllFrameWndTitles(pcnbp->somSelf);
}
break;
case DID_DEFAULT:
// "Default" button:
_bFullPath = 2;
_bSnapToGridAllowed = 2;
_bAcceleratorsAllowed = 2;
_xfSetStatusBarVisibility(pcnbp->somSelf,
STATUSBAR_DEFAULT,
TRUE); // update open folder views
// have the page updated by calling the callback above
fncbXFolderInitPage(pcnbp, CBI_SET | CBI_ENABLE);
_xfUpdateAllFrameWndTitles(pcnbp->somSelf);
break;
default:
fUpdate = FALSE;
break;
}
if (fUpdate)
_wpSaveDeferred(pcnbp->somSelf);
return ((MPARAM)-1);
}
/*
*@@ xfAddXFolderPages:
* this actually adds the "XFolder" pages into all folder notebooks.
*/
SOM_Scope ULONG SOMLINK xf_xfAddXFolderPages(XFolder *somSelf,
HWND hwndDlg)
{
PCREATENOTEBOOKPAGE pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
XFolderMethodDebug("XFolder","xf_xfAddXFolderPages");
strcpy(szXFolderVersion, "~XFolder ");
strcat(szXFolderVersion, XFOLDER_VERSION);
pcnbp->somSelf = somSelf;
pcnbp->hwndNotebook = hwndDlg;
pcnbp->hmod = NLS_MODULE;
pcnbp->ulDlgID = ID_XSD_SETTINGS_FLDR1;
pcnbp->ulPageID = SP_XFOLDER_FLDR;
pcnbp->fMajorTab = TRUE;
pcnbp->pszName = szXFolderVersion;
pcnbp->ulDefaultHelpPanel = ID_XSH_SETTINGS_FLDR1;
pcnbp->pfncbInitPage = fncbXFolderInitPage;
pcnbp->pfncbItemChanged = fncbXFolderItemChanged;
return (ntbInsertPage(pcnbp));
}
/*
*@@ wpInitData:
* here XFolder will initialize its instance data
*/
SOM_Scope void SOMLINK xf_wpInitData(XFolder *somSelf)
{
// PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpInitData");
XFolder_parent_WPFolder_wpInitData(somSelf);
// set all the instance variables to safe defaults
_pliOrderedContentFirst = NULL;
_pliOrderedContentLast = NULL;
_hmtxOrderedContent = NULLHANDLE;
_pICONPOS = NULL;
_ulICONPOSSize = 0;
_bSnapToGridAllowed = 2;
_bFullPath = 2;
_bAcceleratorsAllowed = 2;
_bStatusBar = STATUSBAR_DEFAULT;
_AlwaysSort = SET_DEFAULT;
_DefaultSort = SET_DEFAULT;
// _ulSBInflatedFrame = 0;
_pFldrSortInfo = NULL;
_pFldrLongArray = NULL;
_pszFldrStrArray = NULL;
_pusFldrBackground = NULL;
_cbFldrStrArray = 0;
_cbFldrLongArray = 0;
_pulShowAllInTreeView = NULL;
_fUnInitCalled = FALSE;
_hwndCnrSaved = NULLHANDLE;
}
/*
*@@ wpUnInitData:
* clean up when object is deleted or made dormant
*/
SOM_Scope void SOMLINK xf_wpUnInitData(XFolder *somSelf)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpUnInitData");
// make sure we only do this once, because we
// seem to get called several times sometimes
if (!_fUnInitCalled)
{
_fUnInitCalled = TRUE;
if (_pliOrderedContentFirst)
InvalidateOrderedContent(somThis);
if (_hmtxOrderedContent)
DosCloseMutexSem(_hmtxOrderedContent);
if (_pICONPOS) {
_wpFreeMem(somSelf, _pICONPOS);
_pICONPOS = NULL;
}
XFolder_parent_WPFolder_wpUnInitData(somSelf);
}
}
/*
*@@ wpFree:
* this WPObject method destroys the persistent form of the object
* and then frees the memory that represented that object. For
* WPFolders, this is called when a folder is actually to be
* deleted. We will call the parent method and then also remove
* those darn PMWorkplace:FolderPos entries which the WPS never
* deletes
*/
SOM_Scope BOOL SOMLINK xf_wpFree(XFolder *somSelf)
{
BOOL brc;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
HOBJECT hObj;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpFree");
if (pGlobalSettings->CleanupINIs)
{
// "clean up INI files": get object handle for
// folderpos deletion later. This doesn't hurt
// because every folder has a handle once it has
// been opened
hObj = _wpQueryHandle(somSelf);
}
// according to WPS docs, the parent method should be called
// AFTER additional processing; probably somSelf becomes invalid
// after this
brc = XFolder_parent_WPFolder_wpFree(somSelf);
if (brc)
if (pGlobalSettings->CleanupINIs)
// have FOLDERPOS entries
// deleted by Worker thread; we only pass the
// object HANDLE and not somSelf because somSelf
// is no longer valid after having called the parent
xthrPostWorkerMsg(WOM_DELETEFOLDERPOS,
(MPARAM)hObj, NULL);
return (brc);
}
/*
*@@ wpSetup:
* this instance method is called to allow a
* newly created object to initialize itself.
* XFolder will examine its setup strings here
*/
SOM_Scope BOOL SOMLINK xf_wpSetup(XFolder *somSelf, PSZ pszSetupString)
{
BOOL rc,
fChanged = FALSE;
CHAR szValue[CCHMAXPATH+1];
ULONG cbValue;
USHORT usDefaultSort, usAlwaysSort;
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpSetup");
rc = (XFolder_parent_WPFolder_wpSetup(somSelf, pszSetupString));
if (rc) {
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"SNAPTOGRID", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_bSnapToGridAllowed = 0;
else if (strnicmp(szValue, "YES", 3) == 0)
_bSnapToGridAllowed = 1;
else if (strnicmp(szValue, "DEFAULT", 7) == 0)
_bSnapToGridAllowed = 2;
else if (strnicmp(szValue, "EXEC", 4) == 0)
_xfSnapToGrid(somSelf, FALSE);
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"FULLPATH", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_bFullPath = 0;
else if (strnicmp(szValue, "YES", 3) == 0)
_bFullPath = 1;
else if (strnicmp(szValue, "DEFAULT", 7) == 0)
_bFullPath = 2;
_xfUpdateAllFrameWndTitles(somSelf);
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"ACCELERATORS", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_bAcceleratorsAllowed = 0;
else if (strnicmp(szValue, "YES", 3) == 0)
_bAcceleratorsAllowed = 1;
else if (strnicmp(szValue, "DEFAULT", 7) == 0)
_bAcceleratorsAllowed = 2;
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"FAVORITEFOLDER", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_xfMakeFavoriteFolder(somSelf, FALSE);
else if (strnicmp(szValue, "YES", 3) == 0)
_xfMakeFavoriteFolder(somSelf, TRUE);
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"QUICKOPEN", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_xfSetQuickOpen(somSelf, FALSE);
else if (strnicmp(szValue, "YES", 3) == 0)
_xfSetQuickOpen(somSelf, TRUE);
fChanged = TRUE;
}
if (somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
{
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"STATUSBAR", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
_bStatusBar = STATUSBAR_OFF;
else if (strnicmp(szValue, "YES", 3) == 0)
_bStatusBar = STATUSBAR_ON;
else if (strnicmp(szValue, "DEFAULT", 7) == 0)
_bStatusBar = STATUSBAR_DEFAULT;
}
xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
(MPARAM)1, // show/hide flag
MPNULL);
fChanged = TRUE;
}
_xfQueryFldrSort(somSelf, &usDefaultSort, &usAlwaysSort);
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"ALWAYSSORT", szValue, &cbValue))
{
if (strnicmp(szValue, "NO", 2) == 0)
usAlwaysSort = 0;
else if (strnicmp(szValue, "YES", 3) == 0)
usAlwaysSort = 1;
else if (strnicmp(szValue, "DEFAULT", 7) == 0)
usAlwaysSort = SET_DEFAULT;
_xfSetFldrSort(somSelf, usDefaultSort, usAlwaysSort);
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"DEFAULTSORT", szValue, &cbValue))
{
LONG lValue;
sscanf(szValue, "%d", &lValue);
if ( (lValue >=0) && (lValue <= SV_LAST) )
usDefaultSort = lValue;
else
usDefaultSort = SET_DEFAULT;
_xfSetFldrSort(somSelf, usDefaultSort, usAlwaysSort);
fChanged = TRUE;
}
cbValue = sizeof(szValue);
if (_wpScanSetupString(somSelf, pszSetupString,
"SORTNOW", szValue, &cbValue))
{
LONG lValue;
sscanf(szValue, "%d", &lValue);
if ( (lValue >=0) && (lValue <= SV_LAST) )
usDefaultSort = lValue;
else
usDefaultSort = SET_DEFAULT;
_xfclsForEachOpenView(_XFolder, 0, &fncbSortAllViews);
}
if (fChanged)
_wpSaveDeferred(somSelf);
}
return (rc);
}
/*
*@@ wpSaveState:
* this instance method is called to allow an
* an object to save its state; XFolder will
* save its instance settings (NB page) here
*/
SOM_Scope BOOL SOMLINK xf_wpSaveState(XFolder *somSelf)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpSaveState");
// we will now save all our instance data; in order
// not to blow up the EA size too much, we will only
// save data which is different from the "transparent"
// (i.e. Global) setting
if (_bSnapToGridAllowed != 2)
_wpSaveLong(somSelf, "XFolder", 1, (ULONG)_bSnapToGridAllowed);
if (_bFullPath != 2)
_wpSaveLong(somSelf, "XFolder", 2, (ULONG)_bFullPath);
if (_bAcceleratorsAllowed != 2)
_wpSaveLong(somSelf, "XFolder", 3, (ULONG)_bAcceleratorsAllowed);
if (_bStatusBar != STATUSBAR_DEFAULT)
_wpSaveLong(somSelf, "XFolder", 4, (ULONG)_bStatusBar);
/* if (_ulSBInflatedFrame)
_wpSaveLong(somSelf, "XFolder", 5, (ULONG)_ulSBInflatedFrame); */
if (_AlwaysSort != SET_DEFAULT)
_wpSaveLong(somSelf, "XFolder", 6, (ULONG)_AlwaysSort);
if (_DefaultSort != SET_DEFAULT)
_wpSaveLong(somSelf, "XFolder", 7, (ULONG)_DefaultSort);
return (XFolder_parent_WPFolder_wpSaveState(somSelf));
}
/*
*@@ wpRestoreState:
* this instance method is called to allow an
* an object to restore its state; XFolder will
* restore its instance settings (NB page) here
*/
SOM_Scope BOOL SOMLINK xf_wpRestoreState(XFolder *somSelf,
ULONG ulReserved)
{
ULONG ul;
BOOL brc;
XFolderData *somThis = XFolderGetData(somSelf);
// XFolderMethodDebug("XFolder","xf_wpRestoreState");
#ifdef DEBUG_SOMMETHODS
_Pmpf(("XFolder::wpRestoreState for %s", _wpQueryTitle(somSelf) ));
#endif
// we will now restore all the different XFolder settings
// into the instance data; note that if _wpRestoreLong
// returns FALSE (i.e. setting not found), we always use
// the "transparent" value which makes this folder use
// the corresponding Global Setting
if (_wpRestoreLong(somSelf, "XFolder", 1, &ul))
_bSnapToGridAllowed = (BYTE)ul;
else _bSnapToGridAllowed = 2;
if (_wpRestoreLong(somSelf, "XFolder", 2, &ul))
_bFullPath = (BYTE)ul;
else _bFullPath = 2;
if (_wpRestoreLong(somSelf, "XFolder", 3, &ul))
_bAcceleratorsAllowed = (BYTE)ul;
else _bAcceleratorsAllowed = 2;
if (_wpRestoreLong(somSelf, "XFolder", 4, &ul))
_bStatusBar = (BYTE)ul;
else _bStatusBar = STATUSBAR_DEFAULT;
/* if (_wpRestoreLong(somSelf, "XFolder", 5, &ul))
_ulSBInflatedFrame = (BYTE)ul;
else _ulSBInflatedFrame = 0; */
if (_wpRestoreLong(somSelf, "XFolder", 6, &ul))
_AlwaysSort = (USHORT)ul;
if (_wpRestoreLong(somSelf, "XFolder", 7, &ul))
_DefaultSort = (USHORT)ul;
brc = (XFolder_parent_WPFolder_wpRestoreState(somSelf, ulReserved));
#ifdef DEBUG_SOMMETHODS
_Pmpf((" End of XFolder::wpRestoreState"));
#endif
return (brc);
}
/*
*@@ wpRestoreLong:
* this instance method restores a 32-bit data
* value from the folder EAs upon object awakening.
* We check the "ulKey" value after having called
* the parent to be able to intercept the pointer
* to certain WPS-internal folder data, which
* we cannot access otherwise. That's a real ugly
* kludge, but there's no other way to get certain
* folder settings. ;-)
* On Warp 4, the WPS queries the
* IDKEY_FDRTREEVIEWCONTENTS key here, which is
* == 1 if the "SHOWALLINTREEVIEW" flag is on.
*/
SOM_Scope BOOL SOMLINK xf_wpRestoreLong(XFolder *somSelf, PSZ pszClass,
ULONG ulKey, PULONG pulValue)
{
BOOL brc;
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpRestoreLong");
brc = XFolder_parent_WPFolder_wpRestoreLong(somSelf, pszClass,
ulKey, pulValue);
if (strcmp(pszClass, "WPFolder") == 0)
{
switch (ulKey)
{
// Warp 4
#ifndef IDKEY_FDRTREEVIEWCONTENTS
#define IDKEY_FDRTREEVIEWCONTENTS 2939
#endif
case IDKEY_FDRTREEVIEWCONTENTS: {
// then the pointer given to this method (pValue) must
// be the pointer to the WPFolder-internal SHOWALLINTREEVIEW
// flag
if (pulValue) {
XFolderData *somThis = XFolderGetData(somSelf);
_pulShowAllInTreeView = pulValue;
}
break; }
#ifdef DEBUG_RESTOREDATA
default: {
_Pmpf(("Long IDKEY_xxx (%s %d) --> 0x%lX",
pszClass, ulKey,
*pulValue)); // data returned
break; }
#endif
}
}
return (brc);
}
/*
*@@ wpRestoreData:
* this instance method restores binary instance
* data from the folder EAs upon object awakening.
* We check the "ulKey" value after having called
* the parent to be able to intercept the pointer
* to certain WPS-internal folder data, which
* we cannot access otherwise. That's a real ugly
* kludge, but there's no other way to get certain
* folder settings. ;-)
* On Warp 4, the WPS queries lots of sort and
* folder view settings here, whose pointers we
* can store in XFolder's instance data.
*/
SOM_Scope BOOL SOMLINK xf_wpRestoreData(XFolder *somSelf,
PSZ pszClass, ULONG ulKey,
PBYTE pValue, PULONG pcbValue)
{
BOOL brc;
ULONG cbOrigValue = 0;
// PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderMethodDebug("XFolder","xf_wpRestoreData");
// get the size of the buffer which was given to us
if (pValue)
// pValue given:
cbOrigValue = *pcbValue;
// else: caller is requesting the size of the data
// always call parent, even for the sort data, or
// the WPFolder original gets confused
brc = XFolder_parent_WPFolder_wpRestoreData(somSelf, pszClass,
ulKey, pValue,
pcbValue);
// after we have restored the setting by calling the
// default WPFolder method, we check for a few flags
// which we might be interested in; we can then store
// the pointer to WPS-internal data in XFolder instance
// data
if (strcmp(pszClass, "WPFolder") == 0)
{
switch (ulKey)
{
case IDKEY_FDRSORTINFO:
{
// then the pointer given to this method (pValue) must
// be the pointer to the WPFolder-internal FDRSORTINFO
// structure (undocumented, I've declared it in
// xfldr.idl); we store this pointer in the instance
// data so that we can manipulate it later
if (cbOrigValue == sizeof(FDRSORTINFO))
{
if (pValue) {
XFolderData *somThis = XFolderGetData(somSelf);
_pFldrSortInfo = (PFDRSORTINFO)pValue;
if (brc)
// if the parent method has found sort data,
// and the user had set "Always sort" on for
// the folder using the regular WPS "Sort" page,
// we need to update the XFolder sort data, but
// only update this if this hasn't been set
// by wpRestoreState yet; as a result, the
// XFolder sort settings will follow the WPFolder
// sort settings, but can be overridden
if (_AlwaysSort == SET_DEFAULT) // not set yet?
_AlwaysSort = ((PFDRSORTINFO)pValue)->fAlwaysSort;
}
}
// _Pmpf(("IDKEY_FDRSORTINFO size %d -> %d", cbOrigValue, *pcbValue));
break; }
case IDKEY_FDRBACKGROUND: // size: 2 bytes
if (cbOrigValue == 2)
{
if (pValue) {
XFolderData *somThis = XFolderGetData(somSelf);
_pusFldrBackground = (PUSHORT)pValue;
}
}
break;
case IDKEY_FDRLONGARRAY: // size: 84 bytes
{
XFolderData *somThis = XFolderGetData(somSelf);
// store the size of the data returned in
// folder instance data, in case it is not
// 84 bytes (as it is with Warp 4 fixpak 8)
_cbFldrLongArray = *pcbValue;
if (pValue)
_pFldrLongArray = (PFDRLONGARRAY)pValue;
break; }
case IDKEY_FDRSTRARRAY: // size: 400 bytes
{
XFolderData *somThis = XFolderGetData(somSelf);
// store the size of the data returned in
// folder instance data, in case it is not
// 400 bytes (as it is with Warp 4 fixpak 8)
_cbFldrStrArray = *pcbValue;
if (pValue)
_pszFldrStrArray = (PSZ)pValue;
break; }
#ifdef DEBUG_RESTOREDATA
default: {
_Pmpf(("Data IDKEY_xxx (%s %d) size %d -> %d",
pszClass, ulKey,
cbOrigValue, // size in or 0 if size queried
*pcbValue)); // size out
break; }
#endif
/*
* the following others were queried for G:\root\test
* under Warp 4 fixpak 8:
*/
/*
IDKEY_xxx (WPObject 11) size 32 -> 32 WPOBJECT_DATA
IDKEY_xxx (WPObject 12) size 400 -> 400 WPOBJECT_STRINGS
IDKEY_xxx (WPObject 4) size 8 -> 8 ?!?
IDKEY_xxx (WPFolder 2924) size 542 -> 542 IDKEY_CNRBACKGROUND
IDKEY_xxx (WPFolder 2920) size 542 -> 542 IDKEY_FDRINCCLASS
IDKEY_xxx (WPFolder 2925) size 542 -> 542 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2938) size 8 -> 8 IDKEY_FDRGRIDINFO
and these under Warp 3, no fixpaks:
IDKEY_xxx (WPObject 11) size 28 -> 28 (+) four bytes less
IDKEY_xxx (WPObject 12) size 400 -> 400 (+)
IDKEY_xxx (WPObject 4) size 8 -> 8 (+)
IDKEY_xxx (WPFolder 2924) size 542 -> 542 (+)
IDKEY_xxx (WPFolder 2920) size 542 -> 542 (+)
IDKEY_xxx (WPFolder 2925) size 542 -> 542 (+)
i.e. the same, except the grid info
but if we had a folder background set (Warp 4):
IDKEY_xxx (WPObject 11) size 32 -> 32
IDKEY_xxx (WPObject 12) size 400 -> 400
IDKEY_xxx (WPObject 4) size 8 -> 8
IDKEY_xxx (WPFolder 2924) size 542 -> 542 IDKEY_CNRBACKGROUND
IDKEY_xxx (WPFolder 2920) size 542 -> 542 IDKEY_FDRINCCLASS
IDKEY_xxx (WPFolder 2925) size 542 -> 107 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2920) size 260 -> 260 IDKEY_FDRINCCLASS
IDKEY_xxx (WPFolder 2925) size 260 -> 107 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2925) size 107 -> 107 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2938) size 8 -> 8
and on Warp 3:
IDKEY_xxx (WPObject 11) size 28 -> 28
IDKEY_xxx (WPObject 12) size 400 -> 400
IDKEY_xxx (WPObject 4) size 8 -> 8
no IDKEY_CNRBACKGROUND
IDKEY_xxx (WPFolder 2920) size 259 -> 259 IDKEY_FDRINCCLASS
IDKEY_xxx (WPFolder 2925) size 259 -> 178 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2920) size 260 -> 260 IDKEY_FDRINCCLASS
IDKEY_xxx (WPFolder 2925) size 260 -> 178 IDKEY_FDRINCCRITERIA
IDKEY_xxx (WPFolder 2925) size 178 -> 178 IDKEY_FDRINCCRITERIA
*/
/* this is what we got from the "Programme" folder (Warp 4):
Long IDKEY_xxx (WPFileSystem 4) --> 0x0
Data IDKEY_xxx (WPObject 11) size 32 -> 32 WPOBJECT_DATA
Data IDKEY_xxx (WPObject 12) size 400 -> 400 WPOBJECT_STRINGS
Data IDKEY_xxx (WPObject 4) size 8 -> 8 ?!?
Data IDKEY_xxx (WPFolder 2924) size 542 -> 542 IDKEY_CNRBACKGROUND
Strg IDKEY_xxx (WPFolder 2921) --> NULL IDKEY_FDRINCNAME
Data IDKEY_xxx (WPFolder 2920) size 0 -> 542 IDKEY_FDRINCCLASS
Data IDKEY_xxx (WPFolder 2925) size 0 -> 107 IDKEY_FDRINCCRITERIA
Data IDKEY_xxx (WPFolder 2920) size 0 -> 260 * IDKEY_FDRINCCLASS
Data IDKEY_xxx (WPFolder 2925) size 0 -> 107 * IDKEY_FDRINCCRITERIA
Data IDKEY_xxx (WPFolder 2925) size 107 -> 107 * IDKEY_FDRINCCRITERIA
Strg IDKEY_xxx (WPFolder 2921) --> * IDKEY_FDRINCNAME
Data IDKEY_xxx (WPFolder 2938) size 8 -> 8 IDKEY_FDRGRIDINFO
Long IDKEY_xxx (WPFolder 2939) --> 0x0 IDKEY_FDRTREEVIEWCONTENTS
Long IDKEY_xxx (WPFileSystem 4) --> 0x0
Data IDKEY_xxx (WPObject 11) size 32 -> 32
Data IDKEY_xxx (WPObject 12) size 400 -> 400
Data IDKEY_xxx (WPObject 4) size 8 -> 8
Strg IDKEY_xxx (WPFolder 2934) --> F:\OS2\BITMAP\PLASTER.BMP
IDKEY_FDRCNRBACKGROUND
Strg IDKEY_xxx (WPFolder 2921) --> NULL
Data IDKEY_xxx (WPFolder 2920) size 0 -> 259
Data IDKEY_xxx (WPFolder 2925) size 0 -> 107
Data IDKEY_xxx (WPFolder 2920) size 0 -> 260
Data IDKEY_xxx (WPFolder 2925) size 0 -> 107
Data IDKEY_xxx (WPFolder 2925) size 107 -> 107
Strg IDKEY_xxx (WPFolder 2921) --> F:\OS2\BITMAP\PLASTER.BMP
IDKEY_FDRCNRBACKGROUND
Data IDKEY_xxx (WPFolder 2938) size 8 -> 8
Long IDKEY_xxx (WPFolder 2939) --> 0x0 IDKEY_FDRTREEVIEWCONTENTS
*/
/*
* the following are apperently never queried
* (Warp 4 FP 8 German):
*/
/*
case IDKEY_FDRSORTATTRIBS:
case IDKEY_FDRSORTCLASS:
case IDKEY_FDRINVISCOLUMNS:
case IDKEY_FDRCONTENTATTR:
case IDKEY_FDRSNEAKYCOUNT:
case IDKEY_FDRCNRBACKGROUND:
case IDKEY_FDRBKGNDIMAGEFILE:
*/
} // end switch
}
return (brc);
}
/*
*@@ wpAddSettingsPages:
* call xfAddXFolderPages
*/
SOM_Scope BOOL SOMLINK xf_wpAddSettingsPages(XFolder *somSelf,
HWND hwndNotebook)
{
BOOL rc;
// PAGEINFO pi;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpAddSettingsPages");
rc = (XFolder_parent_WPFolder_wpAddSettingsPages(somSelf,
hwndNotebook));
if (rc)
rc = _xfAddXFolderPages(somSelf, hwndNotebook);
return (rc);
}
/*
* fncbSortInitPage:
* "Sort" page notebook callback function (notebook.c).
* Sets the controls on the page.
* The "Sort" callbacks are used both for the folder settings notebook page
* AND the respective "Sort" page in the "Workplace Shell" object, so we
* need to keep instance data and the XFolder Global Settings apart.
* We do this by examining the page ID in the notebook info struct.
*/
VOID fncbSortInitPage(PVOID pnbi, ULONG ulExtra) // notebook info struct
{
PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
HWND hwndListbox = WinWindowFromID(pcnbp->hwndPage,
ID_XSDI_SORTLISTBOX);
XFolderData *somThis = NULL;
if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
// if we're being called from a folder's notebook,
// get instance data
somThis = XFolderGetData(pcnbp->somSelf);
if (ulExtra & CBI_INIT)
{
if (pcnbp->pBackup == NULL)
{
// first call: backup instance data for "Undo" button;
// this memory will be freed automatically by the
// common notebook window function (notebook.c) when
// the notebook page is destroyed
pcnbp->pBackup = malloc(sizeof(XFolderData));
memcpy(pcnbp->pBackup, somThis, sizeof(XFolderData));
}
// hide the "Enable extended sort" checkbox, which is
// only visible in the "Workplace Shell" object
WinShowWindow(WinWindowFromID(pcnbp->hwndPage, ID_XSDI_REPLACESORT), FALSE);
}
}
if (ulExtra & CBI_INIT)
{
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByName);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByType);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByClass);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByRealName);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortBySize);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByWriteDate);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByAccessDate);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByCreationDate);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByExt);
WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortFoldersFirst);
}
if (somThis) {
// "folder" mode:
if (ulExtra & CBI_SET)
{
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
ALWAYS_SORT);
WinSendMsg(hwndListbox,
LM_SELECTITEM,
(MPARAM)DEFAULT_SORT,
(MPARAM)TRUE);
}
} else {
// "global" mode:
if (ulExtra & CBI_SET)
{
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLACESORT,
pGlobalSettings->ReplaceSort);
winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
pGlobalSettings->AlwaysSort);
WinSendMsg(hwndListbox,
LM_SELECTITEM,
(MPARAM)(pGlobalSettings->DefaultSort),
(MPARAM)TRUE);
}
if (ulExtra & CBI_ENABLE)
{
// disable items if extended sorting is off
winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SORTTEXT,
pGlobalSettings->ReplaceSort);
winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SORTLISTBOX,
pGlobalSettings->ReplaceSort);
winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
pGlobalSettings->ReplaceSort);
}
}
}
/*
* fncbSortItemChanged:
* "Sort" page notebook callback function (notebook.c).
* Reacts to changes of any of the dialog controls.
* The "Sort" callbacks are used both for the folder settings notebook page
* AND the respective "Sort" page in the "Workplace Shell" object, so we
* need to keep instance data and the XFolder GLobal Settings apart.
*/
MRESULT fncbSortItemChanged(PVOID pnbi,
USHORT usItemID, USHORT usNotifyCode,
ULONG ulExtra) // for checkboxes: contains new state
{
PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
BOOL fUpdate = TRUE;
switch (usItemID) {
case ID_XSDI_ALWAYSSORT:
case ID_XSDI_SORTLISTBOX: {
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
HWND hwndListbox = WinWindowFromID(pcnbp->hwndPage,
ID_XSDI_SORTLISTBOX);
// XFolderData *somThis = NULL;
if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
// if we're being called from a folder's notebook,
// change instance data
_xfSetFldrSort(pcnbp->somSelf,
// DefaultSort:
(USHORT)(WinSendMsg(hwndListbox,
LM_QUERYSELECTION,
(MPARAM)LIT_CURSOR,
MPNULL)),
// AlwaysSort:
(USHORT)(winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT))
);
} else {
BOOL bTemp;
pGlobalSettings->ReplaceSort =
winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLACESORT);
pGlobalSettings->DefaultSort =
(BYTE)WinSendMsg(hwndListbox,
LM_QUERYSELECTION,
(MPARAM)LIT_CURSOR,
MPNULL);
bTemp = winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT);
if (bTemp) {
USHORT usDefaultSort, usAlwaysSort;
_xfQueryFldrSort(_wpclsQueryActiveDesktop(_WPDesktop),
&usDefaultSort, &usAlwaysSort);
if (usAlwaysSort != 0)
{
// issue warning that this might also sort the Desktop
if (cmnMessageBoxMsg(pcnbp->hwndPage, 116, 133, MB_YESNO) == MBID_YES)
_xfSetFldrSort(_wpclsQueryActiveDesktop(_WPDesktop),
usDefaultSort, 0);
}
}
pGlobalSettings->AlwaysSort = bTemp;
}
break; }
case ID_XSDI_REPLACESORT: {
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
// "extended sorting on": exists on global page only
pGlobalSettings->ReplaceSort = ulExtra;
fncbSortInitPage(pnbi, CBI_ENABLE);
break; }
// control other than listbox:
case DID_UNDO:
// "Undo" button: restore backed up instance/global data
if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
// if we're being called from a folder's notebook,
// restore instance data
if (pcnbp->pBackup) {
XFolderData *Backup = (pcnbp->pBackup);
_xfSetFldrSort(pcnbp->somSelf,
Backup->DefaultSort,
Backup->AlwaysSort);
}
} else {
// global sort page:
cmnSetDefaultSettings(SP_FLDRSORT_GLOBAL);
}
fncbSortInitPage(pnbi, CBI_SET | CBI_ENABLE);
break;
case DID_DEFAULT:
// "Default" button:
if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
_xfSetFldrSort(pcnbp->somSelf, SET_DEFAULT, SET_DEFAULT);
} else {
cmnSetDefaultSettings(SP_FLDRSORT_GLOBAL);
}
fncbSortInitPage(pnbi, CBI_SET | CBI_ENABLE);
break;
default:
fUpdate = FALSE;
break;
}
if (fUpdate) {
if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
_wpSaveDeferred(pcnbp->somSelf);
// update our folder only
_xfForEachOpenView(pcnbp->somSelf, 0,
&fncbUpdateFolderSorts);
} else {
cmnStoreGlobalSettings();
// update all open folders
_xfclsForEachOpenView(_XFolder, 0,
&fncbUpdateFolderSorts);
}
}
return ((MPARAM)-1);
}
/*
*@@ wpAddFolderSortPage:
* this normally adds the "Sort" page to the folder
* settings notebook; if allowed, we will replace this
* by the new XFolder version of it
*/
SOM_Scope ULONG SOMLINK xf_wpAddFolderSortPage(XFolder *somSelf,
HWND hwndNotebook)
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpAddFolderSortPage");
if (pGlobalSettings->ReplaceSort)
{
// extended sorting enabled:
// check whether the "sort class" of the folder
// is WPFileSystem (which is the default); only
// then replace the "Sort" page with ours. Some
// WPS extensions define their own Details views,
// and we don't want to mess with that
if (_wpQueryFldrSortClass(somSelf) == _WPFileSystem)
{
PCREATENOTEBOOKPAGE pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
pcnbp->somSelf = somSelf;
pcnbp->hwndNotebook = hwndNotebook;
pcnbp->hmod = NLS_MODULE;
pcnbp->ulDlgID = ID_XSD_SETTINGS_FLDRSORT;
pcnbp->fMajorTab = TRUE;
pcnbp->pszName = pNLSStrings->pszSort;
pcnbp->ulDefaultHelpPanel = ID_XSH_SETTINGS_FLDRSORT;
// mark this page as "instance", because both
// the instance settings notebook and the
// "Workplace Shell" object use the same
// callbacks
pcnbp->ulPageID = SP_FLDRSORT_FLDR;
pcnbp->pfncbInitPage = fncbSortInitPage;
pcnbp->pfncbItemChanged = fncbSortItemChanged;
ntbInsertPage(pcnbp);
return (SETTINGS_PAGE_REMOVED);
}
}
return (XFolder_parent_WPFolder_wpAddFolderSortPage(somSelf,
hwndNotebook));
}
/*
*@@ wpFilterPopupMenu:
* this removes default menu entries according to the
* Global Settings.
*/
SOM_Scope ULONG SOMLINK xf_wpFilterPopupMenu(XFolder *somSelf,
ULONG ulFlags,
HWND hwndCnr,
BOOL fMultiSelect)
{
ULONG ulMenuFilter = 0;
// XFolderData *somThis = XFolderGetData(somSelf);
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderMethodDebug("XFolder","xf_wpFilterPopupMenu");
ulMenuFilter = XFolder_parent_WPFolder_wpFilterPopupMenu(somSelf,
ulFlags,
hwndCnr,
fMultiSelect);
#ifdef DEBUG_MENUS
_Pmpf(("XFolder::wpFilterPopupMenu parent flags:"));
_Pmpf((" CTXT_CRANOTHER %d", ulMenuFilter & CTXT_CRANOTHER));
#endif
// 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
return ((ulMenuFilter)
& ~(pGlobalSettings->DefaultMenuItems)
);
}
/*
*@@ wpModifyPopupMenu:
* this routine allows an object to modify a context
* menu. We add the various XFolder menu entries here
* by calling the common XFolder function in menus.c,
* which is also used by the XFldDisk class.
*/
SOM_Scope BOOL SOMLINK xf_wpModifyPopupMenu(XFolder *somSelf,
HWND hwndMenu,
HWND hwndCnr,
ULONG iPosition)
{
BOOL rc = TRUE;
HWND hwndCnr2 = hwndCnr;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpModifyPopupMenu");
// call parent
XFolder_parent_WPFolder_wpModifyPopupMenu(somSelf,hwndMenu,hwndCnr,iPosition);
if (hwndCnr == NULLHANDLE)
{
// bug in Warp 3: if the popup menu is requested
// on container whitespace, hwndCnr is passed as
// NULLHANDLE; we therefore use this ugly
// workaround
XFolderData *somThis = XFolderGetData(somSelf);
hwndCnr2 = _hwndCnrSaved; // set by WM_INITMENU in fnwpSubclassedFolderFrame
}
// call menu manipulator common to XFolder and XFldDisk (menus.c)
rc = mnuModifyPopupMenu(somSelf, hwndMenu, hwndCnr2, iPosition);
return (rc);
}
/*
*@@ wpMenuItemSelected:
* process input when any menu item was selected;
* we do this by calling the common XFolder function
* in menus.c, which is also used by XFldDisk.
*/
SOM_Scope BOOL SOMLINK xf_wpMenuItemSelected(XFolder *somSelf,
HWND hwndFrame,
ULONG ulMenuId)
{
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpMenuItemSelected");
// call the menu item checker common to XFolder and XFldDisk
// (menus.c); this returns TRUE if one of the manipulated
// menu items was selected
if (mnuMenuItemSelected(somSelf, hwndFrame, ulMenuId))
return (TRUE);
else
// none of our menu items: pass on to parent
return (XFolder_parent_WPFolder_wpMenuItemSelected(somSelf, hwndFrame, ulMenuId));
}
/*
*@@ wpMenuItemHelpSelected:
* display help for a context menu item.
*/
SOM_Scope BOOL SOMLINK xf_wpMenuItemHelpSelected(XFolder *somSelf,
ULONG MenuId)
{
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpMenuItemHelpSelected");
// call the common help processor in menus.c;
// if this returns TRUE, help was requested for one
// of the new menu items
if (mnuMenuItemHelpSelected(somSelf, MenuId))
return TRUE;
else
// else: none of our menu items, call default
return (XFolder_parent_WPFolder_wpMenuItemHelpSelected(somSelf,
MenuId));
}
/*
*@@ wpOpen:
* this instance method opens a new folder view.
* This is one of the main hooks where the XFolder
* features are inserted into the WPS.
* We call the parent method first (which will create
* the folder window) and then subclass the
* resulting frame window with the new
* fnwpSubclassedFolderFrame window procedure.
*/
SOM_Scope HWND SOMLINK xf_wpOpen(XFolder *somSelf, HWND hwndCnr,
ULONG ulView, ULONG param)
{
HWND hwndNewFrame;
XFolderMethodDebug("XFolder","xf_wpOpen");
// have parent do the window creation
hwndNewFrame = XFolder_parent_WPFolder_wpOpen(somSelf, hwndCnr, ulView, param);
if ( (ulView == OPEN_CONTENTS)
|| (ulView == OPEN_TREE)
|| (ulView == OPEN_DETAILS)
)
{
PSUBCLASSEDLISTITEM psli;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(somSelf);
// subclass the new folder frame window
psli = cmnSubclassFolderFrame(hwndNewFrame, somSelf, somSelf, ulView);
// change the window title to full path, if allowed
if ( (_bFullPath == 1)
|| ((_bFullPath == 2) && (pGlobalSettings->FullPath))
)
SetOneFrameWndTitle(somSelf, hwndNewFrame);
// add status bar, if allowed:
// 1) status bar only if allowed for the current folder
if ( (_bStatusBar == STATUSBAR_ON)
|| ( (_bStatusBar == STATUSBAR_DEFAULT)
&& (pGlobalSettings->StatusBar)
)
)
// 2) no status bar for active Desktop
if (somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
// 3) check that subclassed list item is valid
if (psli)
// 4) status bar only if allowed for the current view type
if ( ( (ulView == OPEN_CONTENTS)
&& (pGlobalSettings->SBForViews & SBV_ICON)
)
|| ( (ulView == OPEN_TREE)
&& (pGlobalSettings->SBForViews & SBV_TREE)
)
|| ( (ulView == OPEN_DETAILS)
&& (pGlobalSettings->SBForViews & SBV_DETAILS)
)
)
_xfShowStatusBar(somSelf, psli, TRUE);
// replace sort stuff
if (pGlobalSettings->ReplaceSort)
{
hwndCnr = xwpsQueryCnrFromFrame(hwndNewFrame);
if (hwndCnr)
_xfSetCnrSort(somSelf, hwndCnr, FALSE);
}
}
return (hwndNewFrame);
}
/*
*@@ wpRefresh:
* this method updates a folder; after doing
* this, we will also update the title of the
* window and maybe status bars.
*/
SOM_Scope BOOL SOMLINK xf_wpRefresh(XFolder *somSelf, ULONG ulView,
PVOID pReserved)
{
BOOL rc;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpRefresh");
rc = XFolder_parent_WPFolder_wpRefresh(somSelf, ulView, pReserved);
_xfForEachOpenView(somSelf,
(ULONG)2, // update
(PFNWP)fncbUpdateStatusBars);
xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
return rc;
}
/*
*@@ wpSetFldrAttr:
* this sets new container attributes
* (those CV_* flags) for the specified folder view
* (OPEN_CONTENTS, OPEN_TREE, OPEN_DETAILS)
*/
SOM_Scope BOOL SOMLINK xf_wpSetFldrAttr(XFolder *somSelf, ULONG Attr,
ULONG ulView)
{
XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpSetFldrAttr");
#ifdef DEBUG_SORT
{
CHAR szInfo[300] = "";
_Pmpf(("wpSetFldrAttr for %s", _wpQueryTitle(somSelf)));
if (Attr & CV_ICON)
strcpy(szInfo, "CV_ICON ");
if (Attr & CV_NAME)
strcat(szInfo, "CV_NAME ");
if (Attr & CV_TEXT)
strcat(szInfo, "CV_TEXT ");
if (Attr & CV_TREE)
strcat(szInfo, "CV_TREE ");
if (Attr & CV_DETAIL)
strcat(szInfo, "CV_DETAIL ");
if (Attr & CV_MINI)
strcat(szInfo, "CV_MINI ");
if (Attr & CV_FLOW)
strcat(szInfo, "CV_FLOW ");
if (Attr & CA_OWNERDRAW)
strcat(szInfo, "CA_OWNERDRAW ");
if (Attr & CA_OWNERPAINTBACKGROUND)
strcat(szInfo, "CA_OWNERPAINTBACKGROUND ");
_Pmpf((" Flags: %s", szInfo));
}
#endif
return (XFolder_parent_WPFolder_wpSetFldrAttr(somSelf, Attr,
ulView));
}
/*
*@@ wpQueryFldrAttr:
* this returns the current container attributes
* (those CV_* flags) for the specified folder view
* (OPEN_CONTENTS, OPEN_TREE, OPEN_DETAILS)
*/
SOM_Scope ULONG SOMLINK xf_wpQueryFldrAttr(XFolder *somSelf,
ULONG ulView)
{
ULONG ulAttr = 0;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpQueryFldrAttr");
ulAttr = XFolder_parent_WPFolder_wpQueryFldrAttr(somSelf,
ulView);
#ifdef DEBUG_SORT
{
CHAR szInfo[300] = "";
_Pmpf(("wpQueryFldrAttr for %s", _wpQueryTitle(somSelf)));
if (ulAttr & CV_ICON)
strcpy(szInfo, "CV_ICON ");
if (ulAttr & CV_NAME)
strcat(szInfo, "CV_NAME ");
if (ulAttr & CV_TEXT)
strcat(szInfo, "CV_TEXT ");
if (ulAttr & CV_TREE)
strcat(szInfo, "CV_TREE ");
if (ulAttr & CV_DETAIL)
strcat(szInfo, "CV_DETAIL ");
if (ulAttr & CV_MINI)
strcat(szInfo, "CV_MINI ");
if (ulAttr & CV_FLOW)
strcat(szInfo, "CV_FLOW ");
if (ulAttr & CA_OWNERDRAW)
strcat(szInfo, "CA_OWNERDRAW ");
if (ulAttr & CA_OWNERPAINTBACKGROUND)
strcat(szInfo, "CA_OWNERPAINTBACKGROUND ");
_Pmpf((" Flags: %s", szInfo));
}
#endif
return (ulAttr);
}
/*
*@@ wpAddToContent:
* this method is overridden to intercept the
* notification of the "Added an object to a folder"
* event for subclasses that define their own folder view.
* The parent must always be called.
*/
SOM_Scope BOOL SOMLINK xf_wpAddToContent(XFolder *somSelf,
WPObject* Object)
{
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpAddToContent");
#ifdef DEBUG_CNRCONTENT
_Pmpf(("wpAddToContent, folder: %s, object: %s",
_wpQueryTitle(somSelf),
_wpQueryTitle(Object)));
#endif
return (XFolder_parent_WPFolder_wpAddToContent(somSelf, Object));
}
/*
*@@ wpDeleteFromContent:
* this method should be overridden to intercept the
* notification of the "Removed an object from a folder"
* event for subclasses that define their own folder view.
* The parent must always be called.
*/
SOM_Scope BOOL SOMLINK xf_wpDeleteFromContent(XFolder *somSelf,
WPObject* Object)
{
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpDeleteFromContent");
#ifdef DEBUG_CNRCONTENT
_Pmpf(("wpDeleteFromContent, folder: %s, object: %s",
_wpQueryTitle(somSelf),
_wpQueryTitle(Object)));
#endif
return (XFolder_parent_WPFolder_wpDeleteFromContent(somSelf,
Object));
}
/*
*@@ wpStoreIconPosData:
* this method is documented only for Warp 4
* (but exists in Warp 3 also, see WPFOLDER.H);
* it is called when an open folder in icon or
* details view is closed.
* The WPS then apparently saves the .ICONPOS
* data to disk; we only override this method to be
* notified that we need to to update our
* icon order data (xfUpdateOrderedContent).
*/
SOM_Scope BOOL SOMLINK xf_wpStoreIconPosData(XFolder *somSelf,
PICONPOS pIconPos,
ULONG cbSize)
{
BOOL rc;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpStoreIconPosData");
rc = (XFolder_parent_WPFolder_wpStoreIconPosData(somSelf,
pIconPos,
cbSize));
#ifdef DEBUG_SORT
_Pmpf(("wpStoreIconPosData -- pIconPos: 0x%lX, ulSize: 0x%lX",
pIconPos, cbSize));
#endif
xthrPostWorkerMsg(WOM_INVALIDATEORDEREDCONTENT,
(MPARAM)somSelf, MPNULL);
return (rc);
}
/*
*@@ wpMoveObject:
* this is called when the folder is moved to a
* different location; we then need to update
* the titles of this folder AND of possibly open
* subfolders with the full path; we pass this
* to the Worker thread
*/
SOM_Scope BOOL SOMLINK xf_wpMoveObject(XFolder *somSelf,
WPFolder* Folder)
{
BOOL rc;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpMoveObject");
/* call the parent method first, which will actually move the
folder */
rc = XFolder_parent_WPFolder_wpMoveObject(somSelf, Folder);
xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
return rc;
}
/*
*@@ wpSetTitle:
* this is called when the folder is renamed.
* We then need to update the titles of this
* folder AND of possibly open subfolders with
* the full path; we pass this task to the Worker
* thread, since it may take a while
*/
SOM_Scope BOOL SOMLINK xf_wpSetTitle(XFolder *somSelf, PSZ pszNewTitle)
{
BOOL rc;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpSetTitle");
rc = XFolder_parent_WPFolder_wpSetTitle(somSelf, pszNewTitle);
if (_wpFindUseItem(somSelf, USAGE_OPENVIEW, NULL))
xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
return (rc);
}
/*
*@@ wpSetFldrSort:
* apparently, this method normally gets called by the
* WPS every time it tries to sort a folder. That is,
* when one of the "Sort" menu items is selected or when
* the folder is sorted for another reason, e.g. because
* "Always sort" is on and a file in the folder was
* renamed.
*
* The WPS ref. says about this method:
* "This instance method sets the sort attributes on
* the folder window and saves those values in the
* instance data. Note: This method only rearranges a
* folder open in icon view. If (pSortRecord == NULL),
* the values are reset to the default sort values."
*
* However, the description of this method in the WPS
* ref. is complete garbage. The SORTFASTINFO structure
* described there is obviously not used, but some
* undocumented data instead. (I guess that's why IBM
* uses a PVOID here, so they need not apologize.)
* Also, this method rearranges _all_ open folders, not
* just icons views.
*
* Anyway, if XFolder extended sorting is enabled,
* we can intercept this method call to prevent the
* WPS from sorting the container. We will then not
* call the default method, but our own one instead.
* Since XFolder completely takes over the other sort
* functions, this method probably only gets called
* when files are renamed any more.
*/
SOM_Scope BOOL SOMLINK xf_wpSetFldrSort(XFolder *somSelf, PVOID pSortRecord,
ULONG ulView, ULONG ulType)
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
if (pGlobalSettings->ReplaceSort) {
HWND hwndFrame = xwpsQueryFrameFromView(somSelf, ulView);
if (hwndFrame) {
HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
if (hwndCnr) {
_xfSetCnrSort(somSelf, hwndCnr,
TRUE); // enfore cnr sort
return (TRUE);
}
}
}
return (XFolder_parent_WPFolder_wpSetFldrSort(somSelf,
pSortRecord,
ulView,
ulType));
}
/*
*@@ wpQueryDefaultHelp:
* this instance method specifies the default
* help panel for this instance; XFolder will
* return something different for the
* Config folder and its subfolders.
*/
SOM_Scope BOOL SOMLINK xf_wpQueryDefaultHelp(XFolder *somSelf,
PULONG pHelpPanelId,
PSZ HelpLibrary)
{
BOOL rc;
// XFolderData *somThis = XFolderGetData(somSelf);
XFolderMethodDebug("XFolder","xf_wpQueryDefaultHelp");
if (xwpsResidesBelow(somSelf,
_wpclsQueryFolder(_WPFolder, XFOLDER_CONFIGID, TRUE)))
{
// somSelf is in the config folder hierarchy:
// display help for config folders
strncpy(HelpLibrary, cmnQueryHelpLibrary(), CCHMAXPATH);
*pHelpPanelId = ID_XMH_CONFIGFOLDER;
rc = TRUE;
} else
rc = (XFolder_parent_WPFolder_wpQueryDefaultHelp(somSelf,
pHelpPanelId,
HelpLibrary));
return (rc);
}
/* ******************************************************************
* *
* here come the XFolder class methods *
* *
********************************************************************/
/*
*@@ xfclsForEachOpenView:
* this class method goes through all open folder windows and calls
* pfnwpCallback for each open view of each open folder.
*
* The following params will be passed to pfnwpCallback:
* -- hwnd HWND hwndView the hwnd of the view frame window;
* -- mp1 ULONG ulView the view type (as def'd in wpOpen)
* -- mp2 XFolder* pFolder the currently open folder.
*
* This method does not return until all views have been processed.
* You might want to call this method in a different thread if the task
* will take long.
*/
SOM_Scope BOOL SOMLINK xfM_xfclsForEachOpenView(M_XFolder *somSelf,
ULONG ulMsg,
PFNWP pfnwpCallback)
{
XFolder *pFolder;
// M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_xfclsForEachOpenView");
for ( pFolder = _wpclsQueryOpenFolders(somSelf, NULL, QC_FIRST, FALSE);
pFolder;
pFolder = _wpclsQueryOpenFolders(somSelf, pFolder, QC_NEXT, FALSE))
{
if (_somIsA(pFolder, _WPFolder))
{
_xfForEachOpenView(pFolder, ulMsg, pfnwpCallback);
}
}
return TRUE;
}
/*
*@@ xfclsQueryFavoriteFolder:
* This returns "favorite" folders.
* If pFolder == NULL, the first favorite folder is returned,
* otherwise the favorite folder which comes after pFolder
* in the favorite folder list.
* This returns NULL if no more folders are found.
*/
SOM_Scope XFolder* SOMLINK xfM_xfclsQueryFavoriteFolder(M_XFolder *somSelf,
XFolder* pFolder)
{
BOOL fSemOwned = FALSE;
M_XFolderData *somThis = M_XFolderGetData(somSelf);
PCONTENTMENULISTITEM pliFavoriteFolders = pcmliFavoriteFolders,
pItem;
M_XFolderMethodDebug("M_XFolder","xfM_xfclsQueryFavoriteFolder");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
if (pliFavoriteFolders == NULL)
{
// if the list of favorite folders has not yet been built
// in the class data, we will do this now
CHAR szFavorites[1000], szDummy[1000];
PSZ pszFavorites;
// ULONG rc;
PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
"", &szFavorites, sizeof(szFavorites));
pszFavorites = szFavorites;
do {
HOBJECT hObject;
WPFolder *pFolder2;
sscanf(pszFavorites, "%lX %s", &hObject, &szDummy);
pFolder2 = _wpclsQueryObject(_WPFolder, hObject);
if (pFolder2) {
if (xwpsCheckObject(pFolder2))
if (_somIsA(pFolder2, _WPFolder))
{
PCONTENTMENULISTITEM pNew = malloc(sizeof(CONTENTMENULISTITEM));
pNew->pFolder = pFolder2;
lstAppendItem((PLISTITEM*)&pliFavoriteFolders, NULL,
(PLISTITEM)pNew);
}
}
pszFavorites += 6;
} while (strlen(pszFavorites) > 0);
pcmliFavoriteFolders = pliFavoriteFolders;
}
pItem = pliFavoriteFolders;
if (pFolder) {
// folder given as param: look for this folder
// and return the following in the list
while (pItem)
if (pItem->pFolder == pFolder) {
pItem = pItem->pNext;
break;
}
else
pItem = pItem->pNext;
} // else: pItem == pliFavoriteFolders
}
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned) {
DosReleaseMutexSem(hmtxFavoriteFolders);
fSemOwned = FALSE;
}
if (pItem)
return (pItem->pFolder);
else
return (NULL);
}
/*
*@@ xfclsQueryQuickOpenFolder:
* This returns folders which have the "QuickOpen" flag on.
* If pFolder == NULL, the first such folder is returned,
* otherwise the folder which comes after pFolder
* in the quick-open folder list.
* This returns NULL if no more folders are found.
*/
SOM_Scope XFolder* SOMLINK xfM_xfclsQueryQuickOpenFolder(M_XFolder *somSelf,
XFolder* pFolder)
{
BOOL fSemOwned = FALSE;
M_XFolderData *somThis = M_XFolderGetData(somSelf);
PCONTENTMENULISTITEM pliQuickOpenFolders = pcmliQuickOpenFolders,
pItem;
M_XFolderMethodDebug("M_XFolder","xfM_xfclsQueryQuickOpenFolder");
TRY_LOUD(excpt1)
{
fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
if (fSemOwned)
{
if (pliQuickOpenFolders == NULL)
{
// if the list of QuickOpen folders has not yet been built
// in the class data, we will do this now
CHAR szQuickOpen[1000], szDummy[1000];
PSZ pszQuickOpen;
// ULONG rc;
PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
"", &szQuickOpen, sizeof(szQuickOpen));
pszQuickOpen = szQuickOpen;
do {
HOBJECT hObject;
WPFolder *pFolder2;
sscanf(pszQuickOpen, "%lX %s", &hObject, &szDummy);
pFolder2 = _wpclsQueryObject(_WPFolder, hObject);
if (pFolder2) {
if (xwpsCheckObject(pFolder2))
if (_somIsA(pFolder2, _WPFolder))
{
PCONTENTMENULISTITEM pNew = malloc(sizeof(CONTENTMENULISTITEM));
pNew->pFolder = pFolder2;
lstAppendItem((PLISTITEM*)&pliQuickOpenFolders, NULL,
(PLISTITEM)pNew);
}
}
pszQuickOpen += 6;
} while (strlen(pszQuickOpen) > 0);
pcmliQuickOpenFolders = pliQuickOpenFolders;
}
pItem = pliQuickOpenFolders;
if (pFolder) {
// folder given as param: look for this folder
// and return the following in the list
while (pItem)
if (pItem->pFolder == pFolder) {
pItem = pItem->pNext;
break;
}
else
pItem = pItem->pNext;
} // else: pItem == pliQuickOpenFolders
}
}
CATCH(excpt1) { } END_CATCH;
if (fSemOwned)
{
DosReleaseMutexSem(hmtxQuickOpenFolders);
fSemOwned = FALSE;
}
if (pItem)
return (pItem->pFolder);
else
return (NULL);
}
/*
*@@ xfclsSetDefaultTitle:
* changes the default title to pszNewTitle. The default
* title appears in the third column in folder Details
* views.
*/
SOM_Scope BOOL SOMLINK xfM_xfclsSetDefaultTitle(M_XFolder *somSelf,
PSZ pszNewTitle)
{
M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_xfclsSetDefaultTItle");
strncpy(_szDefaultTitle, pszNewTitle, sizeof(_szDefaultTitle)-1);
return (PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_DEFAULTTITLE,
_szDefaultTitle));
}
/*
*@@ wpclsInitData:
* this initializes the WPFolder / XFolder class as a whole;
* we need to call the parent and then set some XFolder
* data
*/
SOM_Scope void SOMLINK xfM_wpclsInitData(M_XFolder *somSelf)
{
PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_wpclsInitData");
M_XFolder_parent_M_WPFolder_wpclsInitData(somSelf);
if (hmtxFavoriteFolders == NULLHANDLE) {
// first call:
// create mutex semaphores for serialized access
cmnInitPSLI();
if (DosCreateMutexSem(NULL,
&hmtxFavoriteFolders, 0, FALSE) != NO_ERROR)
{
DosBeep(100, 300);
hmtxFavoriteFolders = -1;
}
if (DosCreateMutexSem(NULL,
&hmtxQuickOpenFolders, 0, FALSE) != NO_ERROR)
{
DosBeep(100, 300);
hmtxQuickOpenFolders = -1;
}
// initialize other data
pcmliFavoriteFolders = NULL;
pcmliQuickOpenFolders = NULL;
PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_DEFAULTTITLE,
"XFolder", &(_szDefaultTitle), sizeof(_szDefaultTitle));
cmnLoadFolderHotkeys();
// register class for supplementary object
// windows, which are created for each folder view
// which is opened
WinRegisterClass(WinQueryAnchorBlock(HWND_DESKTOP),
WNDCLASS_SUPPLOBJECT, // class name
(PFNWP)fnwpSupplObject, // Window procedure
0, // class style
4); // extra window words for SUBCLASSEDLISTITEM
// pointer (see cmnSubclassFolderFrame)
}
}
/*
*@@ wpclsCreateDefaultTemplates:
* this is called by the system 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, but since we are replacing the class,
* we will have to suppress this in order not to
* crowd the Templates folder.
*/
SOM_Scope BOOL SOMLINK xfM_wpclsCreateDefaultTemplates(M_XFolder *somSelf,
WPObject* Folder)
{
// M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_wpclsCreateDefaultTemplates");
// we only override this class method if it is
// being called for the XFolder 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.
if (somSelf == _XFolder)
return (TRUE);
// means that the Templates folder should _not_ create templates
// by itself; we pretend that we've done this
else
return (M_XFolder_parent_M_WPFolder_wpclsCreateDefaultTemplates(somSelf,
Folder));
}
/*
*@@ wpclsQueryTitle:
* tell the WPS the new class name: XFolder or whatever
* was specified in the "Workplace Shell" object
*/
SOM_Scope PSZ SOMLINK xfM_wpclsQueryTitle(M_XFolder *somSelf)
{
M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xf_wpclsQueryTitle");
if (somSelf == _XFolder)
return (_szDefaultTitle);
else
return (M_XFolder_parent_M_WPFolder_wpclsQueryTitle(somSelf));
}
/*
*@@ wpclsQueryIconData:
* give folders a new default closed icon, if the
* global settings allow this.
* This is loaded from /ICONS/ICONS.DLL.
* Unfortunately, it appears to be impossible to
* dynamically load default icons as specified for
* the ICONINFO structure in the WPS reference.
* ICON_FILE at least doesn't work, and the format
* for ICON_DATA is not explained. So we have to
* use a DLL here.
*/
SOM_Scope ULONG SOMLINK xfM_wpclsQueryIconData(M_XFolder *somSelf,
PICONINFO pIconInfo)
{
ULONG ulrc;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
// M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_wpclsQueryIconData");
if (pGlobalSettings->ReplIcons)
{
// icon replacements allowed:
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->hmod = cmnQueryIconsDLL();
pIconInfo->resid = 100;
}
ulrc = sizeof(ICONINFO);
}
else
// icon replacements not allowed: call default
ulrc = M_XFolder_parent_M_WPFolder_wpclsQueryIconData(somSelf,
pIconInfo);
return (ulrc);
}
/*
*@@ wpclsQueryIconDataN:
* give folders a new default open icon, if the
* global settings allow this.
* See the notes for wpclsQueryIconData.
*/
SOM_Scope ULONG SOMLINK xfM_wpclsQueryIconDataN(M_XFolder *somSelf,
ICONINFO* pIconInfo,
ULONG ulIconIndex)
{
ULONG ulrc;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
// M_XFolderData *somThis = M_XFolderGetData(somSelf);
M_XFolderMethodDebug("M_XFolder","xfM_wpclsQueryIconDataN");
if (pGlobalSettings->ReplIcons)
{
// icon replacements allowed:
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->hmod = cmnQueryIconsDLL();
pIconInfo->resid = 101;
}
ulrc = sizeof(ICONINFO);
}
else
// icon replacements not allowed: call default
ulrc = M_XFolder_parent_M_WPFolder_wpclsQueryIconDataN(somSelf,
pIconInfo,
ulIconIndex);
return (ulrc);
}
/* ******************************************************************
* *
* here come the XFldStartup methods *
* *
********************************************************************/
/*
*@@ wpModifyPopupMenu:
* add a "Process content" menu item to this
* popup menu; the other menu items are inherited
* from XFolder
*/
SOM_Scope BOOL SOMLINK xfstup_wpModifyPopupMenu(XFldStartup *somSelf,
HWND hwndMenu,
HWND hwndCnr,
ULONG iPosition)
{
BOOL rc;
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
/* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
XFldStartupMethodDebug("XFldStartup","xfstup_wpModifyPopupMenu");
rc = XFldStartup_parent_XFolder_wpModifyPopupMenu(somSelf,
hwndMenu,
hwndCnr,
iPosition);
winhInsertMenuSeparator(hwndMenu, MIT_END,
(pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_SEPARATOR));
winhInsertMenuItem(hwndMenu,
MIT_END,
(pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_PROCESSCONTENT),
pNLSStrings->pszProcessContent,
MIS_TEXT, 0);
return (rc);
}
/*
*@@ wpMenuItemSelected:
* react to selection of "Process content"
* menu item
*/
SOM_Scope BOOL SOMLINK xfstup_wpMenuItemSelected(XFldStartup *somSelf,
HWND hwndFrame,
ULONG ulMenuId)
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
/* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
XFldStartupMethodDebug("XFldStartup","xfstup_wpMenuItemSelected");
if ( (ulMenuId - pGlobalSettings->VarMenuOffset) == ID_XFMI_OFS_PROCESSCONTENT ) {
if (cmnMessageBoxMsg((hwndFrame) ? hwndFrame : HWND_DESKTOP,
116, 138, MB_YESNO | MB_DEFBUTTON2)
== MBID_YES) {
xthrPostWorkplaceObjectMsg(XOM_BEGINSTARTUP, MPNULL, MPNULL);
}
return (TRUE);
} else
return (XFldStartup_parent_XFolder_wpMenuItemSelected(somSelf,
hwndFrame,
ulMenuId));
}
/*
*@@ wpMenuItemHelpSelected:
* display help for "Process content"
* menu item
*/
SOM_Scope BOOL SOMLINK xfstup_wpMenuItemHelpSelected(XFldStartup *somSelf,
ULONG MenuId)
{
/* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
XFldStartupMethodDebug("XFldStartup","xfstup_wpMenuItemHelpSelected");
return (XFldStartup_parent_XFolder_wpMenuItemHelpSelected(somSelf,
MenuId));
}
/*
*@@ wpQueryDefaultHelp:
* this instance method specifies the default
* help panel for this instance; display some
* help for the Startup folder
*/
SOM_Scope BOOL SOMLINK xfstup_wpQueryDefaultHelp(XFldStartup *somSelf,
PULONG pHelpPanelId,
PSZ HelpLibrary)
{
/* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
XFldStartupMethodDebug("XFldStartup","xfstup_wpQueryDefaultHelp");
strcpy(HelpLibrary, cmnQueryHelpLibrary());
*pHelpPanelId = ID_XMH_STARTUPSHUTDOWN;
return (TRUE);
/* return (XFldStartup_parent_XFolder_wpQueryDefaultHelp(somSelf,
pHelpPanelId,
HelpLibrary)); */
}
/*
*@@ wpclsQueryTitle:
* tell the WPS the new class name: "XFolder Startup"
*/
SOM_Scope PSZ SOMLINK xfstupM_wpclsQueryTitle(M_XFldStartup *somSelf)
{
/* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryTitle");
return ("XFolder Startup");
// return (M_XFldStartup_parent_M_XFolder_wpclsQueryTitle(somSelf));
}
/*
*@@ wpclsQueryStyle:
* we return a flag so that no templates are created
* for the Startup folder
*/
SOM_Scope ULONG SOMLINK xfstupM_wpclsQueryStyle(M_XFldStartup *somSelf)
{
/* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryStyle");
return (M_XFldStartup_parent_M_XFolder_wpclsQueryStyle(somSelf)
| CLSSTYLE_NEVERTEMPLATE
| CLSSTYLE_NEVERCOPY
// | CLSSTYLE_NEVERDELETE
);
}
/*
*@@ wpclsQueryIconData:
* give the Startup folder a new closed icon
*/
SOM_Scope ULONG SOMLINK xfstupM_wpclsQueryIconData(M_XFldStartup *somSelf,
PICONINFO pIconInfo)
{
/* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryIconData");
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->resid = ID_STARTICON1;
pIconInfo->hmod = modQueryHandle();
}
return (sizeof(ICONINFO));
/* return (M_XFldStartup_parent_M_XFolder_wpclsQueryIconData(somSelf,
pIconInfo)); */
}
/*
*@@ wpclsQueryIconDataN:
* give the Startup folder a new animated icon
*/
SOM_Scope ULONG SOMLINK xfstupM_wpclsQueryIconDataN(M_XFldStartup *somSelf,
ICONINFO* pIconInfo,
ULONG ulIconIndex)
{
/* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryIconDataN");
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->resid = ID_STARTICON2;
pIconInfo->hmod = modQueryHandle();
}
return (sizeof(ICONINFO));
/* return (M_XFldStartup_parent_M_XFolder_wpclsQueryIconDataN(somSelf,
pIconInfo,
ulIconIndex)); */
}
/* ******************************************************************
* *
* here come the XFldShutdown methods *
* *
********************************************************************/
/*
*@@ wpQueryDefaultHelp:
* this instance method specifies the default
* help panel for this instance; display some
* help for the Shutdown folder
*/
SOM_Scope BOOL SOMLINK xfshut_wpQueryDefaultHelp(XFldShutdown *somSelf,
PULONG pHelpPanelId,
PSZ HelpLibrary)
{
/* XFldShutdownData *somThis = XFldShutdownGetData(somSelf); */
XFldShutdownMethodDebug("XFldShutdown","xfshut_wpQueryDefaultHelp");
strcpy(HelpLibrary, cmnQueryHelpLibrary());
*pHelpPanelId = ID_XMH_STARTUPSHUTDOWN;
return (TRUE);
/* return (XFldShutdown_parent_XFolder_wpQueryDefaultHelp(somSelf,
pHelpPanelId,
HelpLibrary)); */
}
/*
*@@ wpclsQueryTitle:
* tell the WPS the new class name: "XFolderShutdown"
*/
SOM_Scope PSZ SOMLINK xfshutM_wpclsQueryTitle(M_XFldShutdown *somSelf)
{
/* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryTitle");
return ("XFolder Shutdown");
// return (M_XFldShutdown_parent_M_XFolder_wpclsQueryTitle(somSelf));
}
/*
*@@ wpclsQueryStyle:
* we return a flag so that no templates are created
* for the Shutdown folder
*/
SOM_Scope ULONG SOMLINK xfshutM_wpclsQueryStyle(M_XFldShutdown *somSelf)
{
/* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryStyle");
return (M_XFldShutdown_parent_M_XFolder_wpclsQueryStyle(somSelf)
| CLSSTYLE_NEVERTEMPLATE
| CLSSTYLE_NEVERCOPY
// | CLSSTYLE_NEVERDELETE
);
}
/*
*@@ wpclsQueryIconData:
* give the Shutdown folder a new closed icon
*/
SOM_Scope ULONG SOMLINK xfshutM_wpclsQueryIconData(M_XFldShutdown *somSelf,
PICONINFO pIconInfo)
{
/* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryIconData");
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->resid = ID_SHUTICON1;
pIconInfo->hmod = modQueryHandle();
}
return (sizeof(ICONINFO));
/* return (M_XFldShutdown_parent_M_XFolder_wpclsQueryIconData(somSelf,
pIconInfo)); */
}
/*
*@@ wpclsQueryIconDataN:
* give the Shutdown folder a new animated icon
*/
SOM_Scope ULONG SOMLINK xfshutM_wpclsQueryIconDataN(M_XFldShutdown *somSelf,
ICONINFO* pIconInfo,
ULONG ulIconIndex)
{
/* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryIconDataN");
if (pIconInfo) {
pIconInfo->fFormat = ICON_RESOURCE;
pIconInfo->resid = ID_SHUTICON2;
pIconInfo->hmod = modQueryHandle();
}
return (sizeof(ICONINFO));
/* return (M_XFldShutdown_parent_M_XFolder_wpclsQueryIconDataN(somSelf,
pIconInfo,
ulIconIndex)); */
}
/* ******************************************************************
* *
* here come all the XFolder window procedures *
* *
********************************************************************/
/*
*@@ fnwpStatusBar:
* since the status bar is just created as a static frame
* control, it is subclassed (by XFolder::xfShowStatusBar),
* and this is the wnd proc for this.
* This handles the new STBM_UPDATESTATUSBAR message (which
* is posted any time the status bar needs to be updated)
* and intercepts WM_TIMER and WM_PAINT.
*/
MRESULT EXPENTRY fnwpStatusBar(HWND hwndBar, ULONG msg, MPARAM mp1, MPARAM mp2)
{
PSTATUSBARDATA psbd = (PSTATUSBARDATA)WinQueryWindowULong(hwndBar, QWL_USER);
MRESULT mrc = 0;
PGLOBALSETTINGS pGlobalSettings =
cmnQueryGlobalSettings();
if (psbd)
{
PFNWP pfnwpStatusBarOriginal = psbd->pfnwpStatusBarOriginal;
switch(msg)
{
/*
* STBM_UPDATESTATUSBAR:
* mp1: MPNULL,
* mp2: MPNULL
* Update status bar text. We will set a timer
* for a short delay to filter out repetitive
* messages here.
* This timer is "one-shot" in that it will be
* started here and stopped as soon as WM_TIMER
* is received.
*/
case STBM_UPDATESTATUSBAR: {
if (psbd->idTimer == 0) {
// only if timer is not yet running: start it now
psbd->idTimer = WinStartTimer(WinQueryAnchorBlock(hwndBar),
hwndBar,
1,
100); // delay: 100 ms
}
break; }
/*
* WM_TIMER:
* a timer is started by STBM_UPDATESTATUSBAR
* to avoid flickering;
* we now compose the actual text to be displayed
*/
case WM_TIMER: {
CHAR szText[1000];
TRY_LOUD(excpt1)
{
// stop timer (it's just for one shot)
WinStopTimer(WinQueryAnchorBlock(hwndBar), hwndBar, 1);
psbd->idTimer = 0;
// if we're not fully populated yet, start timer again and quit;
// otherwise we would display false information.
// We need an extra flag in the status bar data because the
// FOI_POPULATEDWITHALL is reset to 0 by the WPS for some reason
// when an object is deleted from an open folder, and no further
// status bar updates would occur then
if (psbd->fFolderPopulated == FALSE) {
ULONG ulFlags = _wpQueryFldrFlags(psbd->somSelf);
#ifdef DEBUG_STATUSBARS
_Pmpf(( " Folder flags: %lX", ulFlags ));
_Pmpf(( " View: %s",
(psbd->psli->ulView == OPEN_TREE) ? "Tree"
: (psbd->psli->ulView == OPEN_CONTENTS) ? "Content"
: (psbd->psli->ulView == OPEN_DETAILS) ? "Details"
: "unknown"
));
#endif
// for tree views, check if folder is populated with folders;
// otherwise check for populated with all
if ( ( (psbd->psli->ulView == OPEN_TREE)
&& ((ulFlags & FOI_POPULATEDWITHFOLDERS) !=0)
)
|| ((ulFlags & FOI_POPULATEDWITHALL) != 0)
)
{
psbd->fFolderPopulated = TRUE;
} else {
// folder not yet populated:
// restart timer with a lower frequency
// to have this checked again
psbd->idTimer = WinStartTimer(WinQueryAnchorBlock(hwndBar),
hwndBar,
1,
300); // this time, use 300 ms
// and stop
break;
}
}
// OK:
// translate the template text (szText) into something
// meaningful (statbars.c)
stbComposeText(psbd->somSelf,
psbd->psli->hwndCnr, // cnr hwnd in frame wnd struct
szText, sizeof(szText));
}
CATCH(excpt1)
{
strcpy(szText, "*** error composing text");
} END_CATCH;
// set window text (provokes WM_PAINT) and quit
WinSetWindowText(hwndBar, szText);
break; }
/*
* WM_PAINT:
* this, well, paints the status bar.
* Since the status bar is just a static control,
* we want to do some extra stuff to make it prettier.
* At this point, the window text (of the status bar)
* contains the fully translated status bar mnemonics,
* except for the tabulators ("$x" flags), which we'll
* deal with here.
*/
case WM_PAINT: {
// preparations:
RECTL rclBar, rcl;
HPS hps = WinBeginPaint(hwndBar, NULLHANDLE, &rcl);
TRY_LOUD(excpt1)
{
POINTL ptl1;
CHAR szText[1000], szTemp[100] = "0";
USHORT usLength;
LONG lNextX;
PSZ p1, p2, p3;
WinQueryWindowRect(hwndBar, &rclBar);
// switch to RGB mode
GpiCreateLogColorTable(hps, 0,
LCOLF_RGB,
0, 0, NULL);
// 1) draw background
WinFillRect(hps, &rclBar, pGlobalSettings->lSBBgndColor);
// 2) draw 3D frame in selected style
if (pGlobalSettings->SBStyle == SBSTYLE_WARP3RAISED)
// Warp 3 style, raised
gpihDraw3DFrame(hps, &rclBar, 1, TRUE);
else if (pGlobalSettings->SBStyle == SBSTYLE_WARP3SUNKEN)
// Warp 3 style, sunken
gpihDraw3DFrame(hps, &rclBar, 1, FALSE);
else if (pGlobalSettings->SBStyle == SBSTYLE_WARP4MENU) {
// Warp 4 menu style: draw 3D line at top only
rcl = rclBar;
rcl.yBottom = rcl.yTop-2;
gpihDraw3DFrame(hps, &rcl, 1, FALSE);
} else {
// Warp 4 button style
rcl = rclBar;
// draw "sunken" outer rect
gpihDraw3DFrame(hps, &rclBar, 2, FALSE);
// draw "raised" inner rect
WinInflateRect(WinQueryAnchorBlock(hwndBar),
&rcl, -1, -1);
gpihDraw3DFrame(hps, &rcl, 2, TRUE);
}
// 3) start working on text; we do "simple" GpiCharString
// if no tabulators are defined, but calculate some
// subrectangles otherwise
WinQueryWindowText(hwndBar, sizeof(szText)-1, &szText[0]);
// szText now has the translated status bar text
// except for the tabulators ("$x" keys)
p1 = szText;
p2 = NULL;
ptl1.x = 7;
do { // while tabulators are present
// search for tab mnemonic
if (p2 = strstr(p1, "$x(")) {
// tab found: calculate next x position into lNextX
usLength = (p2-p1);
strcpy(szTemp, "100");
if (p3 = strchr(p2, ')')) {
PSZ p4 = strchr(p2, '%');
strncpy(szTemp, p2+3, p3-p2-3);
// get the parameter
sscanf(szTemp, "%d", &lNextX);
if (lNextX < 0) {
// if the result is negative, it's probably
// meant to be an offset from the right
// status bar border
lNextX = (rclBar.xRight + lNextX); // lNextX is negative
}
else if ((p4) && (p4 < p3)) {
// if we have a '%' char before the closing
// bracket, consider lNextX a percentage
// parameter and now translate it into an
// absolute x position using the status bar's
// width
lNextX = (rclBar.xRight * lNextX) / 100;
}
} else
p2 = NULL;
} else
usLength = strlen(p1);
ptl1.y = (pGlobalSettings->SBStyle == SBSTYLE_WARP4MENU) ? 5 : 7;
// set the text color to the global value;
// this might have changed via color drag'n'drop
GpiSetColor(hps, pGlobalSettings->lSBTextColor);
// the font is already preset by the static
// text control (phhhh...)
if (p2) {
// did we have tabs? if so, print text clipped to rect
rcl.xLeft = 0;
rcl.yBottom = 0; // ptl1.y;
rcl.xRight = lNextX-10; // 10 pels space
rcl.yTop = rclBar.yTop;
GpiCharStringPosAt(hps, &ptl1, &rcl, CHS_CLIP,
usLength, p1, NULL);
} else {
// no (more) tabs: just print
GpiMove(hps, &ptl1);
GpiCharString(hps, usLength, p1);
}
if (p2) { // "tabulator" was found: set next x pos
ptl1.x = lNextX;
p1 = p3+1;
}
} while (p2); // go for next tabulator, if we had one
}
CATCH(excpt1)
{
PSZ pszErr = "*** error painting status bar";
POINTL ptl = {5, 5};
GpiMove(hps, &ptl);
GpiCharString(hps, strlen(pszErr), pszErr);
} END_CATCH;
WinEndPaint(hps);
break; }
/*
* STBM_PROHIBITBROADCASTING:
* this msg is sent to us to tell us we will
* be given new presentation parameters soon;
* we will set a flag to TRUE in order to
* prevent broadcasting the pres params again.
* We need this flag because there are two
* situations in which we are given
* WM_PRESPARAMCHANGED messages:
* 1) the user has dropped something on this
* status bar window; in this case, we're
* getting WM_PRESPARAMCHANGED directly,
* without STBM_PROHIBITBROADCASTING, which
* means that we should notify the Worker
* thread to broadcast WM_PRESPARAMCHANGED
* to all status bars;
* 2) a status bar other than this one had been
* dropped something upon; in this case, we'll
* get WM_PRESPARAMCHANGED also (from the
* Worker thread), but STBM_PROHIBITBROADCASTING
* beforehand so that we know we should not
* notify the Worker thread again.
* See WM_PRESPARAMCHANGED below.
*/
case STBM_PROHIBITBROADCASTING: {
psbd->fDontBroadcast = TRUE;
break; }
/*
* WM_PRESPARAMCHANGED:
* if fonts or colors were dropped on the bar, update
* GlobalSettings and have this message broadcast to all
* other status bars on the system.
* This is also posted to us by the Worker thread
* after some OTHER status bar has been dropped
* fonts or colors upon; in this case, psbd->fDontBroadcast
* is TRUE (see above), and we will only update our
* own display and NOT broadcast, because this is
* already being done.
*/
case WM_PRESPARAMCHANGED: {
mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
if (psbd->fDontBroadcast) {
// this flag has been set if it was not this status
// bar whose presparams have changed, but some other
// status bar; in this case, update only
psbd->fDontBroadcast = FALSE;
// update parent's frame controls (because font size
// might have changed)
WinSendMsg(WinQueryWindow(hwndBar, QW_PARENT), WM_UPDATEFRAME, MPNULL, MPNULL);
// update ourselves
WinPostMsg(hwndBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
// and quit
break;
}
// else: it was us that the presparam has been set for
#ifdef DEBUG_STATUSBARS
_Pmpf(( "WM_PRESPARAMCHANGED: %lX", mp1 ));
#endif
// now check what has changed
switch ((ULONG)mp1) {
case PP_FONTNAMESIZE: {
ULONG attrFound;
// CHAR szDummy[200];
CHAR szNewFont[100];
WinQueryPresParam(hwndBar,
PP_FONTNAMESIZE,
0,
&attrFound,
(ULONG)sizeof(szNewFont),
(PVOID)&szNewFont,
0);
cmnSetStatusBarSetting(SBS_STATUSBARFONT,
szNewFont);
// update parent's frame controls (because font size
// might have changed)
WinSendMsg(WinQueryWindow(hwndBar, QW_PARENT),
WM_UPDATEFRAME, MPNULL, MPNULL);
break; }
case PP_FOREGROUNDCOLOR:
case PP_BACKGROUNDCOLOR: {
ULONG ul = 0, attrFound = 0;
WinQueryPresParam(hwndBar,
(ULONG)mp1,
0,
&attrFound,
(ULONG)sizeof(ul),
(PVOID)&ul,
0);
if ((ULONG)mp1 == PP_FOREGROUNDCOLOR)
pGlobalSettings->lSBTextColor = ul;
else
pGlobalSettings->lSBBgndColor = ul;
PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_GLOBALSETTINGS,
pGlobalSettings, sizeof(GLOBALSETTINGS));
WinPostMsg(hwndBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
break; }
}
// finally, broadcast this message to all other status bars;
// this is handled by the Worker thread
xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
(MPARAM)2, // update display
MPNULL);
break; }
/*
* WM_BUTTON1CLICK:
* if button1 is clicked on the status
* bar, we should reset the focus to the
* container.
*/
case WM_BUTTON1CLICK:
// mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
WinSetFocus(HWND_DESKTOP, psbd->psli->hwndCnr);
break;
/*
* WM_BUTTON1DBLCLK:
* on double-click on the status bar,
* open the folder's settings notebook.
* If DEBUG_RESTOREDATA is on (common.h),
* dump some internal folder data to
* PMPRINTF instead.
*/
case WM_BUTTON1DBLCLK: {
/* TRY_LOUD(excpt1) {
CRASH;
}
CATCH(excpt1) {
} END_CATCH; */
#ifdef DEBUG_RESTOREDATA
XFolderData *somThis = XFolderGetData(psbd->somSelf);
_Pmpf(("Dump for %s", _wpQueryTitle(psbd->somSelf) ));
_Pmpf(("FDRLONGARRAY: "));
dbgDump((PBYTE)_pFldrLongArray, _cbFldrLongArray, 3);
#else
WinPostMsg(psbd->psli->hwndFrame,
WM_COMMAND,
(MPARAM)WPMENUID_PROPERTIES,
MPFROM2SHORT(CMDSRC_MENU,
FALSE) ); // results from keyboard operation
#endif
break; }
/*
* WM_CONTEXTMENU:
* if the user right-clicks on status bar,
* display folder's context menu. Parameters:
* mp1:
* POINTS mp1 pointer position
* mp2:
* USHORT usReserved should be 0
* USHORT fPointer if TRUE: results from keyboard
*/
case WM_CONTEXTMENU: {
if (psbd->psli) {
POINTL ptl;
WinSetFocus(HWND_DESKTOP, psbd->psli->hwndCnr);
// give the cnr source emphasis
// (needed for some wpSelectingMenu funcs)
WinSendMsg(psbd->psli->hwndCnr,
CM_SETRECORDEMPHASIS,
(MPARAM)NULL, // undocumented: if precc == NULL,
// the whole cnr is given emphasis
MPFROM2SHORT(TRUE, // set emphasis
CRA_SOURCE));
ptl.x = SHORT1FROMMP(mp1)-30;
ptl.y = SHORT2FROMMP(mp1);
_wpDisplayMenu(psbd->somSelf,
WinQueryWindow(hwndBar, QW_PARENT), // owner: folder frame
hwndBar, // parent: status bar
&ptl,
MENU_OBJECTPOPUP,
0);
// set flag so that the fnwpSubclassedFolderFrame
// can remove the cnr source emphasis after the
// menu has been terminated
psbd->psli->fRemoveSrcEmphasis = TRUE;
}
break; }
/*
* WM_DESTROY:
* call original wnd proc, then free psbd
*/
case WM_DESTROY:
mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
WinSetWindowULong(hwndBar, QWL_USER, 0);
free(psbd);
break;
default:
mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
break;
} // end switch
} // end if (psbd)
/* else // error: call default
mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2); */
return (mrc);
}
/*
* CalcFrameRect:
* this gets called from fnwpSubclassedFolderFrame
* when WM_CALCFRAMERECT is received. This implements
* folder status bars.
*/
VOID CalcFrameRect(MPARAM mp1, MPARAM mp2)
{
PRECTL prclPassed = (PRECTL)mp1;
ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
if (SHORT1FROMMP(mp2))
// TRUE: Frame rectangle provided, calculate client
// FALSE: Client area rectangle provided, calculate frame
{
// TRUE: calculate the rectl of the client;
// call default window procedure to subtract child frame
// controls from the rectangle's height
LONG lClientHeight;
// position the static text frame extension below the client
lClientHeight = prclPassed->yTop - prclPassed->yBottom;
if ( ulStatusBarHeight > lClientHeight )
{
// extension is taller than client, so set client height to 0
prclPassed->yTop = prclPassed->yBottom;
}
else
{
// set the origin of the client and shrink it based upon the
// static text control's height
prclPassed->yBottom += ulStatusBarHeight;
prclPassed->yTop -= ulStatusBarHeight;
}
}
else
{
// FALSE: calculate the rectl of the frame;
// call default window procedure to subtract child frame
// controls from the rectangle's height;
// set the origin of the frame and increase it based upon the
// static text control's height
prclPassed->yBottom -= ulStatusBarHeight;
prclPassed->yTop += ulStatusBarHeight;
}
}
/*
* FormatFrame:
* this gets called from fnwpSubclassedFolderFrame
* when WM_FORMATFRAME is received. This implements
* folder status bars.
*/
VOID FormatFrame(PSUBCLASSEDLISTITEM psli, // in: frame information
MPARAM mp1, // in: mp1 from WM_FORMATFRAME
// (points to SWP array)
ULONG *pulCount) // in/out: frame control count
// from default wnd proc
{
// access the SWP array that is passed to us
// and search all the controls for the container child window,
// which for folders always has the ID 0x8008
ULONG ul;
PSWP swpArr = (PSWP)mp1;
CNRINFO CnrInfo;
for (ul = 0; ul < *pulCount; ul++)
{
if (WinQueryWindowUShort( swpArr[ul].hwnd, QWS_ID ) == 0x8008 )
// FID_CLIENT
{
// container found: reduce size of container by
// status bar height
POINTL ptlBorderSizes;
// XFolderData *somThis = XFolderGetData(psli->somSelf);
ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
WinSendMsg(psli->hwndFrame, WM_QUERYBORDERSIZE,
(MPARAM)&ptlBorderSizes, MPNULL);
// first initialize the _new_ SWP for the status bar.
// Since the SWP array for the std frame controls is
// zero-based, and the standard frame controls occupy
// indices 0 thru ulCount-1 (where ulCount is the total
// count), we use ulCount for our static text control.
swpArr[*pulCount].fl = SWP_MOVE | SWP_SIZE | SWP_NOADJUST | SWP_ZORDER;
swpArr[*pulCount].x = ptlBorderSizes.x;
swpArr[*pulCount].y = ptlBorderSizes.y;
swpArr[*pulCount].cx = swpArr[ul].cx;
swpArr[*pulCount].cy = ulStatusBarHeight;
swpArr[*pulCount].hwndInsertBehind = HWND_BOTTOM; // HWND_TOP;
swpArr[*pulCount].hwnd = psli->hwndStatusBar;
// adjust the origin and height of the container to
// accomodate our static text control
swpArr[ul].y += swpArr[*pulCount].cy;
swpArr[ul].cy -= swpArr[*pulCount].cy;
// now we need to adjust the workspace origin of the cnr
// accordingly, or otherwise the folder icons will appear
// outside the visible cnr workspace and scroll bars will
// show up.
// We only do this the first time we're arriving here
// (which should be before the WPS is populating the folder);
// psli->fNeedCnrScroll has been initially set to TRUE
// by xfShowStatusBar
if (psli->fNeedCnrScroll)
{
winhQueryCnrInfo(swpArr[ul].hwnd, CnrInfo);
#ifdef DEBUG_STATUSBARS
_Pmpf(( "Old CnrInfo.ptlOrigin.y: %lX", CnrInfo.ptlOrigin.y ));
#endif
if ( ((LONG)CnrInfo.ptlOrigin.y >= (LONG)ulStatusBarHeight)
)
{
CnrInfo.ptlOrigin.y -= ulStatusBarHeight;
#ifdef DEBUG_STATUSBARS
_Pmpf(( "New CnrInfo.ptlOrigin.y: %lX", CnrInfo.ptlOrigin.y ));
#endif
WinSendMsg(swpArr[ul].hwnd, CM_SETCNRINFO,
(MPARAM)&CnrInfo, (MPARAM)CMA_PTLORIGIN);
// set flag to FALSE to prevent a second adjustment
psli->fNeedCnrScroll = FALSE;
}
} // end if (psli->fNeedCnrScroll)
} // end if WinQueryWindowUShort
} // end for (ul = 0; ul < ulCount; ul++)
}
/*
* InitMenu:
* this gets called from fnwpSubclassedFolderFrame
* when WM_INITMENU is received.
* This is needed for various menu features:
* 1) for folder content menus, because these
* are initially empty and only filled if the user
* clicks on them.
* We will query a bunch of data first, which we need
* later for drawing our items, and then call
* mnuFillContentSubmenu, which populates the folder
* and fills the menu with the items therein;
* 2) for the menu system sounds;
* 3) for manipulating Warp 4 folder menu _bars_.
* WM_INITMENU parameters:
* SHORT mp1 menu item id
* HWND mp2 menu window handle
* Returns: NULL always.
*/
// original wnd proc for folder content menus,
// which we must subclass
PFNWP pfnwpFolderContentMenuOriginal = NULL;
VOID InitMenu(PSUBCLASSEDLISTITEM psli, // in: frame information
MPARAM mp1,
MPARAM mp2) // in: mp1, mp2 from WM_INITMENU
{
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
XFolderData *somThis = XFolderGetData(psli->somSelf);
PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
ULONG *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
#ifdef DEBUG_MENUS
_Pmpf(( "WM_INITMENU: mp1 = %lX, mp2 = %lX", mp1, mp2 ));
#endif
// store the container window handle in instance
// data for wpPopupMenu workaround (see wpPopupMenu)
_hwndCnrSaved = psli->hwndCnr;
// play system sound
if ( ((USHORT)mp1 < 0x8000) // avoid system menu
|| ((USHORT)mp1 == 0x8020) // include context menu
)
xthrPlaySystemSound(MMSOUND_XFLD_CTXTOPEN);
*pulWorkplaceFunc2 = 200;
// find out whether the menu of which we are notified
// is a folder content menu; if so (and it is not filled
// yet), the first menu item is ID_XFMI_OFS_DUMMY
if ((ULONG)WinSendMsg((HWND)mp2, MM_ITEMIDFROMPOSITION, (MPARAM)0, MPNULL)
== (pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_DUMMY))
{
// okay, let's go
if (pGlobalSettings->FCShowIcons)
{
#ifdef DEBUG_MENUS
_Pmpf(( " preparing owner draw"));
#endif
// show folder content icons ON:
mnuPrepareOwnerDraw(mp1, mp2);
}
*pulWorkplaceFunc2 = 200;
mnuFillContentSubmenu(
(SHORT)mp1, (HWND)mp2,
// this func subclasses the folder content
// menu wnd and stores the result here
&pfnwpFolderContentMenuOriginal);
} else {
// no folder content menu:
// on Warp 4, check if the folder has a menu bar
if (doshIsWarp4()) {
#ifdef DEBUG_MENUS
_Pmpf(( " checking for menu bar"));
#endif
if (SHORT1FROMMP(mp1) == 0x8005) {
// seems to be some WPS menu item;
// since the WPS seems to be using this
// same ID for all the menu bar submenus,
// we need to check the last selected
// menu item, which was stored in the psli
// structure by WM_MENUSELECT (below).
PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
switch (psli->usLastSelMenuItem) {
case 0x2D3:
// "Help" submenu: add XFolder product info
#ifdef DEBUG_MENUS
_Pmpf((" 'Help' menu found"));
#endif
winhInsertMenuSeparator((HWND)mp2, MIT_END,
(pGlobalSettings->VarMenuOffset
+ ID_XFMI_OFS_SEPARATOR));
winhInsertMenuItem((HWND)mp2, MIT_END,
(pGlobalSettings->VarMenuOffset
+ ID_XFMI_OFS_PRODINFO),
pNLSStrings->pszProductInfo,
MIS_TEXT, 0);
break;
case 0x2D0: { // "Edit" submenu
// find position of "Deselect all" item
SHORT sPos = (SHORT)WinSendMsg((HWND)mp2,
MM_ITEMPOSITIONFROMID,
MPFROM2SHORT(0x73, FALSE),
MPNULL);
#ifdef DEBUG_MENUS
_Pmpf((" 'Edit' menu found"));
#endif
// insert "Select by name" after that item
winhInsertMenuItem((HWND)mp2,
sPos+1,
(pGlobalSettings->VarMenuOffset
+ ID_XFMI_OFS_SELECTSOME),
pNLSStrings->pszSelectSome,
MIS_TEXT, 0);
break; }
case 0x2D1: { // "View" submenu
CNRINFO CnrInfo;
#ifdef DEBUG_MENUS
_Pmpf((" 'View' menu found"));
#endif
// modify the "Sort" menu, as we would
// do it for context menus also
mnuModifySortMenu((HWND)mp2,
XFolderGetData(psli->somSelf),
pGlobalSettings,
pNLSStrings);
winhQueryCnrInfo(psli->hwndCnr, CnrInfo);
// and now insert the "folder view" items
winhInsertMenuSeparator((HWND)mp2,
MIT_END,
(pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_SEPARATOR));
mnuInsertFldrViewItems(psli->somSelf,
(HWND)mp2,
psli->hwndCnr,
FALSE,
&CnrInfo);
break; }
}
}
}
}
}
/*
* MenuSelect:
* this gets called from fnwpSubclassedFolderFrame
* when WM_MENUSELECT is received.
* We need this for three reasons:
* 1) we will play a system sound, if desired;
* 2) we need to swallow this for very large folder
* content menus, because for some reason, PM will
* select a random menu item after we have moved
* these menus on the screen;
* 3) we can intercept certain menu items so that
* these don't get passed to wpMenuItemSelected.
* This is needed for menu items such as those in
* the "Sort" menu so that the menu is not dismissed
* after selection.
* WM_MENUSELECT parameters:
* mp1 USHORT usItem - selected menu item
* USHORT usPostCommand - TRUE: if we return TRUE,
* a message will be posted to the owner.
* mp2 HWND - menu control wnd handle
* If we set pfDismiss to TRUE, wpMenuItemSelected will be
* called, and the menu will be dismissed.
* Otherwise the message will be swallowed.
* We return TRUE if the menu item has been handled here.
* Otherwise the default wnd proc will be used.
*/
// flags for fnwpSubclassedFolderFrame;
// these are set by fnwpFolderContentMenu.
// We can afford using global variables here
// because there will never be more than one
// open window at a time.
BOOL fFldrContentMenuMoved = FALSE,
fFldrContentMenuButtonDown = FALSE;
BOOL MenuSelect(PSUBCLASSEDLISTITEM psli, // in: frame information
MPARAM mp1, MPARAM mp2, // in: mp1, mp2 from WM_MENUSELECT
BOOL *pfDismiss) // out: dismissal flag
{
BOOL fHandled = FALSE;
// return value for WM_MENUSELECT;
// TRUE means dismiss menu
psli->usLastSelMenuItem = SHORT1FROMMP(mp1);
// check if we have moved a folder content menu
// (this flag is set by fnwpFolderContentMenu); for
// some reason, PM gets confused with the menu items
// then and automatically tries to select the menu
// item under the mouse, so we swallow this one
// message if (a) the folder content menu has been
// moved by fnwpFolderContentMenu and (b) no mouse
// button is pressed. These flags are all set by
// fnwpFolderContentMenu.
if (fFldrContentMenuMoved)
{
#ifdef DEBUG_MENUS
_Pmpf(( " FCMenuMoved set!"));
#endif
if (!fFldrContentMenuButtonDown) {
// mouse was not pressed: swallow this
// menu selection
*pfDismiss = FALSE;
} else {
// mouse was pressed: allow selection
// and unset flags
*pfDismiss = TRUE;
fFldrContentMenuButtonDown = FALSE;
fFldrContentMenuMoved = FALSE;
}
fHandled = TRUE;
} else {
if ( (SHORT2FROMMP(mp1) == TRUE)
&& ( ((USHORT)mp1 < 0x8000) // avoid system menu
|| ((USHORT)mp1 == 0x8020) // include context menu
)
)
{
HWND hwndCnr = xwpsQueryCnrFromFrame(psli->hwndFrame);
// play system sound
xthrPlaySystemSound(MMSOUND_XFLD_CTXTSELECT);
// Now check if we have a menu item which we don't
// want to see dismissed.
if (hwndCnr) {
// first find out what kind of objects we have here
ULONG ulSelection = 0;
WPObject *pObject1 =
mnuQuerySelectedObject(psli->somSelf,
hwndCnr,
&ulSelection);
WPObject *pObject = pObject1;
#ifdef DEBUG_MENUS
_Pmpf(( " Object selections: %d", ulSelection));
#endif
// dereference shadows
if (pObject)
if (_somIsA(pObject, _WPShadow))
pObject = _wpQueryShadowedObject(pObject, TRUE);
// now call the functions in menus.c for this,
// depending on the class of the object for which
// the menu was opened
if (pObject) {
if (_somIsA(pObject, _WPFileSystem))
{
fHandled = mnuFileSystemSelectingMenuItem(
pObject1, // note that we're passing
// pObject1 instead of pObject;
// pObject1 might be a shadow!
SHORT1FROMMP(mp1), // usItem
(BOOL)SHORT2FROMMP(mp1), // fPostCommand
(HWND)mp2, // hwndMenu
hwndCnr,
ulSelection, // SEL_* flags
pfDismiss); // dismiss-menu flag
}
if ( (!fHandled)
&& (_somIsA(pObject, _WPFolder))
)
{
fHandled = mnuFolderSelectingMenuItem(pObject,
SHORT1FROMMP(mp1), // usItem
(BOOL)SHORT2FROMMP(mp1), // fPostCommand
(HWND)mp2, // hwndMenu
hwndCnr,
ulSelection, // SEL_* flags
pfDismiss); // dismiss-menu flag
}
if ( (fHandled) && (!(*pfDismiss)) )
{
// menu not to be dismissed: set the flag
// which will remove cnr source
// emphasis when the menu is dismissed
// later (WM_ENDMENU msg here)
psli->fRemoveSrcEmphasis = TRUE;
}
}
}
}
}
return (fHandled);
}
/*
*@@ fnwpSubclassedFolderFrame:
* New window proc for subclassed folder frame windows.
* Folder frame windows are subclassed in XFolder::wpOpen
* (or XFldDisk::wpOpen for Disk views) with the address
* of this window procedure.
*
* This is maybe the most central part of XFolder. Since
* most WPS methods are really just reacting to messages
* in the default WPS frame window proc, but for some
* features methods are just not sufficient, basically we
* simulate what the WPS does here by intercepting _lots_
* of messages before the WPS gets them.
*
* Things we do in this proc:
* -- frame control manipulation for status bars
* -- Warp 4 folder menu bar manipulation (WM_INITMENU)
* -- handling of certain menu items w/out dismissing
* the menu; this calls functions in menus.c
* -- menu owner draw (folder content menus w/ icons);
* this calls functions in menus.c also
* -- container control messages: tree view auto-scroll,
* updating status bars etc.
* -- playing the new system sounds for menus and such
* by calling xthrPlaySystemSound.
*
* Note that this function calls lots of "external" functions
* spread across all over the XFolder code. This reduces the
* code size of this function, which gets called very often,
* to avoid excessive use of the processor caches.
*/
MRESULT EXPENTRY fnwpSubclassedFolderFrame(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2)
{
PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
ULONG *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
PSUBCLASSEDLISTITEM psli = NULL;
PFNWP pfnwpOriginal = NULL;
XFolder *somSelf;
MRESULT mrc = MRFALSE;
BOOL fCallDefault = FALSE;
*pulWorkplaceFunc2 = 100;
TRY_LOUD(excpt1) // install "loud" exception handler (except.h)
{
// find the original wnd proc in the
// global linked list, so we can pass messages
// on to it
*pulWorkplaceFunc2 = 110;
psli = cmnQueryPSLI(hwndFrame);
if (psli) {
pfnwpOriginal = psli->pfnwpOriginal;
somSelf = psli->somSelf;
}
if (pfnwpOriginal)
{
*pulWorkplaceFunc2 = 120;
switch(msg)
{
/* *************************
* *
* Status bar: *
* *
**************************/
case WM_QUERYFRAMECTLCOUNT: {
// query the standard frame controls count
ULONG ulrc = (ULONG)((*pfnwpOriginal)(hwndFrame, msg, mp1, mp2));
// if we have a status bar, increment the count
if (psli->hwndStatusBar)
ulrc++;
mrc = (MPARAM)ulrc;
break; }
/*
* WM_FORMATFRAME:
* this message is sent to a frame window to calculate the sizes
* and positions of all of the frame controls and the client window:
* mp1 PSWP pswp structure array
* mp2 PRECTL pprectl pointer to client window
* rectangle
* returns USHORT ccount count of the number of SWP
* arrays returned
*/
case WM_FORMATFRAME:
{
// query the number of standard frame controls
ULONG ulCount = (ULONG)((*pfnwpOriginal)(hwndFrame, msg, mp1, mp2));
#ifdef DEBUG_STATUSBARS
_Pmpf(( "WM_FORMATFRAME ulCount = %d", ulCount ));
#endif
if (psli->hwndStatusBar)
{
// we have a status bar:
// format the frame
FormatFrame(psli, mp1, &ulCount);
// increment the number of frame controls
// to include our status bar
mrc = (MRESULT)(ulCount + 1);
} // end if (psli->hwndStatusBar)
else
mrc = (MRESULT)ulCount;
break; }
/*
* WM_CALCFRAMERECT:
* this message occurs when an application uses the
* WinCalcFrameRect function. Parameters:
* mp1 PRECTL pRect rectangle structure
* mp2 USHORT usFrame frame indicator
* returns BOOL rc rectangle-calculated indicator
*/
case WM_CALCFRAMERECT:
{
mrc = (*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
if (psli->hwndStatusBar)
// we have a status bar: calculate its rectangle
CalcFrameRect(mp1, mp2);
break; }
/* *************************
* *
* Menu items: *
* *
**************************/
/*
* WM_INITMENU:
* this message is sent to a frame whenever a menu
* is about to be displayed. This is needed for
* various menu features; see InitMenu() above.
*/
case WM_INITMENU: {
// always call the default, in case someone else
// is subclassing folders (ObjectDesktop?!?)
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
InitMenu(psli, mp1, mp2);
break; }
/*
* WM_MENUSELECT:
* this is SENT to a menu owner by the menu control to
* determine what to do right after a menu item has been
* selected. If we return TRUE, the menu will be dismissed.
* See MenuSelect() above.
*/
case WM_MENUSELECT: {
BOOL fDismiss = TRUE;
#ifdef DEBUG_MENUS
_Pmpf(( "WM_MENUSELECT: mp1 = %lX/%lX, mp2 = %lX",
SHORT1FROMMP(mp1),
SHORT2FROMMP(mp1),
mp2 ));
#endif
// always call the default, in case someone else
// is subclassing folders (ObjectDesktop?!?)
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
// now handle our stuff; this might modify mrc to
// have the menu stay on the screen
if (MenuSelect(psli, mp1, mp2, &fDismiss))
mrc = (MRESULT)fDismiss;
break; }
/*
* WM_MENUEND:
* this message occurs when a menu control is about to
* terminate. We need to remove cnr source emphasis
* if the user has requested a context menu from a
* status bar.
*/
case WM_MENUEND: {
#ifdef DEBUG_MENUS
_Pmpf(( "WM_MENUEND: mp1 = %lX, mp2 = %lX",
mp1, mp2 ));
/* _Pmpf(( " fFolderContentWindowPosChanged: %d",
fFolderContentWindowPosChanged));
_Pmpf(( " fFolderContentButtonDown: %d",
fFolderContentButtonDown)); */
#endif
// menu opened from status bar?
if (psli->fRemoveSrcEmphasis) {
// if so, remove cnr source emphasis
WinSendMsg(psli->hwndCnr,
CM_SETRECORDEMPHASIS,
(MPARAM)NULL, // undocumented: if precc == NULL,
// the whole cnr is given emphasis
MPFROM2SHORT(FALSE, // remove emphasis
CRA_SOURCE));
// and make sure the container has the
// focus
WinSetFocus(HWND_DESKTOP, psli->hwndCnr);
// reset flag for next context menu
psli->fRemoveSrcEmphasis = FALSE;
}
// unset flag for WM_MENUSELECT above
fFldrContentMenuMoved = FALSE;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
break; }
/*
* WM_MEASUREITEM:
* this msg is sent only once per owner-draw item when
* PM needs to know its size. This gets sent to us for
* items in folder content menus; the height of our items
* will be the same as with non-owner-draw ones, but
* we need to calculate the width according to the item
* text. Return value: check mnuMeasureItem (menus.c)
*/
case WM_MEASUREITEM: {
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
*pulWorkplaceFunc2 = 300;
if ( (SHORT)mp1 > (pGlobalSettings->VarMenuOffset+ID_XFMI_OFS_VARIABLE) )
{
// call the measure-item func in menus.c
mrc = mnuMeasureItem((POWNERITEM)mp2, pGlobalSettings);
}
else
// none of our items: pass to original wnd proc
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
break; }
/*
* WM_DRAWITEM:
* this msg is sent for each item every time it
* needs to be redrawn. This gets sent to us for
* items in folder content menus.
*/
case WM_DRAWITEM: {
PGLOBALSETTINGS pGlobalSettings =
cmnQueryGlobalSettings();
*pulWorkplaceFunc2 = 400;
if ( (SHORT)mp1 > (pGlobalSettings->VarMenuOffset+ID_XFMI_OFS_VARIABLE) )
{
// variable menu item: this must be a folder-content
// menu item, because for others no WM_DRAWITEM is sent
// (menus.c)
if (mnuDrawItem(pGlobalSettings,
mp1, mp2))
mrc = (MRESULT)TRUE;
else // error occured:
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
}
else
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
*pulWorkplaceFunc2 = 499;
break; }
/* *************************
* *
* Miscellaneae: *
* *
**************************/
/*
* WM_CHAR:
* this is intercepted to provide folder hotkeys
*/
case WM_CHAR: {
XFolderData *somThis = XFolderGetData(somSelf);
PGLOBALSETTINGS pGlobalSettings =
cmnQueryGlobalSettings();
if ( (_bAcceleratorsAllowed == 1)
|| ((_bAcceleratorsAllowed == 2) && (pGlobalSettings->Accelerators))
)
{
if (cmnProcessFldrHotkey(hwndFrame, mp1, mp2)) {
mrc = (MRESULT)TRUE;
break;
}
}
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
break; }
/*
* WM_CONTROL:
* this is intercepted to check for container
* notifications we might be interested in
*/
case WM_CONTROL: {
*pulWorkplaceFunc2 = 950;
if (SHORT1FROMMP(mp1) /* id */ == 0x8008) // container!!
{
#ifdef DEBUG_CNRCNTRL
CHAR szTemp2[30];
sprintf(szTemp2, "unknown: %d", SHORT2FROMMP(mp1));
_Pmpf(("Cnr cntrl msg: %s, mp2: %lX",
(SHORT2FROMMP(mp1) == CN_BEGINEDIT) ? "CN_BEGINEDIT"
: (SHORT2FROMMP(mp1) == CN_COLLAPSETREE) ? "CN_COLLAPSETREE"
: (SHORT2FROMMP(mp1) == CN_CONTEXTMENU) ? "CN_CONTEXTMENU"
: (SHORT2FROMMP(mp1) == CN_DRAGAFTER) ? "CN_DRAGAFTER"
: (SHORT2FROMMP(mp1) == CN_DRAGLEAVE) ? "CN_DRAGLEAVE"
: (SHORT2FROMMP(mp1) == CN_DRAGOVER) ? "CN_DRAGOVER"
: (SHORT2FROMMP(mp1) == CN_DROP) ? "CN_DROP"
: (SHORT2FROMMP(mp1) == CN_DROPNOTIFY) ? "CN_DROPNOTIFY"
: (SHORT2FROMMP(mp1) == CN_DROPHELP) ? "CN_DROPHELP"
: (SHORT2FROMMP(mp1) == CN_EMPHASIS) ? "CN_EMPHASIS"
: (SHORT2FROMMP(mp1) == CN_ENDEDIT) ? "CN_ENDEDIT"
: (SHORT2FROMMP(mp1) == CN_ENTER) ? "CN_ENTER"
: (SHORT2FROMMP(mp1) == CN_EXPANDTREE) ? "CN_EXPANDTREE"
: (SHORT2FROMMP(mp1) == CN_HELP) ? "CN_HELP"
: (SHORT2FROMMP(mp1) == CN_INITDRAG) ? "CN_INITDRAG"
: (SHORT2FROMMP(mp1) == CN_KILLFOCUS) ? "CN_KILLFOCUS"
: (SHORT2FROMMP(mp1) == CN_PICKUP) ? "CN_PICKUP"
: (SHORT2FROMMP(mp1) == CN_QUERYDELTA) ? "CN_QUERYDELTA"
: (SHORT2FROMMP(mp1) == CN_REALLOCPSZ) ? "CN_REALLOCPSZ"
: (SHORT2FROMMP(mp1) == CN_SCROLL) ? "CN_SCROLL"
: (SHORT2FROMMP(mp1) == CN_SETFOCUS) ? "CN_SETFOCUS"
: szTemp2,
mp2));
#endif
switch (SHORT2FROMMP(mp1)) {
/*
* CN_BEGINEDIT:
* this is sent by the container control
* when direct text editing is about to
* begin, that is, when the user alt-clicks
* on an object title.
* We'll select the file stem of the object.
*/
/* case CN_BEGINEDIT: {
PCNREDITDATA pced = (PCNREDITDATA)mp2;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
if (pced) {
PMINIRECORDCORE pmrc = (PMINIRECORDCORE)pced->pRecord;
if (pmrc) {
// editing WPS record core, not title etc.:
// get the window ID of the MLE control
// in the cnr window
HWND hwndMLE = WinWindowFromID(pced->hwndCnr,
CID_MLE);
if (hwndMLE) {
ULONG cbText = WinQueryWindowTextLength(
hwndMLE)+1;
PSZ pszText = malloc(cbText);
_Pmpf(("textlen: %d", cbText));
if (WinQueryWindowText(hwndMLE,
cbText,
pszText))
{
PSZ pszLastDot = strrchr(pszText, '.');
_Pmpf(("text: %s", pszText));
WinSendMsg(hwndMLE,
EM_SETSEL,
MPFROM2SHORT(
// first char: 0
0,
// last char:
(pszLastDot)
? (pszLastDot-pszText)
: 10000
), MPNULL);
}
free(pszText);
}
}
}
break; } */
/*
* CN_ENTER:
* double-click or enter key:
* play sound
*/
case CN_ENTER:
*pulWorkplaceFunc2 = 951;
xthrPlaySystemSound(MMSOUND_XFLD_CNRDBLCLK);
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
break;
/*
* CN_EMPHASIS:
* selection changed:
* update status bar
*/
case CN_EMPHASIS:
*pulWorkplaceFunc2 = 952;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
if (psli->hwndStatusBar) {
#ifdef DEBUG_STATUSBARS
_Pmpf(( "CN_EMPHASIS: posting PM_UPDATESTATUSBAR to hwnd %lX", psli->hwndStatusBar ));
#endif
WinPostMsg(psli->hwndStatusBar,
STBM_UPDATESTATUSBAR,
MPNULL,
MPNULL);
}
break;
/*
* CN_EXPANDTREE:
* tree view has been expanded:
* do cnr auto-scroll
*/
case CN_EXPANDTREE: {
PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
*pulWorkplaceFunc2 = 953;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
if (pGlobalSettings->TreeViewAutoScroll) {
xthrPostWorkerMsg(WOM_TREEVIEWAUTOSCROLL,
(MPARAM)hwndFrame,
mp2); // PMINIRECORDCORE
}
break; }
default:
*pulWorkplaceFunc2 = 954;
fCallDefault = TRUE;
break;
}
}
break; }
/*
* WM_CLOSE:
* upon this, we need to clean up our linked list
* of subclassed windows
*/
case WM_CLOSE: {
// first remove the status bar to store the correct wnd size
// xfShowStatusBar(hwndFrame, psli->somSelf, psli, FALSE);
// then do the default stuff
*pulWorkplaceFunc2 = 990;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
// upon closing the window, undo the subclassing, in case
// some other message still comes in
WinSubclassWindow(hwndFrame, pfnwpOriginal);
// destroy the supplementary object window for this folder
// frame window
WinDestroyWindow(psli->hwndSupplObject);
// and remove this window from our subclassing linked list
cmnRemovePSLI(psli);
break; }
default:
fCallDefault = TRUE;
break;
} // end switch
} // end if (pfnwpOriginal)
else {
#ifdef DEBUG_MENUS
DosBeep(10000, 10);
#endif
}
} CATCH(excpt1) {
// exception occured:
return (0);
} END_CATCH;
if (fCallDefault)
{
// this has only been set to TRUE for "default" in
// the switch statement above; we then call the
// default window procedure.
// This is either the original folder frame window proc
// of the WPS itself or maybe the one of other WPS enhancers
// which have subclassed folder windows (ObjectDesktop
// and the like).
// We do this outside the TRY/CATCH stuff above so that
// we don't get blamed for exceptions which we are not
// responsible for. ;-)
*pulWorkplaceFunc2 = 997;
mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
*pulWorkplaceFunc2 = 998;
}
*pulWorkplaceFunc2 = 999;
return (mrc);
}
/*
*@@ fnwpSupplObject:
* this is the wnd proc for the "Supplementary Object wnd"
* which is created for each folder frame window when it's
* subclassed. We need this window to handle additional
* messages which are not part of the normal message set,
* which is handled by fnwpSubclassedFolderFrame.
*
* If we added additional messages to that proc, we'd probably
* ruin other WPS enhancers which might use the same message
* in a different context (ObjectDesktop?), so we use a
* different window.
*
* We cannot use the global XFolder object window
* (fnwpXFolderObject, xthreads.c) because
* sometimes folder windows do not run in the main PM thread
* (TID 1), esp. when they're opened using WinOpenObject or
* REXX functions. This wnd proc always runs in the same
* thread as the folder frame wnd does.
*
* This func is new with XFolder V0.82.
*/
MRESULT EXPENTRY fnwpSupplObject(HWND hwndObject, ULONG msg, MPARAM mp1, MPARAM mp2)
{
MPARAM mrc = NULL;
PSUBCLASSEDLISTITEM psli = (PSUBCLASSEDLISTITEM)
WinQueryWindowULong(hwndObject, QWL_USER);
switch (msg) {
case WM_CREATE:
// set the USER window word to the SUBCLASSEDLISTITEM
// structure which is passed to us upon window
// creation (see cmnSubclassFrameWnd, which creates
// us)
mrc = WinDefWindowProc(hwndObject, msg, mp1, mp2);
psli = (PSUBCLASSEDLISTITEM)mp1;
WinSetWindowULong(hwndObject, QWL_USER, (ULONG)psli);
break;
/*
* SOM_ACTIVATESTATUSBAR:
* add / remove / repaint the folder status bar;
* this is posted every time XFolder needs to change
* anything about status bars. We must not play with
* frame controls from threads other than the thread
* in which the status bar was created, i.e. the thread
* in which the folder frame is running (which, in most
* cases, is thread 1, the main PM thread of the WPS),
* because reformatting frame controls from other
* threads will cause PM hangs or WPS crashes.
* Parameters:
* ULONG mp1 0: disable (destroy) status bar
* 1: enable (create) status bar
* 2: update (reformat) status bar
* HWND mp2: hwndView (frame) to update
*/
case SOM_ACTIVATESTATUSBAR: {
HWND hwndFrame = (HWND)mp2;
#ifdef DEBUG_STATUSBARS
_Pmpf(( "SOM_ACTIVATESTATUSBAR, mp1: %lX, psli: %lX", mp1, psli));
#endif
if (psli)
switch ((ULONG)mp1) {
case 0:
_xfShowStatusBar(psli->somSelf, psli, FALSE);
break;
case 1:
_xfShowStatusBar(psli->somSelf, psli, TRUE);
break;
default: {
// == 2 => update status bars; this is
// neccessary if the font etc. has changed
PSZ pszStatusBarFont =
cmnQueryStatusBarSetting(SBS_STATUSBARFONT);
WinSendMsg(psli->hwndStatusBar, STBM_PROHIBITBROADCASTING,
(MPARAM)TRUE, MPNULL);
WinSetPresParam(psli->hwndStatusBar, PP_FONTNAMESIZE,
(ULONG)strlen(pszStatusBarFont) + 1, (PVOID)pszStatusBarFont);
WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPNULL, MPNULL);
WinSendMsg(psli->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
break; }
}
break; }
default:
mrc = WinDefWindowProc(hwndObject, msg, mp1, mp2);
}
return (mrc);
}
/*
*@@ fnwpFolderContentMenu:
* this is the subclassed wnd proc for folder content menus;
* we need to intercept mouse button 2 msgs to open a folder
* (WarpCenter behavior).
*/
MRESULT EXPENTRY fnwpFolderContentMenu(HWND hwndMenu, ULONG msg, MPARAM mp1, MPARAM mp2)
{
PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
ULONG *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
ULONG ulOldWorkplaceFunc2 = *pulWorkplaceFunc2;
MRESULT mrc = 0;
*pulWorkplaceFunc2 = 10000;
TRY_LOUD(excpt1) // install "loud" exception handler (except.h)
{
USHORT sSelected;
POINTL ptlMouse;
RECTL rtlItem;
switch(msg)
{
case WM_ADJUSTWINDOWPOS:
{
PSWP pswp = (PSWP)mp1;
BOOL fAdjusted = FALSE;
#ifdef DEBUG_MENUS
_Pmpf(("WM_ADJUSTWINDOWPOS"));
#endif
if ((pswp->fl & (SWP_MOVE)) == (SWP_MOVE)) {
#ifdef DEBUG_MENUS
_Pmpf((" SWP_MOVE set"));
#endif
if (!fFldrContentMenuMoved) {
#ifdef DEBUG_MENUS
_Pmpf((" Checking bounds"));
#endif
if ((pswp->x + pswp->cx) >
WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN))
{
pswp->x = 0;
#ifdef DEBUG_MENUS
_Pmpf((" Changed x pos"));
#endif
// avoid several changes for this menu;
// this flag is reset by WM_INITMENU in
// fnwpSubclassedFolderFrame
fFldrContentMenuMoved = TRUE;
fAdjusted = TRUE;
}
if ((pswp->y + pswp->cy) >
WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN))
{
pswp->y = 0;
#ifdef DEBUG_MENUS
_Pmpf((" Changed y pos"));
#endif
// avoid several changes for this menu;
// this flag is reset by WM_INITMENU in
// fnwpSubclassedFolderFrame
fFldrContentMenuMoved = TRUE;
fAdjusted = TRUE;
}
}
}
if (fAdjusted)
pswp->fl |= (SWP_NOADJUST);
mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
fFldrContentMenuButtonDown = FALSE;
break; }
#ifdef DEBUG_MENUS
case MM_SELECTITEM: {
_Pmpf(( "MM_SELECTITEM: mp1 = %lX/%lX, mp2 = %lX",
SHORT1FROMMP(mp1),
SHORT2FROMMP(mp1),
mp2 ));
mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
break; }
#endif
case WM_BUTTON2DOWN:
#ifdef DEBUG_MENUS
_Pmpf(("WM_BUTTON2DOWN"));
#endif
ptlMouse.x = SHORT1FROMMP(mp1);
ptlMouse.y = SHORT2FROMMP(mp1);
WinSendMsg(hwndMenu, MM_SELECTITEM,
MPFROM2SHORT(MIT_NONE, FALSE),
MPFROM2SHORT(0, FALSE));
sSelected = winhQueryItemUnderMouse(hwndMenu, &ptlMouse, &rtlItem);
WinSendMsg(hwndMenu, MM_SETITEMATTR,
MPFROM2SHORT(sSelected,
FALSE),
MPFROM2SHORT(MIA_HILITED, MIA_HILITED)
);
break;
case WM_BUTTON1DOWN:
// let this be handled by the default proc
#ifdef DEBUG_MENUS
_Pmpf(("WM_BUTTON1DOWN"));
#endif
fFldrContentMenuButtonDown = TRUE;
mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
break;
case WM_BUTTON1DBLCLK:
case WM_BUTTON2UP: {
// upon receiving these, we will open the object directly; we need to
// cheat a little bit because sending MM_SELECTITEM would open the submenu
#ifdef DEBUG_MENUS
_Pmpf(("WM_BUTTON2UP"));
#endif
fFldrContentMenuButtonDown = TRUE;
*pulWorkplaceFunc2 = 10100;
ptlMouse.x = SHORT1FROMMP(mp1);
ptlMouse.y = SHORT2FROMMP(mp1);
WinSendMsg(hwndMenu, MM_SELECTITEM,
MPFROM2SHORT(MIT_NONE, FALSE),
MPFROM2SHORT(0, FALSE));
sSelected = winhQueryItemUnderMouse(hwndMenu, &ptlMouse, &rtlItem);
xthrPlaySystemSound(MMSOUND_XFLD_CTXTSELECT);
WinPostMsg(WinQueryWindow(hwndMenu, QW_OWNER),
WM_COMMAND,
(MPARAM)sSelected,
MPFROM2SHORT(CMDSRC_MENU, FALSE));
break; }
default:
*pulWorkplaceFunc2 = 11000;
mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
*pulWorkplaceFunc2 = 11001;
break;
} // end switch
}
CATCH(excpt1) {
// exception occured:
return (MRESULT)0; // keep compiler happy
} END_CATCH;
*pulWorkplaceFunc2 = ulOldWorkplaceFunc2;
return (mrc);
}
/*
* fnwpSelectSome:
* dlg proc for "Select by name" window
*/
MRESULT EXPENTRY fnwpSelectSome(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mrc = MPNULL;
switch (msg) {
case WM_INITDLG: {
CHAR szTitle[CCHMAXPATH];
WinSetWindowULong(hwndDlg, QWL_USER, (ULONG)mp2); // Owner frame hwnd;
WinQueryWindowText((HWND)mp2,
sizeof(szTitle),
szTitle);
WinSetWindowText(hwndDlg, szTitle);
WinSetDlgItemText(hwndDlg, ID_XFDI_SOME_ENTRYFIELD, "*");
WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
EM_SETSEL,
MPFROM2SHORT(0, 1000), // select all
MPNULL);
mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
break; }
case WM_COMMAND: {
switch (SHORT1FROMMP(mp1)) {
/*
* ID_XFDI_SOME_SELECT / DESELECT:
* these are the "select" / "deselect" buttons
*/
case ID_XFDI_SOME_SELECT:
case ID_XFDI_SOME_DESELECT: {
CHAR szMask[CCHMAXPATH];
HWND hwndFrame = WinQueryWindowULong(hwndDlg, QWL_USER);
if (hwndFrame) {
HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
if (hwndCnr) {
WinQueryDlgItemText(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
sizeof(szMask),
szMask);
if (strlen(szMask)) {
// now go through all the container items in hwndCnr
// and select / deselct them accordingly
PMINIRECORDCORE pmrc = NULL;
do {
pmrc =
(PMINIRECORDCORE)WinSendMsg(hwndCnr,
CM_QUERYRECORD,
(MPARAM)pmrc,
MPFROM2SHORT(
(pmrc) ? CMA_NEXT : CMA_FIRST,
CMA_ITEMORDER)
);
if (pmrc) {
CHAR szTarget[CCHMAXPATH];
// CHAR szTemp[3000];
DosEditName(1,
pmrc->pszIcon,
szMask,
szTarget,
sizeof(szTarget)-1);
if (stricmp(pmrc->pszIcon, szTarget) == 0)
// if the two are equal, the cnr item matches
// the search mask
WinSendMsg(hwndCnr,
CM_SETRECORDEMPHASIS,
pmrc,
MPFROM2SHORT(
// select or deselect flag
(SHORT1FROMMP(mp1) == ID_XFDI_SOME_SELECT),
CRA_SELECTED
));
}
} while (pmrc);
}
winhSetDlgItemFocus(hwndDlg, ID_XFDI_SOME_ENTRYFIELD);
WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
EM_SETSEL,
MPFROM2SHORT(0, 1000), // select all
MPNULL);
}
}
break; }
case ID_XFDI_SOME_SELECTALL:
case ID_XFDI_SOME_DESELECTALL: {
HWND hwndFrame = WinQueryWindowULong(hwndDlg, QWL_USER);
if (hwndFrame) {
HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
if (hwndCnr) {
PMINIRECORDCORE pmrc = NULL;
do {
pmrc =
(PMINIRECORDCORE)WinSendMsg(hwndCnr,
CM_QUERYRECORD,
(MPARAM)pmrc,
MPFROM2SHORT(
(pmrc) ? CMA_NEXT : CMA_FIRST,
CMA_ITEMORDER)
);
if (pmrc) {
WinSendMsg(hwndCnr,
CM_SETRECORDEMPHASIS,
pmrc,
MPFROM2SHORT(
// select or deselect flag
(SHORT1FROMMP(mp1) == ID_XFDI_SOME_SELECTALL),
CRA_SELECTED
));
}
} while (pmrc);
winhSetDlgItemFocus(hwndDlg, ID_XFDI_SOME_ENTRYFIELD);
WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
EM_SETSEL,
MPFROM2SHORT(0, 1000), // select all
MPNULL);
}
}
break; }
default:
mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
}
break; }
default:
mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
}
return (mrc);
}