|
|
1.1 root 1: // mpfind.cpp : Defines the class behaviors for the text searches.
2: //
3: // This is a part of the Microsoft Foundation Classes C++ library.
4: // Copyright (C) 1992 Microsoft Corporation
5: // All rights reserved.
6: //
7: // This source code is only intended as a supplement to the
8: // Microsoft Foundation Classes Reference and Microsoft
9: // QuickHelp documentation provided with the library.
10: // See these sources for detailed information regarding the
11: // Microsoft Foundation Classes product.
12:
13: #include "multipad.h"
14: #include "ctype.h" // for _tolower
15:
16: #pragma code_seg("_MPFIND")
17:
18: // HIWORD and LOWORD as defined are not able to be used as lvalues, so
19: // "HIWORD(dwVar) = 0xFFFF" are normally impossible. These macros allow it.
20: //
21: #undef HIWORD
22: #undef LOWORD
23: #define HIWORD(l) (((WORD*)&(l))[1])
24: #define LOWORD(l) (((WORD*)&(l))[0])
25:
26: ///////////////////////////////////////////////////////////////////////////
27: // Search dialog stuff
28: UINT CMPFrame::m_nMsgFind = ::RegisterWindowMessage(FINDMSGSTRING);
29: CFindReplaceDialog* CMPFrame::m_pFindReplace = NULL;
30: CString CMPFrame::m_strFind;
31: static BOOL bMatchCase = FALSE;
32:
33: LONG
34: CMPFrame::CmdFindHelper(UINT wParam, LONG lParam)
35: {
36: CFindReplaceDialog* pDlgFR = CFindReplaceDialog::GetNotifier(lParam);
37: ASSERT(pDlgFR == m_pFindReplace);
38:
39: if (pDlgFR->IsTerminating())
40: {
41: SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
42: m_pFindReplace = NULL; // DO NOT DELETE, DONE AUTOMATICALLY
43:
44: GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_ENABLED);
45: if (m_strFind.GetLength() > 0)
46: {
47: GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
48: GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
49: }
50: }
51: else
52: {
53: ASSERT(m_pActiveChild != NULL);
54:
55: // look for string
56: m_strFind = m_pFindReplace->GetFindString();
57: if (m_strFind.GetLength() == 0)
58: return 0;
59:
60: if (m_pActiveChild->FindText(m_strFind,
61: m_pFindReplace->SearchDown() ?
62: CMPChild::searchDown : CMPChild::searchUp,
63: bMatchCase = m_pFindReplace->MatchCase()) == FALSE)
64: {
65: MPError(MB_OK|MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
66: }
67: else
68: {
69: GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
70: GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
71: SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
72: }
73: }
74: return 0;
75: }
76:
77: // CmdFind:
78: // Invoke the search dialog. Returns when the dialog is closed by the user.
79: //
80: void CMPFrame::CmdFind()
81: {
82: ASSERT(m_pFindReplace == NULL);
83:
84: m_pFindReplace = new CFindReplaceDialog;
85: if (m_pFindReplace->Create(TRUE, m_strFind, NULL,
86: FR_HIDEWHOLEWORD | FR_DOWN) == FALSE)
87: {
88: delete m_pFindReplace;
89: m_pFindReplace = NULL;
90: return;
91: }
92: GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_GRAYED);
93: }
94:
95: // CmdFindPrev:
96: //
97: void CMPFrame::CmdFindPrev(void)
98: {
99: ASSERT(m_strFind.GetLength() != 0);
100: ASSERT(m_pActiveChild != NULL);
101:
102: if (m_pActiveChild->FindText(m_strFind, CMPChild::searchUp,
103: bMatchCase) == FALSE)
104: MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
105: else
106: SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
107: }
108:
109: // CmdFindNext:
110: //
111: void CMPFrame::CmdFindNext(void)
112: {
113: ASSERT(m_strFind.GetLength() != 0);
114: ASSERT(m_pActiveChild != NULL);
115:
116: if (m_pActiveChild->FindText(m_strFind, CMPChild::searchDown,
117: bMatchCase) == FALSE)
118: MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
119: else
120: SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
121: }
122:
123: /////////////////////////////////////////////////////////////////////////////
124: // Search Engine code
125: // This code is the workhorse code to search through the text buffer looking
126: // for a particular substring.
127:
128: // RealSlowCompare:
129: // This is the brute-force method, which leaves a lot to be desired in
130: // performance. However, this works fine for the typical text-file-sized
131: // buffer, which is currently limited by Windows to 32Kb anyway.
132: //
133: BOOL NEAR PASCAL RealSlowCompare(PSTR pSubject, LPSTR pTarget,
134: BOOL fCase = FALSE)
135: {
136: if (fCase)
137: {
138: while (*pTarget)
139: {
140: if (*pTarget++ != *pSubject++)
141: return FALSE;
142: }
143: }
144: else
145: {
146: // If case-insensitive, convert both subject and target
147: // to lowercase before comparing.
148: //
149: while (*pTarget)
150: {
151: if (::AnsiLower((LPSTR)(DWORD)*pTarget++) !=
152: ::AnsiLower((LPSTR)(DWORD)*pSubject++))
153: return FALSE;
154: }
155: }
156: return TRUE;
157: }
158:
159: // FindText:
160: // Takes the szSearch buffer and tries to find it in the text buffer.
161: // The nDirection may be 1 for forward searches or -1 for backward searches.
162: //
163: BOOL CMPChild::FindText(LPCSTR lpszSearch,
164: int nDirection /* = searchDown */,
165: BOOL bMatchCase /* = FALSE */,
166: BOOL bWholeWord /* = FALSE */)
167: {
168: PSTR pText;
169: HANDLE hText;
170: LONG lSel;
171: UINT cch;
172: int i;
173:
174: if (*lpszSearch == '\0')
175: return TRUE;
176:
177: // Find the current selection range.
178: //
179: lSel = m_edit.GetSel();
180:
181: // Get the handle to the text buffer and lock it.
182: //
183: hText = m_edit.GetHandle();
184: pText = (PSTR)LocalLock(hText);
185:
186: // Get the length of the text.
187: //
188: cch = m_edit.GetWindowTextLength();
189:
190: // Start with the next char in selected range.
191: //
192: pText += LOWORD(lSel) + nDirection;
193:
194: // Compute how many characters are before/after the current selection.
195: //
196: if (nDirection < 0)
197: i = LOWORD(lSel);
198: else
199: i = cch - LOWORD(lSel) + 1 - lstrlen(lpszSearch);
200:
201: // While there are uncompared substrings.
202: //
203: while (i > 0)
204: {
205: LOWORD(lSel) += nDirection;
206:
207: // Does this substring match?
208: //
209: if (RealSlowCompare(pText, (LPSTR)lpszSearch, bMatchCase))
210: {
211: // Unlock the buffer.
212: //
213: LocalUnlock(hText);
214:
215: // Select the located string.
216: //
217: HIWORD(lSel) = LOWORD(lSel) + lstrlen(lpszSearch);
218: m_edit.SetSel(lSel);
219: return TRUE;
220: }
221: i--;
222:
223: // Increment/decrement start position.
224: //
225: pText += nDirection;
226: }
227:
228: // Not found... unlock buffer.
229: //
230: LocalUnlock(hText);
231:
232: return FALSE;
233: }
234:
235:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.