1369 lines
39 KiB
C
1369 lines
39 KiB
C
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation 1993-1994
|
||
|
//
|
||
|
// File: info.c
|
||
|
//
|
||
|
// This files contains dialog code for the Info property sheet
|
||
|
//
|
||
|
// History:
|
||
|
// 08-06-93 ScottH Transferred from twin code
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include "brfprv.h" // common headers
|
||
|
#include <brfcasep.h>
|
||
|
|
||
|
#include "res.h"
|
||
|
#include <help.h>
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// INFO dialog struct
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
// State flags for the INFO dialog
|
||
|
#define IS_ALLTYPES 0x0001
|
||
|
#define IS_INCLUDESUBS 0x0002
|
||
|
#define IS_DENYAPPLY 0x0004
|
||
|
#define IS_CHANGED 0x0008
|
||
|
#define IS_LAST_INCLUDESUBS 0x0010
|
||
|
|
||
|
typedef struct tagINFO
|
||
|
{
|
||
|
HWND hwnd; // dialog handle
|
||
|
PPAGEDATA ppagedata;
|
||
|
PINFODATA pinfodata;
|
||
|
int cselPrev; // previous count of selections
|
||
|
|
||
|
LPTSTR pszExtListPrev; // alloc: last saved settings
|
||
|
UINT uState;
|
||
|
BOOL bInit;
|
||
|
|
||
|
} INFO, * PINFO;
|
||
|
|
||
|
|
||
|
// Struct for CHANGETWINPROC callback
|
||
|
typedef struct tagCHANGEDATA
|
||
|
{
|
||
|
HBRFCASE hbrf;
|
||
|
HFOLDERTWIN hft;
|
||
|
|
||
|
HDPA hdpaTwins;
|
||
|
int idpaTwin;
|
||
|
HDPA hdpaFolders;
|
||
|
int idpaStart;
|
||
|
|
||
|
UINT uState;
|
||
|
|
||
|
} CHANGEDATA, * PCHANGEDATA;
|
||
|
|
||
|
typedef HRESULT (CALLBACK * CHANGETWINPROC)(PNEWFOLDERTWIN, TWINRESULT, PCHANGEDATA);
|
||
|
|
||
|
|
||
|
// Struct for Info_AddTwins
|
||
|
typedef struct tagADDTWINSDATA
|
||
|
{
|
||
|
CHANGETWINPROC pfnCallback;
|
||
|
HDPA hdpaSortedFolders;
|
||
|
int idpaStart;
|
||
|
} ADDTWINSDATA, * PADDTWINSDATA;
|
||
|
|
||
|
|
||
|
#define MAX_EXT_LEN 6 // Length for "*.ext"
|
||
|
|
||
|
static TCHAR const c_szAllFilesExt[] = TEXT(".*");
|
||
|
|
||
|
// Helper macros
|
||
|
|
||
|
#define Info_StandAlone(this) ((this)->pinfodata->bStandAlone)
|
||
|
|
||
|
#define Info_GetPtr(hwnd) (PINFO)GetWindowLongPtr(hwnd, DWLP_USER)
|
||
|
#define Info_SetPtr(hwnd, lp) (PINFO)SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)(lp))
|
||
|
|
||
|
|
||
|
SETbl const c_rgseInfo[4] = { // change in ibrfstg.c too
|
||
|
{ E_TR_OUT_OF_MEMORY, IDS_OOM_ADDFOLDER, MB_ERROR },
|
||
|
{ E_OUTOFMEMORY, IDS_OOM_ADDFOLDER, MB_ERROR },
|
||
|
{ E_TR_UNAVAILABLE_VOLUME, IDS_ERR_ADDFOLDER_UNAVAIL_VOL, MB_RETRYCANCEL | MB_ICONWARNING },
|
||
|
{ E_TR_SUBTREE_CYCLE_FOUND, IDS_ERR_ADD_SUBTREECYCLE, MB_WARNING },
|
||
|
};
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Info dialog functions
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Searches for an occurrence of the given extension
|
||
|
in the folder twin list.
|
||
|
|
||
|
Returns: TRUE if the extension was found
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PRIVATE FindExtension(
|
||
|
PFOLDERTWINLIST pftl,
|
||
|
LPCTSTR pszExt)
|
||
|
{
|
||
|
PCFOLDERTWIN pcft;
|
||
|
|
||
|
for (pcft = pftl->pcftFirst; pcft; pcft = pcft->pcftNext)
|
||
|
{
|
||
|
if (IsSzEqual(pszExt, pcft->pcszName))
|
||
|
{
|
||
|
return TRUE; // Found a match!
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Disable all the controls. Remove any selections.
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_DisableAll(
|
||
|
PINFO this)
|
||
|
{
|
||
|
ASSERT(!Info_StandAlone(this));
|
||
|
|
||
|
// Remove selections
|
||
|
//
|
||
|
ListBox_ResetContent(GetDlgItem(this->hwnd, IDC_LBINTYPES));
|
||
|
Button_SetCheck(GetDlgItem(this->hwnd, IDC_RBINALL), 0);
|
||
|
Button_SetCheck(GetDlgItem(this->hwnd, IDC_RBINSELECTED), 0);
|
||
|
Button_SetCheck(GetDlgItem(this->hwnd, IDC_CHININCLUDE), 0);
|
||
|
|
||
|
// Disable the controls
|
||
|
//
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDC_RBINALL), FALSE);
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDC_RBINSELECTED), FALSE);
|
||
|
|
||
|
ListBox_Enable(GetDlgItem(this->hwnd, IDC_LBINTYPES), FALSE);
|
||
|
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDC_CHININCLUDE), FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Initialize the labels for our formatted radio buttons
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_InitLabels(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndST = GetDlgItem(hwnd, IDC_CHININCLUDE);
|
||
|
TCHAR sz[MAXMSGLEN];
|
||
|
TCHAR szFmt[MAXBUFLEN];
|
||
|
LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
LPTSTR pszFile;
|
||
|
|
||
|
pszFile = PathFindFileName(pszPath);
|
||
|
|
||
|
// Set static label
|
||
|
//
|
||
|
GetWindowText(hwndST, szFmt, ARRAYSIZE(szFmt));
|
||
|
wsprintf(sz, szFmt, pszFile);
|
||
|
SetWindowText(hwndST, sz);
|
||
|
|
||
|
if (Info_StandAlone(this))
|
||
|
{
|
||
|
// Set title ("Create Twin of %s")
|
||
|
//
|
||
|
GetWindowText(hwnd, szFmt, ARRAYSIZE(szFmt));
|
||
|
wsprintf(sz, szFmt, pszFile);
|
||
|
SetWindowText(hwnd, sz);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Queries the registry for all the legal extensions that
|
||
|
are registered. These extensions are returned as a
|
||
|
space-separated list in buffer.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: Caller must GFree *ppszBuffer
|
||
|
*/
|
||
|
void PRIVATE GetExtensionList(
|
||
|
LPTSTR * ppszBuffer)
|
||
|
{
|
||
|
HKEY hkRoot;
|
||
|
|
||
|
*ppszBuffer = NULL;
|
||
|
|
||
|
if (ERROR_SUCCESS == RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hkRoot))
|
||
|
{
|
||
|
DWORD dwIndex;
|
||
|
TCHAR szExt[MAX_PATH];
|
||
|
|
||
|
// Enumerate this key
|
||
|
for (dwIndex = 0;
|
||
|
ERROR_SUCCESS == RegEnumKey(hkRoot, dwIndex, szExt, ARRAYSIZE(szExt));
|
||
|
dwIndex++)
|
||
|
{
|
||
|
// Did we get a node that is an extension AND
|
||
|
// is it a legal MS-DOS extension?
|
||
|
if (TEXT('.') == *szExt &&
|
||
|
4 >= lstrlen(szExt))
|
||
|
{
|
||
|
// Yes; add this extension to our list
|
||
|
lstrcat(szExt, TEXT(" "));
|
||
|
if (FALSE == GCatString(ppszBuffer, szExt))
|
||
|
{
|
||
|
// Uh oh, something bad happened
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
RegCloseKey(hkRoot);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Fill the file types listbox
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_FillTypesList(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HWND hwndCtl = GetDlgItem(this->hwnd, IDC_LBINTYPES);
|
||
|
LPTSTR pszExtList;
|
||
|
|
||
|
GetExtensionList(&pszExtList);
|
||
|
if (pszExtList)
|
||
|
{
|
||
|
int nTabWidth;
|
||
|
TCHAR szExt[MAXBUFLEN];
|
||
|
LPTSTR psz;
|
||
|
LPTSTR pszT;
|
||
|
UINT uLen;
|
||
|
SHFILEINFO sfi;
|
||
|
|
||
|
nTabWidth = 30;
|
||
|
ListBox_SetTabStops(hwndCtl, 1, &nTabWidth);
|
||
|
|
||
|
for (psz = pszExtList; *psz; psz = CharNext(psz))
|
||
|
{
|
||
|
// Skip any leading white-space
|
||
|
for (; TEXT(' ') == *psz; psz = CharNext(psz))
|
||
|
;
|
||
|
|
||
|
if (0 == *psz)
|
||
|
{
|
||
|
break; // End of string
|
||
|
}
|
||
|
|
||
|
// Skip to next white-space (or null)
|
||
|
for (pszT = psz; TEXT(' ') < *pszT; pszT = CharNext(pszT))
|
||
|
{
|
||
|
// (This will also stop at null)
|
||
|
}
|
||
|
|
||
|
// (GetExtensionList should only get max 3 char extensions)
|
||
|
uLen = (UINT)(pszT - psz);
|
||
|
ASSERT(ARRAYSIZE(szExt) > uLen);
|
||
|
|
||
|
lstrcpyn(szExt, psz, uLen+1);
|
||
|
CharUpper(szExt);
|
||
|
SHGetFileInfo(szExt, 0, &sfi, sizeof(sfi), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
|
||
|
|
||
|
// Although this forces the format for international versions,
|
||
|
// it makes extraction much much easier.
|
||
|
lstrcat(szExt, TEXT("\t("));
|
||
|
lstrcat(szExt, sfi.szTypeName);
|
||
|
lstrcat(szExt, TEXT(")"));
|
||
|
ListBox_AddString(hwndCtl, szExt);
|
||
|
|
||
|
psz = pszT; // To next extension
|
||
|
}
|
||
|
|
||
|
GFree(pszExtList);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Set the selection of the dialog controls
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_SetSelections(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HWND hwndLB = GetDlgItem(this->hwnd, IDC_LBINTYPES);
|
||
|
int idBtn;
|
||
|
int cItems = ListBox_GetCount(hwndLB);
|
||
|
|
||
|
ListBox_SetSel(hwndLB, FALSE, -1); // deselect everything
|
||
|
|
||
|
// Is this the 'Add Folder' dialog?
|
||
|
if (Info_StandAlone(this))
|
||
|
{
|
||
|
// Yes; default to *.* settings
|
||
|
SetFlag(this->uState, IS_ALLTYPES);
|
||
|
SetFlag(this->uState, IS_INCLUDESUBS);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; query what the selections are
|
||
|
TCHAR szExt[MAXBUFLEN];
|
||
|
PFOLDERTWINLIST pftl;
|
||
|
PCFOLDERTWIN pcft;
|
||
|
int cItems;
|
||
|
int i;
|
||
|
BOOL bStarDotStar;
|
||
|
LPTSTR psz;
|
||
|
|
||
|
if (S_OK == PageData_Query(this->ppagedata, this->hwnd, NULL, &pftl))
|
||
|
{
|
||
|
// Determine the selections in the listbox
|
||
|
szExt[0] = TEXT('*');
|
||
|
|
||
|
cItems = ListBox_GetCount(hwndLB);
|
||
|
for (i = 0; i < cItems; i++)
|
||
|
{
|
||
|
// Extract the extension (it will be the first part of the
|
||
|
// string)
|
||
|
ListBox_GetText(hwndLB, i, &szExt[1]);
|
||
|
for (psz = szExt; *psz && TEXT('\t') != *psz; psz = CharNext(psz))
|
||
|
;
|
||
|
ASSERT(TEXT('\t') == *psz);
|
||
|
*psz = 0; // null terminate after the extension
|
||
|
|
||
|
// Is this extension in the folder twin list?
|
||
|
if (FindExtension(pftl, szExt))
|
||
|
{
|
||
|
// Yes; select the entry
|
||
|
ListBox_SetSel(hwndLB, TRUE, i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ListBox_SetTopIndex(hwndLB, 0);
|
||
|
this->cselPrev = ListBox_GetSelCount(hwndLB);
|
||
|
|
||
|
// Determine the Include Subdirectories checkbox setting
|
||
|
//
|
||
|
bStarDotStar = FALSE;
|
||
|
ClearFlag(this->uState, IS_INCLUDESUBS);
|
||
|
for (pcft = pftl->pcftFirst; pcft; pcft = pcft->pcftNext)
|
||
|
{
|
||
|
if (IsFlagSet(pcft->dwFlags, FT_FL_SUBTREE))
|
||
|
SetFlag(this->uState, IS_INCLUDESUBS);
|
||
|
|
||
|
if (IsSzEqual(pcft->pcszName, c_szAllFiles))
|
||
|
bStarDotStar = TRUE;
|
||
|
}
|
||
|
|
||
|
// Set the default radio button choice, and disable listbox
|
||
|
// if necessary. The default radio choice will be IDC_RBINALL,
|
||
|
// unless there are selections in the listbox AND there is no
|
||
|
// *.* occurrence in the folder twin list.
|
||
|
//
|
||
|
if (0 == this->cselPrev || bStarDotStar)
|
||
|
SetFlag(this->uState, IS_ALLTYPES);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_ALLTYPES);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// An error occurred or this is an orphan. Bail early.
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (IsFlagSet(this->uState, IS_INCLUDESUBS))
|
||
|
SetFlag(this->uState, IS_LAST_INCLUDESUBS);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_LAST_INCLUDESUBS);
|
||
|
|
||
|
// Set the control settings
|
||
|
Button_SetCheck(GetDlgItem(this->hwnd, IDC_CHININCLUDE), IsFlagSet(this->uState, IS_INCLUDESUBS));
|
||
|
|
||
|
ListBox_Enable(hwndLB, IsFlagClear(this->uState, IS_ALLTYPES));
|
||
|
idBtn = IsFlagSet(this->uState, IS_ALLTYPES) ? IDC_RBINALL : IDC_RBINSELECTED;
|
||
|
CheckRadioButton(this->hwnd, IDC_RBINALL, IDC_RBINSELECTED, idBtn);
|
||
|
|
||
|
// If listbox is empty, disable Selected Types radio button
|
||
|
if (0 == cItems)
|
||
|
{
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDC_RBINSELECTED), FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Get the selected extensions in the listbox
|
||
|
and place them as a list in *ppszExtList.
|
||
|
|
||
|
.* is placed in the buffer if the Select All radio button
|
||
|
is chosen instead.
|
||
|
|
||
|
Returns: TRUE on success
|
||
|
|
||
|
Cond: The caller must GFree *ppszExtList
|
||
|
*/
|
||
|
BOOL PRIVATE Info_GetSelections(
|
||
|
PINFO this,
|
||
|
LPTSTR * ppszExtList)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
*ppszExtList = NULL;
|
||
|
|
||
|
// Did user choose the All Types radio button?
|
||
|
if (IsFlagSet(this->uState, IS_ALLTYPES))
|
||
|
{
|
||
|
// Yes; store the .* extension
|
||
|
bRet = GSetString(ppszExtList, c_szAllFilesExt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; user selected a bunch of wildcards to filter
|
||
|
LPINT pisel;
|
||
|
TCHAR szExt[MAXBUFLEN];
|
||
|
int csel;
|
||
|
int isel;
|
||
|
HWND hwndCtl = GetDlgItem(this->hwnd, IDC_LBINTYPES);
|
||
|
|
||
|
// Allocate memory for the selection buffer
|
||
|
csel = ListBox_GetSelCount(hwndCtl);
|
||
|
pisel = GAllocArray(int, csel);
|
||
|
if (pisel)
|
||
|
{
|
||
|
// Get the selected extensions from the listbox
|
||
|
LPTSTR psz;
|
||
|
|
||
|
if (0 < csel)
|
||
|
{
|
||
|
ListBox_GetSelItems(hwndCtl, csel, pisel);
|
||
|
for (isel = 0; isel < csel; isel++)
|
||
|
{
|
||
|
// Extract the extension (it will be the first part of the string)
|
||
|
ListBox_GetText(hwndCtl, pisel[isel], szExt);
|
||
|
for (psz = szExt; *psz && TEXT('\t') != *psz; psz = CharNext(psz))
|
||
|
;
|
||
|
ASSERT(TEXT('\t') == *psz);
|
||
|
*psz = 0;
|
||
|
|
||
|
if (FALSE == GCatString(ppszExtList, szExt))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isel == csel)
|
||
|
{
|
||
|
bRet = TRUE; // Success
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GFree(*ppszExtList);
|
||
|
}
|
||
|
}
|
||
|
GFree(pisel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Create a sorted DPA version of the folder twin list
|
||
|
|
||
|
Returns: hdpa
|
||
|
NULL on OOM
|
||
|
Cond: --
|
||
|
*/
|
||
|
HDPA PRIVATE CreateSortedFolderDPA(
|
||
|
PFOLDERTWINLIST pftl)
|
||
|
{
|
||
|
HDPA hdpa;
|
||
|
|
||
|
ASSERT(pftl);
|
||
|
|
||
|
hdpa = DPA_Create(8);
|
||
|
if (hdpa)
|
||
|
{
|
||
|
PCFOLDERTWIN pcft;
|
||
|
|
||
|
for (pcft = pftl->pcftFirst; pcft; pcft = pcft->pcftNext)
|
||
|
{
|
||
|
// Use the dwUser field as a deletion flag
|
||
|
((PFOLDERTWIN)pcft)->dwUser = FALSE;
|
||
|
|
||
|
if (DPA_ERR == DPA_InsertPtr(hdpa, DPA_APPEND, (LPVOID)pcft))
|
||
|
{
|
||
|
DPA_Destroy(hdpa);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
DPA_Sort(hdpa, NCompareFolders, CMP_FOLDERTWINS);
|
||
|
}
|
||
|
|
||
|
return hdpa;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Process callback after adding a folder twin
|
||
|
|
||
|
Returns: standard result
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT CALLBACK ChangeTwinProc(
|
||
|
PNEWFOLDERTWIN pnft,
|
||
|
TWINRESULT tr,
|
||
|
PCHANGEDATA pcd)
|
||
|
{
|
||
|
HRESULT hres = NOERROR;
|
||
|
|
||
|
// Is this a duplicate twin?
|
||
|
if (TR_DUPLICATE_TWIN == tr)
|
||
|
{
|
||
|
// Yes; there's a wierd case to deal with. It's possible that the
|
||
|
// only thing the user did was check/uncheck the Include Subdirs
|
||
|
// checkbox. If this is true, then we delete the old twin and add
|
||
|
// a new twin (with same filespec as before) with the flags set
|
||
|
// differently.
|
||
|
PCFOLDERTWIN pcft;
|
||
|
HDPA hdpaFolders = pcd->hdpaFolders;
|
||
|
int cdpa = DPA_GetPtrCount(hdpaFolders);
|
||
|
int idpa;
|
||
|
BOOL bOldInclude;
|
||
|
|
||
|
// Find the correct pcfolder. We will either tag it or
|
||
|
// we will delete it right now and re-add the new twin.
|
||
|
for (idpa = pcd->idpaStart; idpa < cdpa; idpa++)
|
||
|
{
|
||
|
pcft = DPA_FastGetPtr(hdpaFolders, idpa);
|
||
|
|
||
|
if (IsSzEqual(pcft->pcszName, pnft->pcszName))
|
||
|
break; // found it!
|
||
|
}
|
||
|
ASSERT(idpa < cdpa);
|
||
|
|
||
|
// Tag the twin to save from impending doom...
|
||
|
((PFOLDERTWIN)(DWORD_PTR)pcft)->dwUser = TRUE;
|
||
|
|
||
|
// Has the Include Subfolders checkbox setting changed?
|
||
|
bOldInclude = IsFlagSet(pcft->dwFlags, FT_FL_SUBTREE);
|
||
|
if (bOldInclude ^ IsFlagSet(pcd->uState, IS_INCLUDESUBS))
|
||
|
{
|
||
|
// Yes; delete the twin anyway and add the new one.
|
||
|
HFOLDERTWIN hft;
|
||
|
|
||
|
DEBUG_CODE( TRACE_MSG(TF_GENERAL, TEXT("Deleting old folder twin")); )
|
||
|
Sync_DeleteTwin(pcft->hftOther);
|
||
|
|
||
|
// Add the new folder twin to the database
|
||
|
tr = Sync_AddFolder(pcd->hbrf, pnft, &hft);
|
||
|
if (TR_SUCCESS != tr)
|
||
|
{
|
||
|
// Adding the new twin failed
|
||
|
DPA_DeletePtr(pcd->hdpaTwins, pcd->idpaTwin);
|
||
|
hres = HRESULT_FROM_TR(tr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Set the new twin handle in the pcd->hdpaTwins list
|
||
|
DPA_SetPtr(pcd->hdpaTwins, pcd->idpaTwin, (LPVOID)hft);
|
||
|
|
||
|
DEBUG_CODE( TRACE_MSG(TF_GENERAL, TEXT("Adding new folder twin")); )
|
||
|
DEBUG_CODE( Sync_Dump(pnft, NEWFOLDERTWIN); )
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; this isn't new, so don't add to list
|
||
|
DPA_DeletePtr(pcd->hdpaTwins, pcd->idpaTwin);
|
||
|
}
|
||
|
}
|
||
|
else if (tr != TR_SUCCESS)
|
||
|
{
|
||
|
// Sync_AddFolder failed
|
||
|
DPA_DeletePtr(pcd->hdpaTwins, pcd->idpaTwin);
|
||
|
hres = HRESULT_FROM_TR(tr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sync_AddFolder succeeded
|
||
|
DPA_SetPtr(pcd->hdpaTwins, pcd->idpaTwin, (LPVOID)pcd->hft);
|
||
|
|
||
|
DEBUG_CODE( TRACE_MSG(TF_GENERAL, TEXT("Adding new folder twin")); )
|
||
|
DEBUG_CODE( Sync_Dump(pnft, NEWFOLDERTWIN); )
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Add folder twins based on the list of extensions
|
||
|
|
||
|
Returns: standard result
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT PRIVATE Info_AddTwins(
|
||
|
PINFO this,
|
||
|
PNEWFOLDERTWIN pnft,
|
||
|
PADDTWINSDATA patd, // May be NULL
|
||
|
LPTSTR pszExtList) // This function writes in this buffer
|
||
|
{
|
||
|
HRESULT hres = NOERROR;
|
||
|
CHANGEDATA cd;
|
||
|
HDPA hdpa;
|
||
|
int idpa;
|
||
|
TCHAR szWildcard[MAX_EXT_LEN];
|
||
|
LPTSTR psz;
|
||
|
LPTSTR pszT;
|
||
|
TCHAR ch;
|
||
|
|
||
|
hdpa = this->pinfodata->hdpaTwins;
|
||
|
|
||
|
cd.hbrf = PageData_GetHbrf(this->ppagedata);
|
||
|
cd.hdpaTwins = hdpa;
|
||
|
if (patd)
|
||
|
{
|
||
|
cd.hdpaFolders = patd->hdpaSortedFolders;
|
||
|
cd.idpaStart = patd->idpaStart;
|
||
|
}
|
||
|
cd.uState = this->uState;
|
||
|
|
||
|
pnft->pcszName = szWildcard;
|
||
|
szWildcard[0] = TEXT('*');
|
||
|
|
||
|
for (psz = pszExtList; *psz; )
|
||
|
{
|
||
|
TWINRESULT tr;
|
||
|
HFOLDERTWIN hft = NULL;
|
||
|
|
||
|
// Find the beginning of the next extension for the next iteration
|
||
|
for (pszT = CharNext(psz); *pszT && TEXT('.') != *pszT; pszT = CharNext(pszT))
|
||
|
;
|
||
|
ch = *pszT;
|
||
|
*pszT = 0; // Temporary assignment
|
||
|
|
||
|
// Copy the extension into the name string
|
||
|
lstrcpy(&szWildcard[1], psz);
|
||
|
|
||
|
*pszT = ch;
|
||
|
psz = pszT;
|
||
|
|
||
|
// First make sure we can add another handle to hdpaTwins
|
||
|
if (DPA_ERR == (idpa = DPA_InsertPtr(hdpa, DPA_APPEND, (LPVOID)hft)))
|
||
|
{
|
||
|
hres = ResultFromScode(E_OUTOFMEMORY);
|
||
|
break; // Failed
|
||
|
}
|
||
|
|
||
|
// Add the folder twin to the database
|
||
|
tr = Sync_AddFolder(cd.hbrf, pnft, &hft);
|
||
|
|
||
|
if (patd)
|
||
|
{
|
||
|
cd.idpaTwin = idpa;
|
||
|
cd.hft = hft;
|
||
|
|
||
|
ASSERT(patd->pfnCallback);
|
||
|
if ( FAILED((hres = patd->pfnCallback(pnft, tr, &cd))) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if (TR_SUCCESS != tr)
|
||
|
{
|
||
|
// Sync_AddFolder failed
|
||
|
DPA_DeletePtr(hdpa, idpa);
|
||
|
hres = HRESULT_FROM_TR(tr);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sync_AddFolder succeeded
|
||
|
DPA_SetPtr(hdpa, idpa, (LPVOID)hft);
|
||
|
|
||
|
DEBUG_CODE( Sync_Dump(pnft, NEWFOLDERTWIN); )
|
||
|
}
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Add the folder twin to the database
|
||
|
|
||
|
Returns: standard result
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT PRIVATE Info_CommitStandAlone(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
NEWFOLDERTWIN nft;
|
||
|
LPTSTR pszExtList;
|
||
|
|
||
|
RETRY_BEGIN(FALSE)
|
||
|
{
|
||
|
ZeroInit(&nft, NEWFOLDERTWIN);
|
||
|
nft.ulSize = sizeof(nft);
|
||
|
nft.pcszFolder1 = Atom_GetName(this->ppagedata->atomPath);
|
||
|
nft.pcszFolder2 = Atom_GetName(this->pinfodata->atomTo);
|
||
|
// nft.pcszName is set in Info_AddTwins()
|
||
|
nft.dwAttributes = OBJECT_TWIN_ATTRIBUTES;
|
||
|
nft.dwFlags = IsFlagSet(this->uState, IS_INCLUDESUBS) ? NFT_FL_SUBTREE : 0;
|
||
|
|
||
|
// Create an extension list based on the dialog settings
|
||
|
if (!Info_GetSelections(this, &pszExtList))
|
||
|
{
|
||
|
// Failed
|
||
|
hres = ResultFromScode(E_OUTOFMEMORY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Add the twins
|
||
|
hres = Info_AddTwins(this, &nft, NULL, pszExtList);
|
||
|
GFree(pszExtList);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
// Since the engine does not create folders if the folder is empty,
|
||
|
// we will create the folder now (whether it is empty or not).
|
||
|
// If the folder already exists, CreateDirectory will fail.
|
||
|
// Big deal.
|
||
|
CreateDirectory(nft.pcszFolder2, NULL);
|
||
|
PathNotifyShell(nft.pcszFolder2, NSE_MKDIR, FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD dwError = GetLastError();
|
||
|
int id;
|
||
|
|
||
|
// Unavailable disk?
|
||
|
if (ERROR_INVALID_DATA == dwError || ERROR_ACCESS_DENIED == dwError)
|
||
|
{
|
||
|
// Yes
|
||
|
hres = E_TR_UNAVAILABLE_VOLUME;
|
||
|
}
|
||
|
|
||
|
id = SEMsgBox(this->hwnd, IDS_CAP_INFO, hres, c_rgseInfo, ARRAYSIZE(c_rgseInfo));
|
||
|
if (IDRETRY == id)
|
||
|
{
|
||
|
// Try the operation again
|
||
|
RETRY_SET();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
RETRY_END()
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Commit the user changes to the database. We delete
|
||
|
all old hFolderTwins, and add new ones.
|
||
|
|
||
|
Returns: standard result
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT PRIVATE Info_CommitChange(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
PFOLDERTWINLIST pftl;
|
||
|
|
||
|
hres = PageData_Query(this->ppagedata, this->hwnd, NULL, &pftl);
|
||
|
if (S_FALSE == hres)
|
||
|
{
|
||
|
// The folder has become an orphan right under our nose.
|
||
|
// Don't do anything.
|
||
|
Info_DisableAll(this);
|
||
|
}
|
||
|
else if (S_OK == hres)
|
||
|
{
|
||
|
LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
ADDTWINSDATA atd;
|
||
|
DECLAREHOURGLASS;
|
||
|
|
||
|
SetHourglass();
|
||
|
|
||
|
atd.pfnCallback = ChangeTwinProc;
|
||
|
|
||
|
// Create a sorted DPA based on the folder twin list
|
||
|
atd.hdpaSortedFolders = CreateSortedFolderDPA(pftl);
|
||
|
if (atd.hdpaSortedFolders)
|
||
|
{
|
||
|
// Create an extension list based on the dialog settings
|
||
|
LPTSTR pszExtList = NULL;
|
||
|
|
||
|
if (Info_GetSelections(this, &pszExtList))
|
||
|
{
|
||
|
NEWFOLDERTWIN nft;
|
||
|
PCFOLDERTWIN pcft;
|
||
|
PCFOLDERTWIN pcftLast;
|
||
|
int idpa;
|
||
|
int cdpa;
|
||
|
|
||
|
// Now add new folder twins. Iterate thru atd.hdpaSortedFolders.
|
||
|
// For each unique folder twin in this list, we add a new twin,
|
||
|
// using the old lpcszFolder as the lpcszFolder2 field in our
|
||
|
// NEWFOLDERTWIN structure.
|
||
|
//
|
||
|
ZeroInit(&nft, NEWFOLDERTWIN);
|
||
|
nft.ulSize = sizeof(NEWFOLDERTWIN);
|
||
|
nft.pcszFolder1 = pszPath;
|
||
|
// nft.pcszFolder2 is set in loop below
|
||
|
// nft.pcszName is set in Info_AddTwins()
|
||
|
nft.dwAttributes = OBJECT_TWIN_ATTRIBUTES;
|
||
|
nft.dwFlags = IsFlagSet(this->uState, IS_INCLUDESUBS) ? NFT_FL_SUBTREE : 0;
|
||
|
|
||
|
// Iterate thru existing folder twins. Act on each unique one.
|
||
|
cdpa = DPA_GetPtrCount(atd.hdpaSortedFolders);
|
||
|
pcftLast = NULL;
|
||
|
for (idpa = 0; idpa < cdpa; idpa++)
|
||
|
{
|
||
|
pcft = DPA_FastGetPtr(atd.hdpaSortedFolders, idpa);
|
||
|
|
||
|
// Unique?
|
||
|
if (pcftLast && pcft->pcszOtherFolder == pcftLast->pcszOtherFolder)
|
||
|
{
|
||
|
// No; skip to next one
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// This is a unique folder. Add it using the extensions in
|
||
|
// pszExtList.
|
||
|
atd.idpaStart = idpa;
|
||
|
nft.pcszFolder2 = pcft->pcszOtherFolder;
|
||
|
|
||
|
hres = Info_AddTwins(this, &nft, &atd, pszExtList);
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
pcftLast = pcft;
|
||
|
}
|
||
|
|
||
|
// Delete any old twins
|
||
|
for (pcft = pftl->pcftFirst; pcft; pcft = pcft->pcftNext)
|
||
|
{
|
||
|
// Is it okay to delete this twin?
|
||
|
if (pcft->hftOther && FALSE == pcft->dwUser)
|
||
|
{
|
||
|
// Yes
|
||
|
TRACE_MSG(TF_GENERAL, TEXT("Deleting folder twin with extension '%s'"), pcft->pcszName);
|
||
|
Sync_DeleteTwin(pcft->hftOther);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
GFree(pszExtList);
|
||
|
}
|
||
|
DPA_Destroy(atd.hdpaSortedFolders);
|
||
|
}
|
||
|
|
||
|
ResetHourglass();
|
||
|
|
||
|
// Notify the shell of the change
|
||
|
PathNotifyShell(pszPath, NSE_UPDATEITEM, FALSE);
|
||
|
|
||
|
// Throw out the last saved settings and reset
|
||
|
GFree(this->pszExtListPrev);
|
||
|
Info_GetSelections(this, &this->pszExtListPrev);
|
||
|
|
||
|
this->ppagedata->bRecalc = TRUE;
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
static SETbl const c_rgseInfoChange[] = {
|
||
|
{ E_TR_OUT_OF_MEMORY, IDS_OOM_CHANGETYPES, MB_ERROR },
|
||
|
{ E_OUTOFMEMORY, IDS_OOM_CHANGETYPES, MB_ERROR },
|
||
|
{ E_TR_SUBTREE_CYCLE_FOUND, IDS_ERR_ADD_SUBTREECYCLE, MB_WARNING },
|
||
|
};
|
||
|
|
||
|
SEMsgBox(this->hwnd, IDS_CAP_INFO, hres, c_rgseInfoChange, ARRAYSIZE(c_rgseInfoChange));
|
||
|
}
|
||
|
}
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Info WM_INITDIALOG Handler
|
||
|
Returns:
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PRIVATE Info_OnInitDialog(
|
||
|
PINFO this,
|
||
|
HWND hwndFocus,
|
||
|
LPARAM lParam) // LPPROPSHEETINFO
|
||
|
{
|
||
|
this->ppagedata = (PPAGEDATA)((LPPROPSHEETPAGE)lParam)->lParam;
|
||
|
this->pinfodata = (PINFODATA)this->ppagedata->lParam;
|
||
|
|
||
|
// Set the text of the controls
|
||
|
Info_InitLabels(this);
|
||
|
|
||
|
// Fill listbox and set the control selections
|
||
|
Info_FillTypesList(this);
|
||
|
if (Info_StandAlone(this))
|
||
|
{
|
||
|
Info_SetSelections(this);
|
||
|
Info_GetSelections(this, &this->pszExtListPrev);
|
||
|
}
|
||
|
|
||
|
this->bInit = TRUE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: PSN_APPLY handler
|
||
|
|
||
|
Returns: FALSE if everything is OK
|
||
|
TRUE to have the property sheet switch to this page to
|
||
|
correct something.
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PRIVATE Info_OnApply(
|
||
|
PINFO this)
|
||
|
{
|
||
|
BOOL bRet;
|
||
|
LPTSTR pszExtList;
|
||
|
|
||
|
ASSERT(!Info_StandAlone(this));
|
||
|
|
||
|
Info_GetSelections(this, &pszExtList);
|
||
|
|
||
|
// Deny the apply?
|
||
|
if (IsFlagSet(this->uState, IS_DENYAPPLY))
|
||
|
{
|
||
|
// Yes; don't let the apply go thru
|
||
|
MsgBox(this->hwnd, MAKEINTRESOURCE(IDS_MSG_SPECIFYTYPE),
|
||
|
MAKEINTRESOURCE(IDS_CAP_INFO), NULL, MB_ERROR);
|
||
|
bRet = PSNRET_INVALID;
|
||
|
}
|
||
|
// Have any settings changed?
|
||
|
else if (pszExtList && this->pszExtListPrev &&
|
||
|
// (Assume extensions are always listed in same order)
|
||
|
IsSzEqual(this->pszExtListPrev, pszExtList) &&
|
||
|
IsFlagSet(this->uState, IS_INCLUDESUBS) == IsFlagSet(this->uState, IS_LAST_INCLUDESUBS))
|
||
|
{
|
||
|
// No
|
||
|
bRet = PSNRET_NOERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Yes; commit the changes
|
||
|
Info_CommitChange(this);
|
||
|
|
||
|
// Sync up the current/previous state
|
||
|
if (IsFlagSet(this->uState, IS_INCLUDESUBS))
|
||
|
SetFlag(this->uState, IS_LAST_INCLUDESUBS);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_LAST_INCLUDESUBS);
|
||
|
|
||
|
bRet = PSNRET_NOERROR;
|
||
|
}
|
||
|
|
||
|
GFree(pszExtList);
|
||
|
ClearFlag(this->uState, IS_CHANGED);
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: PSN_SETACTIVE handler
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_OnSetActive(
|
||
|
PINFO this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
|
||
|
// Cause the page to be painted right away
|
||
|
SetWindowRedraw(hwnd, TRUE);
|
||
|
InvalidateRect(hwnd, NULL, TRUE);
|
||
|
UpdateWindow(hwnd);
|
||
|
|
||
|
if (this->bInit)
|
||
|
{
|
||
|
PageData_Init(this->ppagedata, GetParent(hwnd));
|
||
|
this->bInit = FALSE;
|
||
|
|
||
|
Info_SetSelections(this);
|
||
|
Info_GetSelections(this, &this->pszExtListPrev);
|
||
|
}
|
||
|
|
||
|
// Is this data still valid?
|
||
|
else if (S_FALSE == PageData_Query(this->ppagedata, this->hwnd, NULL, NULL))
|
||
|
{
|
||
|
// No; the folder has become an orphan
|
||
|
Info_DisableAll(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: WM_NOTIFY handler
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
LRESULT PRIVATE Info_OnNotify(
|
||
|
PINFO this,
|
||
|
int idFrom,
|
||
|
NMHDR * lpnmhdr)
|
||
|
{
|
||
|
LRESULT lRet = 0;
|
||
|
|
||
|
switch (lpnmhdr->code)
|
||
|
{
|
||
|
case PSN_SETACTIVE:
|
||
|
Info_OnSetActive(this);
|
||
|
break;
|
||
|
|
||
|
case PSN_APPLY:
|
||
|
lRet = Info_OnApply(this);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Determines whether to keep from leaving this sheet.
|
||
|
For the stand-alone ('Add Folder') dialog, this
|
||
|
function enables or disables the OK button.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_DenyKill(
|
||
|
PINFO this,
|
||
|
BOOL bDeny)
|
||
|
{
|
||
|
if (Info_StandAlone(this))
|
||
|
{
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDOK), !bDeny);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (bDeny)
|
||
|
SetFlag(this->uState, IS_DENYAPPLY);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_DENYAPPLY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Enable the Apply button
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_HandleChange(
|
||
|
PINFO this)
|
||
|
{
|
||
|
if (IsFlagClear(this->uState, IS_CHANGED) && !Info_StandAlone(this))
|
||
|
{
|
||
|
SetFlag(this->uState, IS_CHANGED);
|
||
|
PropSheet_Changed(GetParent(this->hwnd), this->hwnd);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Info WM_COMMAND Handler
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
VOID PRIVATE Info_OnCommand(
|
||
|
PINFO this,
|
||
|
int id,
|
||
|
HWND hwndCtl,
|
||
|
UINT uNotifyCode)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
|
||
|
switch (id)
|
||
|
{
|
||
|
case IDC_RBINALL:
|
||
|
Info_DenyKill(this, FALSE);
|
||
|
|
||
|
// fall thru
|
||
|
|
||
|
case IDC_RBINSELECTED:
|
||
|
// Disable/enable listbox depending on which radio button
|
||
|
// is marked.
|
||
|
//
|
||
|
if (IDC_RBINALL == id)
|
||
|
SetFlag(this->uState, IS_ALLTYPES);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_ALLTYPES);
|
||
|
ListBox_Enable(GetDlgItem(hwnd, IDC_LBINTYPES), IsFlagClear(this->uState, IS_ALLTYPES));
|
||
|
|
||
|
if (IDC_RBINSELECTED == id &&
|
||
|
0 == ListBox_GetSelCount(GetDlgItem(hwnd, IDC_LBINTYPES)))
|
||
|
{
|
||
|
Info_DenyKill(this, TRUE);
|
||
|
}
|
||
|
|
||
|
Info_HandleChange(this);
|
||
|
break;
|
||
|
|
||
|
case IDC_LBINTYPES:
|
||
|
if (uNotifyCode == LBN_SELCHANGE)
|
||
|
{
|
||
|
// Disable/enable OK button based on number of selections
|
||
|
// in listbox.
|
||
|
//
|
||
|
int csel = ListBox_GetSelCount(GetDlgItem(hwnd, IDC_LBINTYPES));
|
||
|
|
||
|
if (csel == 0)
|
||
|
Info_DenyKill(this, TRUE);
|
||
|
else if (csel != this->cselPrev && this->cselPrev == 0)
|
||
|
Info_DenyKill(this, FALSE);
|
||
|
this->cselPrev = csel;
|
||
|
|
||
|
Info_HandleChange(this);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case IDC_CHININCLUDE:
|
||
|
if (FALSE != Button_GetCheck(GetDlgItem(hwnd, IDC_CHININCLUDE)))
|
||
|
SetFlag(this->uState, IS_INCLUDESUBS);
|
||
|
else
|
||
|
ClearFlag(this->uState, IS_INCLUDESUBS);
|
||
|
Info_HandleChange(this);
|
||
|
break;
|
||
|
|
||
|
case IDOK:
|
||
|
if (FAILED(Info_CommitStandAlone(this)))
|
||
|
EndDialog(hwnd, -1);
|
||
|
|
||
|
// Fall thru
|
||
|
// | |
|
||
|
// v v
|
||
|
|
||
|
case IDCANCEL:
|
||
|
if (Info_StandAlone(this))
|
||
|
EndDialog(hwnd, id);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Handle WM_DESTROY
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Info_OnDestroy(
|
||
|
PINFO this)
|
||
|
{
|
||
|
GFree(this->pszExtListPrev);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////// PRIVATE FUNCTIONS
|
||
|
|
||
|
|
||
|
static BOOL s_bInfoRecurse = FALSE;
|
||
|
|
||
|
LRESULT INLINE Info_DefProc(
|
||
|
HWND hDlg,
|
||
|
UINT msg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
ENTEREXCLUSIVE();
|
||
|
{
|
||
|
s_bInfoRecurse = TRUE;
|
||
|
}
|
||
|
LEAVEEXCLUSIVE();
|
||
|
|
||
|
return DefDlgProc(hDlg, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Real Create Folder Twin dialog proc
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
LRESULT Info_DlgProc(
|
||
|
PINFO this,
|
||
|
UINT message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
const static DWORD rgHelpIDs[] = {
|
||
|
IDC_RBINALL, IDH_BFC_FILTER_TYPE,
|
||
|
IDC_RBINSELECTED, IDH_BFC_FILTER_TYPE,
|
||
|
IDC_LBINTYPES, IDH_BFC_FILTER_TYPE,
|
||
|
IDC_CHININCLUDE, IDH_BFC_FILTER_INCLUDE,
|
||
|
IDC_GBIN, IDH_BFC_FILTER_TYPE,
|
||
|
0, 0 };
|
||
|
|
||
|
switch (message)
|
||
|
{
|
||
|
HANDLE_MSG(this, WM_INITDIALOG, Info_OnInitDialog);
|
||
|
HANDLE_MSG(this, WM_COMMAND, Info_OnCommand);
|
||
|
HANDLE_MSG(this, WM_NOTIFY, Info_OnNotify);
|
||
|
HANDLE_MSG(this, WM_DESTROY, Info_OnDestroy);
|
||
|
|
||
|
case WM_HELP:
|
||
|
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szWinHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPVOID)rgHelpIDs);
|
||
|
return 0;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
WinHelp((HWND)wParam, c_szWinHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID)rgHelpIDs);
|
||
|
return 0;
|
||
|
|
||
|
default:
|
||
|
return Info_DefProc(this->hwnd, message, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Create Folder Twin Dialog Wrapper
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
INT_PTR _export CALLBACK Info_WrapperProc(
|
||
|
HWND hDlg, // std params
|
||
|
UINT message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
PINFO this;
|
||
|
|
||
|
// Cool windowsx.h dialog technique. For full explanation, see
|
||
|
// WINDOWSX.TXT. This supports multiple-instancing of dialogs.
|
||
|
//
|
||
|
ENTEREXCLUSIVE();
|
||
|
{
|
||
|
if (s_bInfoRecurse)
|
||
|
{
|
||
|
s_bInfoRecurse = FALSE;
|
||
|
LEAVEEXCLUSIVE();
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
LEAVEEXCLUSIVE();
|
||
|
|
||
|
this = Info_GetPtr(hDlg);
|
||
|
if (this == NULL)
|
||
|
{
|
||
|
if (message == WM_INITDIALOG)
|
||
|
{
|
||
|
this = GAlloc(sizeof(*this));
|
||
|
if (!this)
|
||
|
{
|
||
|
MsgBox(hDlg, MAKEINTRESOURCE(IDS_OOM_INFO), MAKEINTRESOURCE(IDS_CAP_INFO),
|
||
|
NULL, MB_ERROR);
|
||
|
EndDialog(hDlg, IDCANCEL);
|
||
|
return Info_DefProc(hDlg, message, wParam, lParam);
|
||
|
}
|
||
|
this->hwnd = hDlg;
|
||
|
Info_SetPtr(hDlg, this);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return Info_DefProc(hDlg, message, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (message == WM_DESTROY)
|
||
|
{
|
||
|
Info_DlgProc(this, message, wParam, lParam);
|
||
|
GFree(this);
|
||
|
Info_SetPtr(hDlg, NULL);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return SetDlgMsgResult(hDlg, message, Info_DlgProc(this, message, wParam, lParam));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////// PUBLIC FUNCTIONS
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Entry point to invoke dialog
|
||
|
|
||
|
Returns: standard hresult
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT PUBLIC Info_DoModal(
|
||
|
HWND hwndOwner,
|
||
|
LPCTSTR pszPathFrom, // Source path
|
||
|
LPCTSTR pszPathTo, // Target path
|
||
|
HDPA hdpaTwin,
|
||
|
PCBS pcbs)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
PROPSHEETPAGE psp;
|
||
|
PAGEDATA pagedata;
|
||
|
INFODATA infodata;
|
||
|
|
||
|
// (Use the source path for the atomPath because the target path
|
||
|
// does not exist yet.)
|
||
|
pagedata.atomPath = Atom_Add(pszPathFrom);
|
||
|
if (ATOM_ERR != pagedata.atomPath)
|
||
|
{
|
||
|
infodata.atomTo = Atom_Add(pszPathTo);
|
||
|
if (ATOM_ERR != infodata.atomTo)
|
||
|
{
|
||
|
INT_PTR nRet;
|
||
|
|
||
|
pagedata.pcbs = pcbs;
|
||
|
pagedata.lParam = (LPARAM)&infodata;
|
||
|
|
||
|
infodata.hdpaTwins = hdpaTwin;
|
||
|
infodata.bStandAlone = TRUE;
|
||
|
|
||
|
// Fake up a propsheetinfo struct for the dialog box
|
||
|
psp.lParam = (LPARAM)&pagedata; // this is all we care about
|
||
|
|
||
|
nRet = DoModal(hwndOwner, Info_WrapperProc, IDD_INFOCREATE, (LPARAM)(LPVOID)&psp);
|
||
|
Atom_Delete(infodata.atomTo);
|
||
|
|
||
|
switch (nRet)
|
||
|
{
|
||
|
case IDOK: hres = NOERROR; break;
|
||
|
case IDCANCEL: hres = E_ABORT; break;
|
||
|
default: hres = E_OUTOFMEMORY; break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
Atom_Delete(pagedata.atomPath);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
return hres;
|
||
|
}
|