1309 lines
32 KiB
C
1309 lines
32 KiB
C
/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
|
|
**
|
|
** edit.c
|
|
** Remote Access Common Dialog APIs
|
|
** List editor, string editor dialog routines
|
|
**
|
|
** 08/28/95 Steve Cobb
|
|
*/
|
|
|
|
#include "rasdlgp.h"
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** Local datatypes (alphabetically)
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* List editor dialog argument block.
|
|
*/
|
|
#define LEARGS struct tagLEARGS
|
|
LEARGS
|
|
{
|
|
/* Caller's arguments to the stub API.
|
|
*/
|
|
DTLLIST* pList;
|
|
BOOL* pfCheck;
|
|
DWORD dwMaxItemLen;
|
|
TCHAR* pszTitle;
|
|
TCHAR* pszItemLabel;
|
|
TCHAR* pszListLabel;
|
|
TCHAR* pszCheckLabel;
|
|
TCHAR* pszDefaultItem;
|
|
INT iSelInitial;
|
|
DWORD* pdwHelp;
|
|
DWORD dwfFlags;
|
|
PDESTROYNODE pDestroyId;
|
|
};
|
|
|
|
|
|
/* List editor dialog context block.
|
|
*/
|
|
#define LEINFO struct tagLEINFO
|
|
LEINFO
|
|
{
|
|
/* Caller's arguments to the dialog.
|
|
*/
|
|
LEARGS* pArgs;
|
|
|
|
/* Handle of this dialog and some of it's controls.
|
|
*/
|
|
HWND hwndDlg;
|
|
HWND hwndStItem;
|
|
HWND hwndStList;
|
|
HWND hwndPbAdd;
|
|
HWND hwndPbReplace;
|
|
HWND hwndPbUp;
|
|
HWND hwndPbDown;
|
|
HWND hwndPbDelete;
|
|
HWND hwndPbOk;
|
|
HWND hwndEb;
|
|
HWND hwndLb;
|
|
HWND hwndCb;
|
|
|
|
/* Convenient alternatives to (pInfo->pArgs->dwFlags & LEDFLAG_Sorted) and
|
|
** (pInfo->pArgs->dwFlags & LEDFLAG_NoDeleteLastItem).
|
|
*/
|
|
BOOL fSorted;
|
|
BOOL fNoDeleteLast;
|
|
|
|
/* Button bitmaps.
|
|
*/
|
|
HBITMAP hbmUp;
|
|
HBITMAP hbmDown;
|
|
|
|
/* List of empty nodes whose node-IDs should be 'pDestroyId'ed if user
|
|
** presses OK.
|
|
*/
|
|
DTLLIST* pListDeletes;
|
|
};
|
|
|
|
|
|
/* String Editor dialog arument block.
|
|
*/
|
|
#define ZEARGS struct tagZEARGS
|
|
ZEARGS
|
|
{
|
|
/* Caller's aruments to the stub API.
|
|
*/
|
|
TCHAR* pszIn;
|
|
DWORD dwSidTitle;
|
|
DWORD dwSidLabel;
|
|
DWORD cbMax;
|
|
DWORD dwHelpId;
|
|
TCHAR** ppszOut;
|
|
};
|
|
|
|
|
|
/* String Editor dialog context block.
|
|
*/
|
|
#define ZEINFO struct tagZEINFO
|
|
ZEINFO
|
|
{
|
|
/* Caller's arguments to the stub API.
|
|
*/
|
|
ZEARGS* pArgs;
|
|
|
|
/* Dialog and control handles.
|
|
*/
|
|
HWND hwndDlg;
|
|
HWND hwndEb;
|
|
};
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** Local prototypes (alphabetically)
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
INT_PTR CALLBACK
|
|
LeDlgProc(
|
|
IN HWND hwnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wparam,
|
|
IN LPARAM lparam );
|
|
|
|
VOID
|
|
LeAdd(
|
|
IN LEINFO* pInfo );
|
|
|
|
BOOL
|
|
LeCommand(
|
|
IN LEINFO* pInfo,
|
|
IN WORD wNotification,
|
|
IN WORD wId,
|
|
IN HWND hwndCtrl );
|
|
|
|
VOID
|
|
LeDelete(
|
|
IN LEINFO* pInfo );
|
|
|
|
VOID
|
|
LeDown(
|
|
IN LEINFO* pInfo );
|
|
|
|
VOID
|
|
LeEnableUpAndDownButtons(
|
|
IN LEINFO* pInfo );
|
|
|
|
VOID
|
|
LeExitNoMemory(
|
|
IN LEINFO* pInfo );
|
|
|
|
BOOL
|
|
LeInit(
|
|
IN HWND hwndDlg,
|
|
IN LEARGS* pArgs );
|
|
|
|
VOID
|
|
LeItemTextFromListSelection(
|
|
IN LEINFO* pInfo );
|
|
|
|
VOID
|
|
LeReplace(
|
|
IN LEINFO* pInfo );
|
|
|
|
BOOL
|
|
LeSaveSettings(
|
|
IN LEINFO* pInfo );
|
|
|
|
VOID
|
|
LeTerm(
|
|
IN HWND hwndDlg );
|
|
|
|
VOID
|
|
LeUp(
|
|
IN LEINFO* pInfo );
|
|
|
|
INT_PTR CALLBACK
|
|
ZeDlgProc(
|
|
IN HWND hwnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wparam,
|
|
IN LPARAM lparam );
|
|
|
|
BOOL
|
|
ZeCommand(
|
|
IN ZEINFO* pInfo,
|
|
IN WORD wNotification,
|
|
IN WORD wId,
|
|
IN HWND hwndCtrl );
|
|
|
|
BOOL
|
|
ZeInit(
|
|
IN HWND hwndDlg,
|
|
IN ZEARGS* pArgs );
|
|
|
|
VOID
|
|
ZeTerm(
|
|
IN HWND hwndDlg );
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** List Editor dialog entry point
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
BOOL
|
|
ListEditorDlg(
|
|
IN HWND hwndOwner,
|
|
IN OUT DTLLIST* pList,
|
|
IN OUT BOOL* pfCheck,
|
|
IN DWORD dwMaxItemLen,
|
|
IN TCHAR* pszTitle,
|
|
IN TCHAR* pszItemLabel,
|
|
IN TCHAR* pszListLabel,
|
|
IN TCHAR* pszCheckLabel,
|
|
IN TCHAR* pszDefaultItem,
|
|
IN INT iSelInitial,
|
|
IN DWORD* pdwHelp,
|
|
IN DWORD dwfFlags,
|
|
IN PDESTROYNODE pDestroyId )
|
|
|
|
/* Pops-up the List Editor dialog.
|
|
**
|
|
** 'HwndOwner' is the owner of the dialog. 'PList' is, on entry, the Psz
|
|
** list to display initially, and on successful exit, the result list.
|
|
** 'PfCheck' is the state of the check box or NULL for the non-checkbox
|
|
** style. 'DwMaxItemLen' is the maximum length of an individual list
|
|
** item. 'PszTitle' is the dialog title. 'PszItemLabel' is the label
|
|
** (and hotkey) associated with the item box. 'PszListLabel' is the label
|
|
** (and hotkey) associated with the list. 'PszCheckLabel' is the label
|
|
** (and hotkey) associated with the checkbox. 'PszDefaultItem' is the
|
|
** default contents of the edit box or for the selected list text.
|
|
** 'ISelInitial' is the item the list to initally select. 'PdwHelp' is
|
|
** the array of CID_LE_* help contexts to use. 'DwfFlags' indicates
|
|
** LEDFLAG_* behavior options. 'PDestroyId' is the routine to use to
|
|
** destroy node IDs when they are deleted or NULL if none.
|
|
**
|
|
** Returns true if user pressed OK and succeeded, false if he pressed
|
|
** Cancel or encountered an error.
|
|
*/
|
|
{
|
|
int nStatus;
|
|
LEARGS args;
|
|
|
|
TRACE("ListEditorDlg");
|
|
|
|
args.pList = pList;
|
|
args.pfCheck = pfCheck;
|
|
args.dwMaxItemLen = dwMaxItemLen;
|
|
args.pszTitle = pszTitle;
|
|
args.pszItemLabel = pszItemLabel;
|
|
args.pszListLabel = pszListLabel;
|
|
args.pszCheckLabel = pszCheckLabel;
|
|
args.pszDefaultItem = pszDefaultItem;
|
|
args.iSelInitial = iSelInitial;
|
|
args.pdwHelp = pdwHelp;
|
|
args.dwfFlags = dwfFlags;
|
|
args.pDestroyId = pDestroyId;
|
|
|
|
nStatus =
|
|
(BOOL )DialogBoxParam(
|
|
g_hinstDll,
|
|
(pfCheck)
|
|
? MAKEINTRESOURCE( DID_LE_ListEditor2 )
|
|
: ((dwfFlags & LEDFLAG_Sorted)
|
|
? MAKEINTRESOURCE( DID_LE_ListEditor3 )
|
|
: MAKEINTRESOURCE( DID_LE_ListEditor )),
|
|
hwndOwner,
|
|
LeDlgProc,
|
|
(LPARAM )&args );
|
|
|
|
if (nStatus == -1)
|
|
{
|
|
ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
|
|
nStatus = FALSE;
|
|
}
|
|
|
|
return (BOOL )nStatus;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** List Editor dialog routines
|
|
** Listed alphabetically following dialog proc
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
INT_PTR CALLBACK
|
|
LeDlgProc(
|
|
IN HWND hwnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wparam,
|
|
IN LPARAM lparam )
|
|
|
|
/* DialogProc callback for the List Editor dialog. Parameters and return
|
|
** value are as described for standard windows 'DialogProc's.
|
|
*/
|
|
{
|
|
#if 0
|
|
TRACE4("LeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
|
|
(DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
|
|
#endif
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return LeInit( hwnd, (LEARGS* )lparam );
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
|
|
ASSERT(pInfo);
|
|
|
|
ContextHelp( pInfo->pArgs->pdwHelp, hwnd, unMsg, wparam, lparam );
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
|
|
ASSERT(pInfo);
|
|
|
|
return LeCommand(
|
|
pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
LeTerm( hwnd );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
VOID
|
|
LeAdd(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Add button click handler. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
TCHAR* psz;
|
|
|
|
psz = GetText( pInfo->hwndEb );
|
|
if (!psz)
|
|
{
|
|
LeExitNoMemory( pInfo );
|
|
return;
|
|
}
|
|
|
|
if (pInfo->pArgs->dwfFlags & LEDFLAG_Unique)
|
|
{
|
|
if (ListBox_IndexFromString( pInfo->hwndLb, psz ) >= 0)
|
|
{
|
|
MSGARGS msgargs;
|
|
|
|
ZeroMemory( &msgargs, sizeof(msgargs) );
|
|
msgargs.apszArgs[ 0 ] = psz;
|
|
MsgDlg( pInfo->hwndDlg, SID_NotUnique, &msgargs );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
SetFocus( pInfo->hwndEb );
|
|
Free( psz );
|
|
return;
|
|
}
|
|
}
|
|
|
|
ListBox_SetCurSel( pInfo->hwndLb,
|
|
ListBox_AddItem( pInfo->hwndLb, psz, 0 ) );
|
|
Free( psz );
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
EnableWindow( pInfo->hwndPbReplace, FALSE );
|
|
|
|
if (!pInfo->fNoDeleteLast || ListBox_GetCount( pInfo->hwndLb ) > 1)
|
|
EnableWindow( pInfo->hwndPbDelete, TRUE );
|
|
|
|
SetWindowText( pInfo->hwndEb, TEXT("") );
|
|
SetFocus( pInfo->hwndEb );
|
|
}
|
|
|
|
|
|
BOOL
|
|
LeCommand(
|
|
IN LEINFO* pInfo,
|
|
IN WORD wNotification,
|
|
IN WORD wId,
|
|
IN HWND hwndCtrl )
|
|
|
|
/* Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
|
|
** is the notification code of the command. 'wId' is the control/menu
|
|
** identifier of the command. 'HwndCtrl' is the control window handle of
|
|
** the command.
|
|
**
|
|
** Returns true if processed message, false otherwise.
|
|
*/
|
|
{
|
|
TRACE2("LeCommand(n=%d,i=%d)",
|
|
(DWORD)wNotification,(DWORD)wId);
|
|
|
|
switch (wId)
|
|
{
|
|
case CID_LE_PB_Add:
|
|
LeAdd( pInfo );
|
|
return TRUE;
|
|
|
|
case CID_LE_PB_Replace:
|
|
LeReplace( pInfo );
|
|
return TRUE;
|
|
|
|
case CID_LE_PB_Up:
|
|
LeUp( pInfo );
|
|
return TRUE;
|
|
|
|
case CID_LE_PB_Down:
|
|
LeDown( pInfo );
|
|
return TRUE;
|
|
|
|
case CID_LE_PB_Delete:
|
|
LeDelete( pInfo );
|
|
return TRUE;
|
|
|
|
case CID_LE_EB_Item:
|
|
{
|
|
if (wNotification == EN_SETFOCUS || wNotification == EN_UPDATE)
|
|
{
|
|
TCHAR* psz = GetText( pInfo->hwndEb );
|
|
|
|
if (psz && lstrlen( psz ) > 0 && !IsAllWhite( psz ))
|
|
{
|
|
EnableWindow( pInfo->hwndPbAdd, TRUE );
|
|
EnableWindow( pInfo->hwndPbReplace, TRUE );
|
|
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbAdd );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( pInfo->hwndPbAdd, FALSE );
|
|
EnableWindow( pInfo->hwndPbReplace, FALSE );
|
|
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbOk );
|
|
}
|
|
|
|
Free0( psz );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case CID_LE_LB_List:
|
|
{
|
|
if (wNotification == LBN_SELCHANGE)
|
|
{
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
if (ListBox_GetCurSel( pInfo->hwndLb ) >= 0)
|
|
LeItemTextFromListSelection( pInfo );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case CID_LE_CB_Promote:
|
|
{
|
|
if (wNotification == BN_SETFOCUS)
|
|
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbOk );
|
|
return TRUE;
|
|
}
|
|
|
|
case IDOK:
|
|
EndDialog( pInfo->hwndDlg, LeSaveSettings( pInfo ) );
|
|
return TRUE;
|
|
|
|
|
|
case IDCANCEL:
|
|
{
|
|
DTLLIST* pList;
|
|
DTLNODE* pNode;
|
|
|
|
TRACE("Cancel pressed");
|
|
EndDialog( pInfo->hwndDlg, FALSE );
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
VOID
|
|
LeDelete(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Delete button click handler. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
INT i;
|
|
INT c;
|
|
|
|
i = ListBox_GetCurSel( pInfo->hwndLb );
|
|
if (pInfo->pArgs->pDestroyId)
|
|
{
|
|
INT_PTR lId = ListBox_GetItemData( pInfo->hwndLb, i );
|
|
if (lId != 0)
|
|
{
|
|
DTLNODE* pNode;
|
|
|
|
pNode = DtlCreateNode( NULL, (DWORD)lId );
|
|
if (!pNode)
|
|
{
|
|
ErrorDlg( pInfo->hwndDlg, SID_OP_DisplayData,
|
|
ERROR_NOT_ENOUGH_MEMORY, NULL );
|
|
EndDialog( pInfo->hwndDlg, FALSE );
|
|
return;
|
|
}
|
|
|
|
DtlAddNodeFirst( pInfo->pListDeletes, pNode );
|
|
}
|
|
}
|
|
ListBox_DeleteString( pInfo->hwndLb, i );
|
|
c = ListBox_GetCount( pInfo->hwndLb );
|
|
|
|
if (c == 0)
|
|
{
|
|
EnableWindow( pInfo->hwndPbReplace, FALSE );
|
|
EnableWindow( pInfo->hwndPbDelete, FALSE );
|
|
SetFocus( pInfo->hwndEb );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
}
|
|
else
|
|
{
|
|
if (c == 1 && pInfo->fNoDeleteLast)
|
|
EnableWindow( pInfo->hwndPbDelete, FALSE );
|
|
|
|
if (i >= c)
|
|
i = c - 1;
|
|
|
|
ListBox_SetCurSel( pInfo->hwndLb, i );
|
|
}
|
|
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
|
|
if (IsWindowEnabled( GetFocus() ))
|
|
{
|
|
SetFocus( pInfo->hwndEb );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
LeDown(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Down button click handler. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
TCHAR* psz;
|
|
INT i;
|
|
INT_PTR lId;
|
|
|
|
ASSERT(!pInfo->fSorted);
|
|
|
|
i = ListBox_GetCurSel( pInfo->hwndLb );
|
|
psz = ListBox_GetPsz( pInfo->hwndLb, i );
|
|
if (!psz)
|
|
{
|
|
LeExitNoMemory( pInfo );
|
|
return;
|
|
}
|
|
|
|
lId = ListBox_GetItemData( pInfo->hwndLb, i );
|
|
ListBox_InsertString( pInfo->hwndLb, i + 2, psz );
|
|
ListBox_SetItemData( pInfo->hwndLb, i + 2, lId );
|
|
Free( psz );
|
|
ListBox_DeleteString( pInfo->hwndLb, i );
|
|
ListBox_SetCurSel( pInfo->hwndLb, i + 1 );
|
|
|
|
if (i == ListBox_GetCount( pInfo->hwndLb ))
|
|
{
|
|
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbUp );
|
|
SetFocus( pInfo->hwndPbUp );
|
|
}
|
|
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
}
|
|
|
|
|
|
VOID
|
|
LeEnableUpAndDownButtons(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Determine if the Up and Down operations make sense and enable/disable
|
|
** the buttons as appropriate. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
INT i;
|
|
INT c;
|
|
|
|
if (pInfo->fSorted)
|
|
return;
|
|
|
|
i = ListBox_GetCurSel( pInfo->hwndLb );
|
|
c = ListBox_GetCount( pInfo->hwndLb );
|
|
|
|
EnableWindow( pInfo->hwndPbDown, (i < c - 1 ) );
|
|
EnableWindow( pInfo->hwndPbUp, (i > 0) );
|
|
}
|
|
|
|
|
|
VOID
|
|
LeExitNoMemory(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* End the dialog reporting a memory. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
ErrorDlg( pInfo->hwndDlg,
|
|
SID_OP_DisplayData, ERROR_NOT_ENOUGH_MEMORY, NULL );
|
|
EndDialog( pInfo->hwndDlg, FALSE );
|
|
}
|
|
|
|
|
|
BOOL
|
|
LeInit(
|
|
IN HWND hwndDlg,
|
|
IN LEARGS* pArgs )
|
|
|
|
/* Called on WM_INITDIALOG. 'HwndDlg' is the handle of the phonebook
|
|
** dialog window. 'PArgs' is caller's arguments as passed to the stub
|
|
** API.
|
|
**
|
|
** Return false if focus was set, true otherwise, i.e. as defined for
|
|
** WM_INITDIALOG.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
LEINFO* pInfo;
|
|
DTLNODE* pNode;
|
|
INT c;
|
|
|
|
TRACE("LeInit");
|
|
|
|
/* Allocate the dialog context block. Initialize minimally for proper
|
|
** cleanup, then attach to the dialog window.
|
|
*/
|
|
{
|
|
pInfo = Malloc( sizeof(*pInfo) );
|
|
if (!pInfo)
|
|
{
|
|
ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
|
|
EndDialog( hwndDlg, FALSE );
|
|
return TRUE;
|
|
}
|
|
|
|
ZeroMemory( pInfo, sizeof(*pInfo) );
|
|
pInfo->pArgs = pArgs;
|
|
pInfo->hwndDlg = hwndDlg;
|
|
|
|
SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo );
|
|
TRACE("Context set");
|
|
}
|
|
|
|
/* Set up convenient shortcuts.
|
|
*/
|
|
if (pArgs->dwfFlags & LEDFLAG_Sorted)
|
|
pInfo->fSorted = TRUE;
|
|
if (pArgs->dwfFlags & LEDFLAG_NoDeleteLastItem)
|
|
pInfo->fNoDeleteLast = TRUE;
|
|
|
|
pInfo->hwndStItem = GetDlgItem( hwndDlg, CID_LE_ST_Item );
|
|
ASSERT(pInfo->hwndStItem);
|
|
pInfo->hwndStList = GetDlgItem( hwndDlg, CID_LE_ST_List );
|
|
ASSERT(pInfo->hwndStList);
|
|
pInfo->hwndPbAdd = GetDlgItem( hwndDlg, CID_LE_PB_Add );
|
|
ASSERT(pInfo->hwndPbAdd);
|
|
pInfo->hwndPbReplace = GetDlgItem( hwndDlg, CID_LE_PB_Replace );
|
|
ASSERT(pInfo->hwndPbReplace);
|
|
pInfo->hwndPbDelete = GetDlgItem( hwndDlg, CID_LE_PB_Delete );
|
|
ASSERT(pInfo->hwndPbDelete);
|
|
pInfo->hwndPbOk = GetDlgItem( hwndDlg, IDOK );
|
|
ASSERT(pInfo->hwndPbOk);
|
|
pInfo->hwndEb = GetDlgItem( hwndDlg, CID_LE_EB_Item );
|
|
ASSERT(pInfo->hwndEb);
|
|
pInfo->hwndLb = GetDlgItem( hwndDlg, CID_LE_LB_List );
|
|
ASSERT(pInfo->hwndLb);
|
|
|
|
if (pArgs->pDestroyId)
|
|
{
|
|
/* Create the empty list of deletions.
|
|
*/
|
|
pInfo->pListDeletes = DtlCreateList( 0L );
|
|
if (!pInfo->pListDeletes)
|
|
{
|
|
ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
|
|
EndDialog( hwndDlg, FALSE );
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (!pInfo->fSorted)
|
|
{
|
|
pInfo->hwndPbUp = GetDlgItem( hwndDlg, CID_LE_PB_Up );
|
|
ASSERT(pInfo->hwndPbUp);
|
|
pInfo->hwndPbDown = GetDlgItem( hwndDlg, CID_LE_PB_Down );
|
|
ASSERT(pInfo->hwndPbDown);
|
|
|
|
/* Draw the graphical up and down arrow indicators.
|
|
*/
|
|
pInfo->hbmUp = Button_CreateBitmap(
|
|
pInfo->hwndPbUp, BMS_UpArrowOnRight );
|
|
if (pInfo->hbmUp)
|
|
{
|
|
SendMessage( pInfo->hwndPbUp, BM_SETIMAGE, 0,
|
|
(LPARAM )pInfo->hbmUp );
|
|
}
|
|
|
|
pInfo->hbmDown = Button_CreateBitmap(
|
|
pInfo->hwndPbDown, BMS_DownArrowOnRight );
|
|
if (pInfo->hbmDown)
|
|
{
|
|
SendMessage( pInfo->hwndPbDown, BM_SETIMAGE, 0,
|
|
(LPARAM )pInfo->hbmDown );
|
|
}
|
|
}
|
|
|
|
if (pArgs->pfCheck)
|
|
{
|
|
pInfo->hwndCb = GetDlgItem( hwndDlg, CID_LE_CB_Promote );
|
|
ASSERT(pInfo->hwndCb);
|
|
SetWindowText( pInfo->hwndCb, pArgs->pszCheckLabel );
|
|
Button_SetCheck( pInfo->hwndCb, *pArgs->pfCheck );
|
|
}
|
|
|
|
Edit_LimitText( pInfo->hwndEb, pArgs->dwMaxItemLen );
|
|
|
|
/* Set caller-defined dialog title and labels.
|
|
*/
|
|
SetWindowText( pInfo->hwndDlg, pArgs->pszTitle );
|
|
SetWindowText( pInfo->hwndStItem, pArgs->pszItemLabel );
|
|
SetWindowText( pInfo->hwndStList, pArgs->pszListLabel );
|
|
|
|
/* Fill the listbox.
|
|
*/
|
|
for (pNode = DtlGetFirstNode( pArgs->pList );
|
|
pNode;
|
|
pNode = DtlGetNextNode( pNode ))
|
|
{
|
|
TCHAR* psz = (TCHAR* )DtlGetData( pNode );
|
|
ASSERT(psz);
|
|
|
|
ListBox_AddItem( pInfo->hwndLb, psz, (VOID* )UlongToPtr(DtlGetNodeId( pNode ) ));
|
|
}
|
|
|
|
c = ListBox_GetCount( pInfo->hwndLb );
|
|
if (c > 0)
|
|
{
|
|
/* Select item selected by caller.
|
|
*/
|
|
ListBox_SetCurSelNotify( pInfo->hwndLb, pArgs->iSelInitial );
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
|
|
if (c == 1 && pInfo->fNoDeleteLast)
|
|
EnableWindow( pInfo->hwndPbDelete, FALSE );
|
|
}
|
|
else
|
|
{
|
|
/* Empty list.
|
|
*/
|
|
if (!pInfo->fSorted)
|
|
{
|
|
EnableWindow( pInfo->hwndPbUp, FALSE );
|
|
EnableWindow( pInfo->hwndPbDown, FALSE );
|
|
}
|
|
EnableWindow( pInfo->hwndPbDelete, FALSE );
|
|
}
|
|
|
|
|
|
/* Set default edit box contents, if any.
|
|
*/
|
|
if (pArgs->pszDefaultItem)
|
|
{
|
|
SetWindowText( pInfo->hwndEb, pArgs->pszDefaultItem );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( pInfo->hwndPbAdd, FALSE );
|
|
EnableWindow( pInfo->hwndPbReplace, FALSE );
|
|
}
|
|
|
|
/* Center dialog on the owner window.
|
|
*/
|
|
CenterWindow( hwndDlg, GetParent( hwndDlg ) );
|
|
|
|
/* Add context help button to title bar. Dlgedit.exe doesn't currently
|
|
** support this at resource edit time. When that's fixed set
|
|
** DS_CONTEXTHELP there and remove this call.
|
|
*/
|
|
AddContextHelpButton( hwndDlg );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
LeItemTextFromListSelection(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Copies the currently selected item in the list to the edit box.
|
|
** 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
TCHAR* psz;
|
|
INT iSel;
|
|
|
|
iSel = ListBox_GetCurSel( pInfo->hwndLb );
|
|
if (iSel >= 0)
|
|
{
|
|
psz = ListBox_GetPsz( pInfo->hwndLb, iSel );
|
|
if (psz)
|
|
{
|
|
SetWindowText( pInfo->hwndEb, psz );
|
|
Free( psz );
|
|
return;
|
|
}
|
|
}
|
|
|
|
SetWindowText( pInfo->hwndEb, TEXT("") );
|
|
}
|
|
|
|
|
|
VOID
|
|
LeReplace(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Replace button click handler. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
TCHAR* psz;
|
|
INT i;
|
|
INT_PTR lId;
|
|
|
|
psz = GetText( pInfo->hwndEb );
|
|
if (!psz)
|
|
{
|
|
LeExitNoMemory( pInfo );
|
|
return;
|
|
}
|
|
|
|
if (pInfo->pArgs->dwfFlags & LEDFLAG_Unique)
|
|
{
|
|
if (ListBox_IndexFromString( pInfo->hwndLb, psz ) >= 0)
|
|
{
|
|
MSGARGS msgargs;
|
|
|
|
ZeroMemory( &msgargs, sizeof(msgargs) );
|
|
msgargs.apszArgs[ 0 ] = psz;
|
|
MsgDlg( pInfo->hwndDlg, SID_NotUnique, &msgargs );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
SetFocus( pInfo->hwndEb );
|
|
Free( psz );
|
|
return;
|
|
}
|
|
}
|
|
|
|
i = ListBox_GetCurSel( pInfo->hwndLb );
|
|
lId = ListBox_GetItemData( pInfo->hwndLb, i );
|
|
ListBox_DeleteString( pInfo->hwndLb, i );
|
|
|
|
if (pInfo->fSorted)
|
|
{
|
|
i = ListBox_AddItem( pInfo->hwndLb, psz, (VOID* )lId );
|
|
}
|
|
else
|
|
{
|
|
ListBox_InsertString( pInfo->hwndLb, i, psz );
|
|
ListBox_SetItemData( pInfo->hwndLb, i, lId );
|
|
}
|
|
|
|
Free( psz );
|
|
ListBox_SetCurSel( pInfo->hwndLb, i );
|
|
SetFocus( pInfo->hwndEb );
|
|
SetWindowText( pInfo->hwndEb, TEXT("") );
|
|
}
|
|
|
|
|
|
BOOL
|
|
LeSaveSettings(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Saves dialog settings in the stub API caller's list. 'PInfo' is the
|
|
** dialog context.
|
|
**
|
|
** Returns true if successful, false if does not validate.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
DTLNODE* pNode;
|
|
DTLLIST* pList;
|
|
DTLLIST* pListNew;
|
|
TCHAR* psz;
|
|
INT_PTR lId;
|
|
INT c;
|
|
INT i;
|
|
|
|
/* Make new list from list box contents.
|
|
*/
|
|
do
|
|
{
|
|
pListNew = DtlCreateList( 0L );
|
|
if (!pListNew)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwErr = 0;
|
|
c = ListBox_GetCount( pInfo->hwndLb );
|
|
|
|
for (i = 0; i < c; ++i)
|
|
{
|
|
psz = ListBox_GetPsz( pInfo->hwndLb, i );
|
|
if (!psz)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
lId = ListBox_GetItemData( pInfo->hwndLb, i );
|
|
ASSERT(lId>=0);
|
|
|
|
pNode = DtlCreateNode( psz, (DWORD)lId );
|
|
if (!pNode)
|
|
{
|
|
Free( psz );
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
DtlAddNodeLast( pListNew, pNode );
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
if (dwErr != 0)
|
|
{
|
|
ErrorDlg( pInfo->hwndDlg, SID_OP_DisplayData, dwErr, NULL );
|
|
DtlDestroyList( pListNew, DestroyPszNode );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Free all data in the old list.
|
|
*/
|
|
while (pNode = DtlGetFirstNode( pInfo->pArgs->pList ))
|
|
{
|
|
Free( (TCHAR* )DtlGetData( pNode ) );
|
|
DtlDeleteNode( pInfo->pArgs->pList, pNode );
|
|
}
|
|
|
|
/* Free the node-IDs in the list of deletions.
|
|
*/
|
|
if (pInfo->pListDeletes)
|
|
{
|
|
while (pNode = DtlGetFirstNode( pInfo->pListDeletes ))
|
|
{
|
|
pInfo->pArgs->pDestroyId( (DTLNODE* )UlongToPtr(DtlGetNodeId( pNode ) ));
|
|
DtlDeleteNode( pInfo->pListDeletes, pNode );
|
|
}
|
|
}
|
|
|
|
/* Move the new list onto caller's list.
|
|
*/
|
|
while (pNode = DtlGetFirstNode( pListNew ))
|
|
{
|
|
DtlRemoveNode( pListNew, pNode );
|
|
DtlAddNodeLast( pInfo->pArgs->pList, pNode );
|
|
}
|
|
DtlDestroyList( pListNew, DestroyPszNode );
|
|
|
|
/* Tell caller what the checkbox setting is.
|
|
*/
|
|
if (pInfo->pArgs->pfCheck)
|
|
*pInfo->pArgs->pfCheck = Button_GetCheck( pInfo->hwndCb );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
LeTerm(
|
|
IN HWND hwndDlg )
|
|
|
|
/* Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
|
|
*/
|
|
{
|
|
LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
|
|
|
|
TRACE("LeTerm");
|
|
|
|
if (pInfo)
|
|
{
|
|
if (pInfo->hbmUp)
|
|
DeleteObject( pInfo->hbmUp );
|
|
if (pInfo->hbmDown)
|
|
DeleteObject( pInfo->hbmDown );
|
|
|
|
DtlDestroyList( pInfo->pListDeletes, NULL );
|
|
Free( pInfo );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
LeUp(
|
|
IN LEINFO* pInfo )
|
|
|
|
/* Up button click handler. 'PInfo' is the dialog context.
|
|
*/
|
|
{
|
|
TCHAR* psz;
|
|
INT i;
|
|
LONG_PTR lId;
|
|
|
|
ASSERT(!pInfo->fSorted);
|
|
|
|
i = ListBox_GetCurSel( pInfo->hwndLb );
|
|
psz = ListBox_GetPsz( pInfo->hwndLb, i );
|
|
if (!psz)
|
|
{
|
|
LeExitNoMemory( pInfo );
|
|
return;
|
|
}
|
|
|
|
ListBox_InsertString( pInfo->hwndLb, i - 1, psz );
|
|
Free( psz );
|
|
lId = ListBox_GetItemData( pInfo->hwndLb, i + 1 );
|
|
ListBox_DeleteString( pInfo->hwndLb, i + 1 );
|
|
ListBox_SetItemData( pInfo->hwndLb, i - 1, lId );
|
|
ListBox_SetCurSel( pInfo->hwndLb, i - 1 );
|
|
|
|
if (i == 1)
|
|
{
|
|
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbDown );
|
|
SetFocus( pInfo->hwndPbDown );
|
|
}
|
|
|
|
LeEnableUpAndDownButtons( pInfo );
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** String Editor dialog entry point
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
BOOL
|
|
StringEditorDlg(
|
|
IN HWND hwndOwner,
|
|
IN TCHAR* pszIn,
|
|
IN DWORD dwSidTitle,
|
|
IN DWORD dwSidLabel,
|
|
IN DWORD cbMax,
|
|
IN DWORD dwHelpId,
|
|
IN OUT TCHAR** ppszOut )
|
|
|
|
/* Pops-up the String Editor dialog. 'PszIn' is the initial setting of
|
|
** the edit box or NULL for blank. 'DwSidTitle' and 'dwSidLabel' are the
|
|
** string resource IDs of the dialog title and edit box label. 'CbMax' is
|
|
** the maximum length of the to allow or 0 for no limit. 'DwHelpId' is
|
|
** the HID_* constant to associate with the label and edit field or -1 if
|
|
** none.
|
|
**
|
|
** Returns true if user pressed OK and succeeded, false if he pressed
|
|
** Cancel or encountered an error. If true, '*ppszNumber' is a heap block
|
|
** with the edited result. It is caller's responsibility to Free the
|
|
** returned block.
|
|
*/
|
|
{
|
|
int nStatus;
|
|
ZEARGS args;
|
|
|
|
TRACE("StringEditorDlg");
|
|
|
|
args.pszIn = pszIn;
|
|
args.dwSidTitle = dwSidTitle;
|
|
args.dwSidLabel = dwSidLabel;
|
|
args.cbMax = cbMax;
|
|
args.dwHelpId = dwHelpId;
|
|
args.ppszOut = ppszOut;
|
|
|
|
nStatus =
|
|
(BOOL )DialogBoxParam(
|
|
g_hinstDll,
|
|
MAKEINTRESOURCE( DID_ZE_StringEditor ),
|
|
hwndOwner,
|
|
ZeDlgProc,
|
|
(LPARAM )&args );
|
|
|
|
if (nStatus == -1)
|
|
{
|
|
ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
|
|
nStatus = FALSE;
|
|
}
|
|
|
|
return (BOOL )nStatus;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** String Editor dialog routines
|
|
** Listed alphabetically following dialog proc
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
INT_PTR CALLBACK
|
|
ZeDlgProc(
|
|
IN HWND hwnd,
|
|
IN UINT unMsg,
|
|
IN WPARAM wparam,
|
|
IN LPARAM lparam )
|
|
|
|
/* DialogProc callback for the Edit Phone Number dialog. Parameters and
|
|
** return value are as described for standard windows 'DialogProc's.
|
|
FastRight:right */
|
|
{
|
|
#if 0
|
|
TRACE4("ZeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
|
|
(DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
|
|
#endif
|
|
|
|
switch (unMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return ZeInit( hwnd, (ZEARGS* )lparam );
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
ZEINFO* pInfo;
|
|
|
|
pInfo = (ZEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
|
|
if (pInfo && pInfo->pArgs->dwHelpId != (DWORD )-1)
|
|
{
|
|
DWORD adwZeHelp[ (2 + 1) * 2 ];
|
|
|
|
ZeroMemory( adwZeHelp, sizeof(adwZeHelp) );
|
|
adwZeHelp[ 0 ] = CID_ZE_ST_String;
|
|
adwZeHelp[ 2 ] = CID_ZE_EB_String;
|
|
adwZeHelp[ 1 ] = adwZeHelp[ 3 ] = pInfo->pArgs->dwHelpId;
|
|
|
|
ContextHelp( adwZeHelp, hwnd, unMsg, wparam, lparam );
|
|
break;
|
|
}
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
ZEINFO* pInfo = (ZEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
|
|
ASSERT(pInfo);
|
|
|
|
return ZeCommand(
|
|
pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
ZeTerm( hwnd );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ZeCommand(
|
|
IN ZEINFO* pInfo,
|
|
IN WORD wNotification,
|
|
IN WORD wId,
|
|
IN HWND hwndCtrl )
|
|
|
|
/* Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
|
|
** is the notification code of the command. 'wId' is the control/menu
|
|
** identifier of the command. 'HwndCtrl' is the control window handle of
|
|
** the command.
|
|
**
|
|
** Returns true if processed message, false otherwise.
|
|
*/
|
|
{
|
|
TRACE2("ZeCommand(n=%d,i=%d)",
|
|
(DWORD)wNotification,(DWORD)wId);
|
|
|
|
switch (wId)
|
|
{
|
|
case IDOK:
|
|
{
|
|
TRACE("OK pressed");
|
|
*pInfo->pArgs->ppszOut = GetText( pInfo->hwndEb );
|
|
EndDialog( pInfo->hwndDlg, (*pInfo->pArgs->ppszOut != NULL) );
|
|
return TRUE;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
{
|
|
TRACE("Cancel pressed");
|
|
EndDialog( pInfo->hwndDlg, FALSE );
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ZeInit(
|
|
IN HWND hwndDlg,
|
|
IN ZEARGS* pArgs )
|
|
|
|
/* Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
|
|
** 'PArgs' is caller's arguments as passed to the stub API.
|
|
**
|
|
** Return false if focus was set, true otherwise, i.e. as defined for
|
|
** WM_INITDIALOG.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
TCHAR* psz;
|
|
ZEINFO* pInfo;
|
|
|
|
TRACE("ZeInit");
|
|
|
|
/* Allocate the dialog context block. Initialize minimally for proper
|
|
** cleanup, then attach to the dialog window.
|
|
*/
|
|
{
|
|
pInfo = Malloc( sizeof(*pInfo) );
|
|
if (!pInfo)
|
|
{
|
|
ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
|
|
EndDialog( hwndDlg, FALSE );
|
|
return TRUE;
|
|
}
|
|
|
|
ZeroMemory( pInfo, sizeof(*pInfo) );
|
|
pInfo->pArgs = pArgs;
|
|
pInfo->hwndDlg = hwndDlg;
|
|
|
|
SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)pInfo );
|
|
TRACE("Context set");
|
|
}
|
|
|
|
pInfo->hwndEb = GetDlgItem( hwndDlg, CID_ZE_EB_String );
|
|
ASSERT(pInfo->hwndEb);
|
|
|
|
if (pArgs->cbMax > 0)
|
|
Edit_LimitText( pInfo->hwndEb, pArgs->cbMax );
|
|
|
|
psz = PszFromId( g_hinstDll, pArgs->dwSidTitle );
|
|
if (psz)
|
|
{
|
|
SetWindowText( hwndDlg, psz );
|
|
Free( psz );
|
|
}
|
|
|
|
psz = PszFromId( g_hinstDll, pArgs->dwSidLabel );
|
|
if (psz)
|
|
{
|
|
HWND hwndSt = GetDlgItem( hwndDlg, CID_ZE_ST_String );
|
|
ASSERT(hwndSt);
|
|
SetWindowText( hwndSt, psz );
|
|
Free( psz );
|
|
}
|
|
|
|
if (pArgs->pszIn)
|
|
{
|
|
SetWindowText( pInfo->hwndEb, pArgs->pszIn );
|
|
Edit_SetSel( pInfo->hwndEb, 0, -1 );
|
|
}
|
|
|
|
/* Center dialog on the owner window.
|
|
*/
|
|
CenterWindow( hwndDlg, GetParent( hwndDlg ) );
|
|
|
|
/* Add context help button to title bar. Dlgedit.exe doesn't currently
|
|
** support this at resource edit time. When that's fixed set
|
|
** DS_CONTEXTHELP there and remove this call.
|
|
*/
|
|
AddContextHelpButton( hwndDlg );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
ZeTerm(
|
|
IN HWND hwndDlg )
|
|
|
|
/* Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
|
|
*/
|
|
{
|
|
ZEINFO* pInfo = (ZEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
|
|
|
|
TRACE("ZeTerm");
|
|
|
|
if (pInfo)
|
|
Free( pInfo );
|
|
}
|