// 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 ); } }