File:  [WindowsNT SDKs] / mstools / mfc / samples / multipad / mpfind.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:22:33 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-oct-1992, ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 328 10-12-1992

// mpfind.cpp : Defines the class behaviors for the text searches.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and Microsoft
// QuickHelp documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "multipad.h"
#include "ctype.h" // for _tolower

#ifndef _NTWIN
#pragma code_seg("_MPFIND")
#endif

// HIWORD and LOWORD as defined are not able to be used as lvalues, so
// "HIWORD(dwVar) = 0xFFFF" are normally impossible.  These macros allow it.
//
#undef HIWORD
#undef LOWORD
#define HIWORD(l) (((WORD*)&(l))[1])
#define LOWORD(l) (((WORD*)&(l))[0])

///////////////////////////////////////////////////////////////////////////
// Search dialog stuff
UINT CMPFrame::m_nMsgFind = ::RegisterWindowMessage(FINDMSGSTRING);
CFindReplaceDialog* CMPFrame::m_pFindReplace = NULL;
CString CMPFrame::m_strFind;
static BOOL bMatchCase = FALSE;

LONG
CMPFrame::CmdFindHelper(UINT wParam, LONG lParam)
{
	CFindReplaceDialog* pDlgFR = CFindReplaceDialog::GetNotifier(lParam);
	ASSERT(pDlgFR == m_pFindReplace);

	if (pDlgFR->IsTerminating())
	{
		SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
		m_pFindReplace = NULL;  // DO NOT DELETE, DONE AUTOMATICALLY

		GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_ENABLED);
		if (m_strFind.GetLength() > 0)
		{
			GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
			GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
		}
	}
	else
	{
		ASSERT(m_pActiveChild != NULL);

		// look for string
		m_strFind = m_pFindReplace->GetFindString();
		if (m_strFind.GetLength() == 0)
			return 0;

		if (m_pActiveChild->FindText(m_strFind,
			m_pFindReplace->SearchDown() ? 
					CMPChild::searchDown : CMPChild::searchUp,
			bMatchCase = m_pFindReplace->MatchCase()) == FALSE)
		{
			MPError(MB_OK|MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
		}
		else
		{
			GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
			GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
			SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
		}
	}
	return 0;
}

// CmdFind:
// Invoke the search dialog.  Returns when the dialog is closed by the user.
//
void CMPFrame::CmdFind()
{
	ASSERT(m_pFindReplace == NULL);

	m_pFindReplace = new CFindReplaceDialog;
	if (m_pFindReplace->Create(TRUE, m_strFind, NULL,
			FR_HIDEWHOLEWORD | FR_DOWN) == FALSE)
	{
		delete m_pFindReplace;
		m_pFindReplace = NULL;
		return;
	}
	GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_GRAYED);
}

// CmdFindPrev:
//
void CMPFrame::CmdFindPrev(void)
{
	ASSERT(m_strFind.GetLength() != 0);
	ASSERT(m_pActiveChild != NULL);

	if (m_pActiveChild->FindText(m_strFind, CMPChild::searchUp,
			bMatchCase) == FALSE)
		MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
	else
		SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

// CmdFindNext:
//
void CMPFrame::CmdFindNext(void)
{
	ASSERT(m_strFind.GetLength() != 0);
	ASSERT(m_pActiveChild != NULL);

	if (m_pActiveChild->FindText(m_strFind, CMPChild::searchDown,
			bMatchCase) == FALSE)
		MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
	else
		SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

/////////////////////////////////////////////////////////////////////////////
// Search Engine code
// This code is the workhorse code to search through the text buffer looking
// for a particular substring.

// RealSlowCompare:
// This is the brute-force method, which leaves a lot to be desired in
// performance.  However, this works fine for the typical text-file-sized
// buffer, which is currently limited by Windows to 32Kb anyway.
//
BOOL NEAR PASCAL RealSlowCompare(PSTR pSubject, LPSTR pTarget, 
		BOOL fCase = FALSE)
{
	if (fCase)
	{
		while (*pTarget)
		{
			if (*pTarget++ != *pSubject++)
				return FALSE;
		}
	}
	else
	{
		// If case-insensitive, convert both subject and target
		// to lowercase before comparing.
		//
		while (*pTarget)
		{
			if (::AnsiLower((LPSTR)(DWORD)*pTarget++) != 
				::AnsiLower((LPSTR)(DWORD)*pSubject++))
				return FALSE;
		}
	}
	return TRUE;
}

// FindText:
// Takes the szSearch buffer and tries to find it in the text buffer.
// The nDirection may be 1 for forward searches or -1 for backward searches.
//
BOOL CMPChild::FindText(LPCSTR lpszSearch, 
		int nDirection /* = searchDown */, 
		BOOL bMatchCase /* = FALSE */,
		BOOL bWholeWord /* = FALSE */)
{
	PSTR pText;
	HANDLE hText;
	LONG lSel;
	UINT cch;
	int i;
	
	if (*lpszSearch == '\0')
		return TRUE;
	
	// Find the current selection range.
	//
	lSel = m_edit.GetSel();
	
	// Get the handle to the text buffer and lock it.
	//
	hText = m_edit.GetHandle();
	pText = (PSTR)LocalLock(hText);
	
	// Get the length of the text.
	//
	cch = m_edit.GetWindowTextLength();
	
	// Start with the next char in selected range.
	//
	pText += LOWORD(lSel) + nDirection;
	
	// Compute how many characters are before/after the current selection.
	//
	if (nDirection < 0)
		i = LOWORD(lSel);
	else
		i = cch - LOWORD(lSel) + 1 - lstrlen(lpszSearch);
	
	// While there are uncompared substrings.
	//
	while (i > 0)
	{
		LOWORD(lSel) += nDirection;
	
		// Does this substring match?
		//
		if (RealSlowCompare(pText, (LPSTR)lpszSearch, bMatchCase))
		{
			// Unlock the buffer.
			//
			LocalUnlock(hText);
			
			// Select the located string.
			//
			HIWORD(lSel) = LOWORD(lSel) + lstrlen(lpszSearch);
			m_edit.SetSel(lSel);
			return TRUE;
		}
		i--;
		
		// Increment/decrement start position.
		//
		pText += nDirection;
	}
	
	// Not found... unlock buffer.
	//
	LocalUnlock(hText);
	
	return FALSE;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.