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