/*************************************************************************** * * * MODULE : MpFind.c * * * * PURPOSE : Code to do text searches in MultiPad. * * * * FUNCTIONS : RealSlowCompare () - Compares subject string with target * * string. * * * * MyFindText () - Looks for the search string in the * * active window. * * * * FindPrev () - Find previous occurence of search * * string. * * * * FindNext () - Find next occurence of search string* * * * FindDlgProc () - Dialog function for Search/Find. * * * * Find () - Invokes FindDlgProc () * * * ***************************************************************************/ // COPYRIGHT: // // (C) Copyright Microsoft Corp. 1992. All rights reserved. // // You have a royalty-free right to use, modify, reproduce and // distribute the Sample Files (and/or any modified version) in // any way you find useful, provided that you agree that // Microsoft has no warranty obligations or liability for any // Sample Application Files which are modified. #include "multipad.h" #undef HIWORD #undef LOWORD #define HIWORD(l) (((WORD*)&(l))[1]) #define LOWORD(l) (((WORD*)&(l))[0]) BOOL fCase = FALSE; /* Turn case sensitivity off */ char szSearch[160] = ""; /* Initialize search string */ /**************************************************************************** * * * FUNCTION : RealSlowCompare () * * * * PURPOSE : Compares subject string with the target string. This fn/ * * is called repeatedly so that all substrings are compared, * * which makes it O(n ** 2), hence it's name. * * * * RETURNS : TRUE - If pSubject is identical to pTarget. * * FALSE - otherwise. * * * ****************************************************************************/ BOOL NEAR PASCAL RealSlowCompare (pSubject, pTarget ) register PSTR pSubject; register PSTR pTarget; { if (fCase){ while (*pTarget) if (*pTarget++ != *pSubject++) return FALSE; } else{ /* If case-insensitive, convert both subject and target to lowercase * before comparing. */ AnsiLower ((LPSTR)pTarget); while (*pTarget) if (*pTarget++ != (char)(DWORD)AnsiLower ((LPSTR)(DWORD)(BYTE)*pSubject++)) return FALSE; } return TRUE; } /**************************************************************************** * * * FUNCTION : MyFindText () * * * * PURPOSE : Finds the search string in the active window according to * * search direction (dch) specified ( -1 for reverse and 1 for* * forward searches). * * * ****************************************************************************/ VOID NEAR PASCAL MyFindText( dch ) register int dch; { register PSTR pText; HANDLE hT; LONG l; WORD cch; int i; if (!*szSearch) return; /* Find the current selection range */ l = SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0L); /* Get the handle to the text buffer and lock it */ hT = (HANDLE)SendMessage (hwndActiveEdit, EM_GETHANDLE, 0, 0L); pText = LocalLock(hT); /* Get the length of the text */ cch = (WORD)SendMessage (hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L); /* Start with the next char. in selected range ... */ pText += LOWORD (l) + dch; /* Compute how many characters are before/after the current selection*/ if (dch < 0) i = LOWORD (l); else i = cch - LOWORD (l) + 1 - lstrlen (szSearch); /* While there are uncompared substrings... */ while ( i > 0){ LOWORD(l)+=dch; /* Does this substring match? */ if (RealSlowCompare(pText,szSearch)){ /* Yes, unlock the buffer.*/ LocalUnlock(hT); /* Select the located string */ HIWORD(l) = LOWORD(l) + lstrlen (szSearch); SendMessage (hwndActiveEdit, EM_SETSEL, 0, l); return; } i--; /* increment/decrement start position by 1 */ pText += dch; } /* Not found... unlock buffer. */ LocalUnlock (hT); /* Give a message */ MPError (hwndFrame, MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPSTR)szSearch); return; } /**************************************************************************** * * * FUNCTION : FindPrev () * * * * PURPOSE : Finds the previous occurence of the search string. Calls * * MyFindText () with a negative search direction. * * * ****************************************************************************/ VOID FAR PASCAL FindPrev(void) { MyFindText(-1); } /**************************************************************************** * * * FUNCTION : FindNext () * * * * PURPOSE : Finds the next occurence of search string. Calls * * MyFindText () with a positive search direction. * * * ****************************************************************************/ VOID FAR PASCAL FindNext(void) { MyFindText(1); } /**************************************************************************** * * * FUNCTION : FindDlgProc(hwnd, message, wParam, lParam) * * * * PURPOSE : Dialog function for the Search/Find command. Prompts user * * for target string, case flag and search direction. * * * ****************************************************************************/ BOOL FAR PASCAL FindDlgProc(hwnd, msg, wParam, lParam) HWND hwnd; WORD msg; WORD wParam; LONG lParam; { switch (msg){ case WM_INITDIALOG:{ /* Check/uncheck case button */ CheckDlgButton (hwnd, IDD_CASE, fCase); /* Set default search string to most recently searched string */ SetDlgItemText (hwnd, IDD_SEARCH, szSearch); /* Allow search only if target is nonempty */ if (!lstrlen (szSearch)){ EnableWindow (GetDlgItem (hwnd, IDOK), FALSE); EnableWindow (GetDlgItem (hwnd, IDD_PREV), FALSE); } break; } case WM_COMMAND:{ /* Search forward by default (see IDOK below) */ int i = 1; switch (wParam){ /* if the search target becomes non-empty, enable searching */ case IDD_SEARCH: if (HIWORD (lParam) == EN_CHANGE){ if (!(WORD) SendDlgItemMessage (hwnd, IDD_SEARCH, WM_GETTEXTLENGTH, 0, 0L)) i = FALSE; else i = TRUE; EnableWindow (GetDlgItem (hwnd, IDOK), i); EnableWindow (GetDlgItem (hwnd, IDD_PREV), i); } break; case IDD_CASE: /* Toggle state of case button */ CheckDlgButton (hwnd, IDD_CASE, !IsDlgButtonChecked (hwnd, IDD_CASE)); break; case IDD_PREV: /* Set direction to backwards */ i=-1; /*** FALL THRU ***/ case IDOK: /* Save case selection */ fCase = IsDlgButtonChecked( hwnd, IDD_CASE); /* Get search string */ GetDlgItemText (hwnd, IDD_SEARCH, szSearch, sizeof (szSearch)); /* Find the text */ MyFindText (i); /*** FALL THRU ***/ /* End the dialog */ case IDCANCEL: EndDialog (hwnd, 0); break; default: return FALSE; } break; } default: return FALSE; } return TRUE; } /**************************************************************************** * * * FUNCTION : Find() * * * * PURPOSE : Invokes the Search/Find dialog. * * * ****************************************************************************/ VOID FAR PASCAL Find() { FARPROC lpfn; lpfn = MakeProcInstance (FindDlgProc, hInst); DialogBox (hInst, IDD_FIND, hwndFrame, lpfn); FreeProcInstance (lpfn); }