|
|
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.