windows-nt/Source/XPSP1/NT/net/rras/ras/ui/rasdlg/edit.c
2020-09-26 16:20:57 +08:00

1352 lines
31 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.
//
typedef struct
_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;
}
LEARGS;
// List editor dialog context block.
//
typedef struct
_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;
}
LEINFO;
// String Editor dialog arument block.
//
typedef struct
_ZEARGS
{
/* Caller's aruments to the stub API.
*/
TCHAR* pszIn;
DWORD dwSidTitle;
DWORD dwSidLabel;
DWORD cbMax;
DWORD dwHelpId;
TCHAR** ppszOut;
}
ZEARGS;
// String Editor dialog context block.
//
typedef struct
_ZEINFO
{
// Caller's arguments to the stub API.
//
ZEARGS* pArgs;
// Dialog and control handles.
//
HWND hwndDlg;
HWND hwndEb;
}
ZEINFO;
//-----------------------------------------------------------------------------
// 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_PTR 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 =
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 (nStatus) ? TRUE : FALSE;
}
//----------------------------------------------------------------------------
// 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.
//
{
TRACE3( "LeCommand(n=%d,i=%d,c=$%x)",
(DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
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)
{
LONG_PTR lId = ListBox_GetItemData( pInfo->hwndLb, i );
if (lId != 0)
{
DTLNODE* pNode;
pNode = DtlCreateNode( NULL, 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;
LONG_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, (ULONG_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* ) 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;
LONG_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;
LONG_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, 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* )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_PTR 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 (nStatus) ? TRUE : FALSE;
}
//----------------------------------------------------------------------------
// 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.
//
{
#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.
//
{
TRACE3( "ZeCommand(n=%d,i=%d,c=$%x)",
(DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
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, (ULONG_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 );
}
}