|
|
/*++
Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
Module Name:
find.c
Abstract:
This module implements the Win32 find dialog.
Revision History:
--*/
// precompiled headers
#include "precomp.h"
#pragma hdrstop
#include "find.h"
#include "util.h"
#ifdef UNICODE
////////////////////////////////////////////////////////////////////////////
//
// FindTextA
//
// ANSI entry point for FindText when this code is built UNICODE.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI FindTextA( LPFINDREPLACEA pFRA) { return (CreateFindReplaceDlg((LPFINDREPLACEW)pFRA, DLGT_FIND, COMDLG_ANSI)); }
#else
////////////////////////////////////////////////////////////////////////////
//
// FindTextW
//
// Stub UNICODE function for FindText when this code is built ANSI.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI FindTextW( LPFINDREPLACEW pFRW) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return (FALSE); }
#endif
////////////////////////////////////////////////////////////////////////////
//
// FindText
//
// The FindText function creates a system-defined modeless dialog box
// that enables the user to find text within a document.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI FindText( LPFINDREPLACE pFR) { return ( CreateFindReplaceDlg(pFR, DLGT_FIND, COMDLG_WIDE) ); }
#ifdef UNICODE
////////////////////////////////////////////////////////////////////////////
//
// ReplaceTextA
//
// ANSI entry point for ReplaceText when this code is built UNICODE.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI ReplaceTextA( LPFINDREPLACEA pFRA) { return (CreateFindReplaceDlg((LPFINDREPLACEW)pFRA, DLGT_REPLACE, COMDLG_ANSI)); }
#else
////////////////////////////////////////////////////////////////////////////
//
// ReplaceTextW
//
// Stub UNICODE function for ReplaceText when this code is built ANSI.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI ReplaceTextW( LPFINDREPLACEW pFRW) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return (FALSE); }
#endif
////////////////////////////////////////////////////////////////////////////
//
// ReplaceText
//
// The ReplaceText function creates a system-defined modeless dialog box
// that enables the user to find and replace text within a document.
//
////////////////////////////////////////////////////////////////////////////
HWND WINAPI ReplaceText( LPFINDREPLACE pFR) { return ( CreateFindReplaceDlg(pFR, DLGT_REPLACE, COMDLG_WIDE) ); }
////////////////////////////////////////////////////////////////////////////
//
// CreateFindReplaceDlg
//
// Creates FindText modeless dialog.
//
// pFR - ptr to FINDREPLACE structure set up by user
// DlgType - type of dialog to create (DLGT_FIND, DLGT_REPLACE)
// ApiType - type of FINDREPLACE ptr (COMDLG_ANSI or COMDLG_WIDE)
//
// Returns success => HANDLE to created dlg
// failure => HNULL = ((HANDLE) 0)
//
////////////////////////////////////////////////////////////////////////////
HWND CreateFindReplaceDlg( LPFINDREPLACE pFR, UINT DlgType, UINT ApiType) { HWND hWndDlg; // handle to created modeless dialog
HANDLE hDlgTemplate; // handle to loaded dialog resource
LPCDLGTEMPLATE lpDlgTemplate; // pointer to loaded resource block
#ifdef UNICODE
UINT uiWOWFlag = 0; #endif
if (!pFR) { StoreExtendedError(CDERR_INITIALIZATION); return (FALSE); }
if (!SetupOK(pFR, DlgType, ApiType)) { return (HNULL); }
if (!(hDlgTemplate = GetDlgTemplate(pFR, DlgType, ApiType))) { return (FALSE); }
if (lpDlgTemplate = (LPCDLGTEMPLATE)LockResource(hDlgTemplate)) { PFINDREPLACEINFO pFRI;
if (pFRI = (PFINDREPLACEINFO)LocalAlloc(LPTR, sizeof(FINDREPLACEINFO))) { //
// CLEAR extended error on new instantiation.
//
StoreExtendedError(0);
if (pFR->Flags & FR_ENABLEHOOK) { glpfnFindHook = GETHOOKFN(pFR); }
pFRI->pFR = pFR; pFRI->ApiType = ApiType; pFRI->DlgType = DlgType;
#ifdef UNICODE
if (IS16BITWOWAPP(pFR)) { uiWOWFlag = SCDLG_16BIT; }
hWndDlg = CreateDialogIndirectParamAorW( g_hinst, lpDlgTemplate, pFR->hwndOwner, FindReplaceDlgProc, (LPARAM)pFRI, uiWOWFlag ); #else
hWndDlg = CreateDialogIndirectParam( g_hinst, lpDlgTemplate, pFR->hwndOwner, FindReplaceDlgProc, (LPARAM)pFRI ); #endif
if (!hWndDlg) { glpfnFindHook = 0; LocalFree(pFRI); } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); return (NULL); } } else { StoreExtendedError(CDERR_LOCKRESFAILURE); return (HNULL); }
return (hWndDlg); }
////////////////////////////////////////////////////////////////////////////
//
// SetupOK
//
// Checks setup for unmet preconditions.
//
// pFR ptr to FINDREPLACE structure
// DlgType dialog type (either FIND or REPLACE)
// ApiType findreplace type (either COMDLG_ANSI or COMDLG_UNICODE)
//
// Returns TRUE - success
// FALSE - failure
//
////////////////////////////////////////////////////////////////////////////
BOOL SetupOK( LPFINDREPLACE pFR, UINT DlgType, UINT ApiType) { LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
//
// Sanity
//
if (!pFR) { return (FALSE); }
if (pFR->lStructSize != sizeof(FINDREPLACE)) { StoreExtendedError(CDERR_STRUCTSIZE); return (FALSE); }
//
// Verify window handle and text pointers.
//
if (!IsWindow(pFR->hwndOwner)) { StoreExtendedError(CDERR_DIALOGFAILURE); return (FALSE); }
if (!pFR->lpstrFindWhat || ((DlgType == DLGT_REPLACE) && !pFR->lpstrReplaceWith) || !pFR->wFindWhatLen) { StoreExtendedError(FRERR_BUFFERLENGTHZERO); return (FALSE); }
//
// Verify lpfnHook has a ptr if ENABLED.
//
if (pFR->Flags & FR_ENABLEHOOK) { if (!pFR->lpfnHook) { StoreExtendedError(CDERR_NOHOOK); return (FALSE); } } else { pFR->lpfnHook = 0; }
//
// Get LangID
//
if ( !(pFR->Flags & FR_ENABLETEMPLATE) && !(pFR->Flags & FR_ENABLETEMPLATEHANDLE) ) { LangID = GetDialogLanguage(pFR->hwndOwner, NULL); }
//
// Warning! Warning! Warning!
//
// We have to set g_tlsLangID before any call for CDLoadString
//
TlsSetValue(g_tlsLangID, (LPVOID) LangID);
//
// Load "CLOSE" text for Replace.
//
if ((DlgType == DLGT_REPLACE) && !CDLoadString(g_hinst, iszClose, (LPTSTR)szClose, CCHCLOSE)) { StoreExtendedError(CDERR_LOADSTRFAILURE); return (FALSE); }
//
// Setup unique msg# for talking to hwndOwner.
//
#ifdef UNICODE
if (ApiType == COMDLG_ANSI) { if (!(wFRMessage = RegisterWindowMessageA((LPCSTR)FINDMSGSTRINGA))) { StoreExtendedError(CDERR_REGISTERMSGFAIL); return (FALSE); } } else #endif
{ if (!(wFRMessage = RegisterWindowMessage((LPCTSTR)FINDMSGSTRING))) { StoreExtendedError(CDERR_REGISTERMSGFAIL); return (FALSE); } }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// GetDlgTemplate
//
// Finds and loads the dialog template.
//
// pFR ptr to FINDREPLACE structure
// ApiType findreplace type (either COMDLG_ANSI or COMDLG_UNICODE)
//
// Returns handle to dialog template - success
// HNULL = ((HANDLE) 0) - failure
//
////////////////////////////////////////////////////////////////////////////
HANDLE GetDlgTemplate( LPFINDREPLACE pFR, UINT DlgType, UINT ApiType) { HANDLE hRes; // handle of res. block with dialog
HANDLE hDlgTemplate; // handle to loaded dialog resource
LANGID LangID;
if (pFR->Flags & FR_ENABLETEMPLATE) { //
// Find/Load TEMP NAME and INSTANCE from pFR.
//
#ifdef UNICODE
if (ApiType == COMDLG_ANSI) { hRes = FindResourceA( (HMODULE)pFR->hInstance, (LPCSTR)pFR->lpTemplateName, (LPCSTR)RT_DIALOG ); } else #endif
{ hRes = FindResource( pFR->hInstance, (LPCTSTR)pFR->lpTemplateName, (LPCTSTR)RT_DIALOG ); } if (!hRes) { StoreExtendedError(CDERR_FINDRESFAILURE); return (HNULL); } if (!(hDlgTemplate = LoadResource(pFR->hInstance, hRes))) { StoreExtendedError(CDERR_LOADRESFAILURE); return (HNULL); } } else if (pFR->Flags & FR_ENABLETEMPLATEHANDLE) { //
// Get whole PRELOADED resource handle from user.
//
if (!(hDlgTemplate = pFR->hInstance)) { StoreExtendedError(CDERR_NOHINSTANCE); return (HNULL); } } else { //
// Get STANDARD dialog from DLL instance block.
//
LangID = (LANGID) TlsGetValue(g_tlsLangID);
if (DlgType == DLGT_FIND) { hRes = FindResourceExFallback( g_hinst, RT_DIALOG, MAKEINTRESOURCE(FINDDLGORD), LangID); } else { hRes = FindResourceExFallback( g_hinst, RT_DIALOG, MAKEINTRESOURCE(REPLACEDLGORD), LangID); }
//
// !!!!! definitely ORD here?
//
if (!hRes) { StoreExtendedError(CDERR_FINDRESFAILURE); return (HNULL); } if (!(hDlgTemplate = LoadResource(g_hinst, hRes))) { StoreExtendedError(CDERR_LOADRESFAILURE); return (HNULL); } }
return (hDlgTemplate); }
////////////////////////////////////////////////////////////////////////////
//
// FindReplaceDlgProc
//
// Handles messages to FindText/ReplaceText dialogs.
//
// hDlg - handle to dialog
// wMsg - window message
// wParam - w parameter of message
// lParam - l parameter of message
//
// Note: lparam contains ptr to FINDREPLACEINITPROC upon
// initialization from CreateDialogIndirectParam...
//
// Returns: TRUE (or dlg fcn return vals) - success
// FALSE - failure
//
////////////////////////////////////////////////////////////////////////////
BOOL_PTR CALLBACK FindReplaceDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { PFINDREPLACEINFO pFRI; LPFINDREPLACE pFR; BOOL_PTR bRet;
//
// If a hook exists, let hook function do procing.
//
if (pFRI = (PFINDREPLACEINFO)GetProp(hDlg, FINDREPLACEPROP)) { if ((pFR = (LPFINDREPLACE)pFRI->pFR) && (pFR->Flags & FR_ENABLEHOOK)) { LPFRHOOKPROC lpfnHook = GETHOOKFN(pFR);
if ((bRet = (*lpfnHook)(hDlg, wMsg, wParam, lParam))) { return (bRet); } } } else if (glpfnFindHook && (wMsg != WM_INITDIALOG) && (bRet = (* glpfnFindHook)(hDlg, wMsg, wParam, lParam))) { return (bRet); }
//
// Dispatch MSG to appropriate HANDLER.
//
switch (wMsg) { case ( WM_INITDIALOG ) : { //
// Set Up P-Slot.
//
pFRI = (PFINDREPLACEINFO)lParam; SetProp(hDlg, FINDREPLACEPROP, (HANDLE)pFRI);
glpfnFindHook = 0;
//
// Init dlg controls accordingly.
//
pFR = pFRI->pFR; InitControlsWithFlags(hDlg, pFR, pFRI->DlgType, pFRI->ApiType);
//
// If Hook function, do extra processing.
//
if (pFR->Flags & FR_ENABLEHOOK) { LPFRHOOKPROC lpfnHook = GETHOOKFN(pFR);
bRet = (*lpfnHook)(hDlg, wMsg, wParam, (LPARAM)pFR); } else { bRet = TRUE; }
if (bRet) { //
// If the hook function returns FALSE, then we must call
// these functions here.
//
ShowWindow(hDlg, SW_SHOWNORMAL); UpdateWindow(hDlg); }
return (bRet); break; } case ( WM_COMMAND ) : { if (!pFRI || !pFR) { return (FALSE); }
switch (GET_WM_COMMAND_ID (wParam, lParam)) { //
// FIND NEXT button clicked.
//
case ( IDOK ) : { UpdateTextAndFlags( hDlg, pFR, FR_FINDNEXT, pFRI->DlgType, pFRI->ApiType ); NotifyUpdateTextAndFlags(pFR); break; } case ( IDCANCEL ) : case ( IDABORT ) : { EndDlgSession(hDlg, pFR); LocalFree(pFRI); break; } case ( psh1 ) : case ( psh2 ) : { UpdateTextAndFlags( hDlg, pFR, (wParam == psh1) ? FR_REPLACE : FR_REPLACEALL, pFRI->DlgType, pFRI->ApiType ); if (NotifyUpdateTextAndFlags(pFR) == TRUE) { //
// Change <Cancel> button to <Close> if function
// returns TRUE.
// IDCANCEL instead of psh1.
SetWindowText( GetDlgItem(hDlg, IDCANCEL), (LPTSTR)szClose ); } break; } case ( pshHelp ) : { //
// Call HELP app.
//
#ifdef UNICODE
if (pFRI->ApiType == COMDLG_ANSI) { if (msgHELPA && pFR->hwndOwner) { SendMessage( pFR->hwndOwner, msgHELPA, (WPARAM)hDlg, (LPARAM)pFR ); } } else #endif
{ if (msgHELPW && pFR->hwndOwner) { SendMessage( pFR->hwndOwner, msgHELPW, (WPARAM)hDlg, (LPARAM)pFR ); } } break; } case ( edt1 ) : { if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { BOOL fAnythingToFind = (BOOL)SendDlgItemMessage( hDlg, edt1, WM_GETTEXTLENGTH, 0, 0L ); EnableWindow(GetDlgItem(hDlg, IDOK), fAnythingToFind); if (pFRI->DlgType == DLGT_REPLACE) { EnableWindow(GetDlgItem(hDlg, psh1), fAnythingToFind); EnableWindow(GetDlgItem(hDlg, psh2), fAnythingToFind); } }
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { EnableWindow( GetDlgItem(hDlg, IDOK), (BOOL)SendDlgItemMessage( hDlg, edt1, WM_GETTEXTLENGTH, 0, 0L )); } break; } default : { return (FALSE); } } break; } case ( WM_HELP ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aFindReplaceHelpIDs ); } break; } case ( WM_CONTEXTMENU ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)aFindReplaceHelpIDs ); } break; } case ( WM_CLOSE ) : { SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(IDCANCEL, 0, 0)); return (TRUE); break; } default: { return (FALSE); break; } }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// EndDlgSession
//
// Cleans up upon destroying the dialog.
//
////////////////////////////////////////////////////////////////////////////
VOID EndDlgSession( HWND hDlg, LPFINDREPLACE pFR) { //
// Need to terminate regardless of app testing order ... so:
//
//
// No SUCCESS on termination.
//
pFR->Flags &= ~((DWORD)(FR_REPLACE | FR_FINDNEXT | FR_REPLACEALL));
//
// Tell caller dialog is about to terminate.
//
pFR->Flags |= FR_DIALOGTERM; NotifyUpdateTextAndFlags(pFR);
if (IS16BITWOWAPP(pFR)) { if ((pFR->Flags & FR_ENABLEHOOK) && (pFR->lpfnHook)) { (*pFR->lpfnHook)(hDlg, WM_DESTROY, 0, 0); } }
//
// Free property slots.
//
RemoveProp(hDlg, FINDREPLACEPROP); DestroyWindow(hDlg); }
////////////////////////////////////////////////////////////////////////////
//
// InitControlsWithFlags
//
////////////////////////////////////////////////////////////////////////////
VOID InitControlsWithFlags( HWND hDlg, LPFINDREPLACE pFR, UINT DlgType, UINT ApiType) { HWND hCtl;
//
// Set EDIT control to FindText.
//
#ifdef UNICODE
if (ApiType == COMDLG_ANSI) { SetDlgItemTextA(hDlg, edt1, (LPSTR)pFR->lpstrFindWhat); } else #endif
{ SetDlgItemText(hDlg, edt1, (LPTSTR)pFR->lpstrFindWhat); } SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(edt1, 0, EN_CHANGE));
//
// Set HELP push button state.
//
if (!(pFR->Flags & FR_SHOWHELP)) { ShowWindow(hCtl = GetDlgItem(hDlg, pshHelp), SW_HIDE); EnableWindow(hCtl, FALSE); }
//
// Dis/Enable check state of WHOLE WORD control.
//
if (pFR->Flags & FR_HIDEWHOLEWORD) { ShowWindow(hCtl = GetDlgItem(hDlg, chx1), SW_HIDE); EnableWindow(hCtl, FALSE); } else if (pFR->Flags & FR_NOWHOLEWORD) { EnableWindow(GetDlgItem(hDlg, chx1), FALSE); } CheckDlgButton(hDlg, chx1, (pFR->Flags & FR_WHOLEWORD) ? TRUE: FALSE);
//
// Dis/Enable check state of MATCH CASE control.
//
if (pFR->Flags & FR_HIDEMATCHCASE) { ShowWindow(hCtl = GetDlgItem(hDlg, chx2), SW_HIDE); EnableWindow(hCtl, FALSE); } else if (pFR->Flags & FR_NOMATCHCASE) { EnableWindow(GetDlgItem(hDlg, chx2), FALSE); } CheckDlgButton(hDlg, chx2, (pFR->Flags & FR_MATCHCASE) ? TRUE: FALSE);
//
// Dis/Enable check state of UP/DOWN buttons.
//
if (pFR->Flags & FR_HIDEUPDOWN) { ShowWindow(GetDlgItem(hDlg, grp1), SW_HIDE); ShowWindow(hCtl = GetDlgItem(hDlg, rad1), SW_HIDE); EnableWindow(hCtl, FALSE); ShowWindow(hCtl = GetDlgItem(hDlg, rad2), SW_HIDE); EnableWindow(hCtl, FALSE); } else if (pFR->Flags & FR_NOUPDOWN) { EnableWindow(GetDlgItem(hDlg, rad1), FALSE); EnableWindow(GetDlgItem(hDlg, rad2), FALSE); }
if (DlgType == DLGT_FIND) { //
// Find Text only search direction setup.
//
CheckRadioButton( hDlg, rad1, rad2, (pFR->Flags & FR_DOWN ? rad2 : rad1) ); } else { //
// Replace Text only operations.
//
#ifdef UNICODE
if (ApiType == COMDLG_ANSI) { SetDlgItemTextA(hDlg, edt2, (LPSTR)pFR->lpstrReplaceWith); } else #endif
{ SetDlgItemText(hDlg, edt2, pFR->lpstrReplaceWith); } SendMessage( hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(edt2, 0, EN_CHANGE) ); } }
////////////////////////////////////////////////////////////////////////////
//
// UpdateTextAndFlags
//
// chx1 is whether or not to match entire words
// chx2 is whether or not case is relevant
// chx3 is whether or not to wrap scans
//
////////////////////////////////////////////////////////////////////////////
VOID UpdateTextAndFlags( HWND hDlg, LPFINDREPLACE pFR, DWORD dwActionFlag, UINT DlgType, UINT ApiType) { //
// Only clear flags that this routine sets. The hook and template
// flags should not be anded off here.
//
pFR->Flags &= ~((DWORD)(FR_WHOLEWORD | FR_MATCHCASE | FR_REPLACE | FR_FINDNEXT | FR_REPLACEALL | FR_DOWN)); if (IsDlgButtonChecked(hDlg, chx1)) { pFR->Flags |= FR_WHOLEWORD; }
if (IsDlgButtonChecked(hDlg, chx2)) { pFR->Flags |= FR_MATCHCASE; }
//
// Set ACTION flag FR_{REPLACE,FINDNEXT,REPLACEALL}.
//
pFR->Flags |= dwActionFlag;
#ifdef UNICODE
if (ApiType == COMDLG_ANSI) { GetDlgItemTextA(hDlg, edt1, (LPSTR)pFR->lpstrFindWhat, pFR->wFindWhatLen); } else #endif
{ GetDlgItemText(hDlg, edt1, pFR->lpstrFindWhat, pFR->wFindWhatLen); }
if (DlgType == DLGT_FIND) { //
// Assume searching down. Check if UP button is NOT pressed, rather
// than if DOWN button IS. So, if buttons have been hidden or
// disabled, FR_DOWN flag will be set correctly.
//
if (!IsDlgButtonChecked(hDlg, rad1)) { pFR->Flags |= FR_DOWN; } } else { #ifdef UNICODE
if (ApiType == COMDLG_ANSI) { GetDlgItemTextA( hDlg, edt2, (LPSTR)pFR->lpstrReplaceWith, pFR->wReplaceWithLen ); } else #endif
{ GetDlgItemText( hDlg, edt2, pFR->lpstrReplaceWith, pFR->wReplaceWithLen ); } pFR->Flags |= FR_DOWN; } }
////////////////////////////////////////////////////////////////////////////
//
// NotifyUpdateTextAndFlags
//
////////////////////////////////////////////////////////////////////////////
LRESULT NotifyUpdateTextAndFlags( LPFINDREPLACE pFR) { if (IS16BITWOWAPP(pFR)) { return ( SendMessage( pFR->hwndOwner, WM_NOTIFYWOW, WMNW_UPDATEFINDREPLACE, (DWORD_PTR)pFR ) ); } return ( SendMessage(pFR->hwndOwner, wFRMessage, 0, (DWORD_PTR)pFR) ); }
|