|
|
1.1 ! root 1: /*************************************************************************** ! 2: * * ! 3: * MODULE : MpFind.c * ! 4: * * ! 5: * PURPOSE : Code to do text searches in MultiPad. * ! 6: * * ! 7: * FUNCTIONS : RealSlowCompare () - Compares subject string with target * ! 8: * string. * ! 9: * * ! 10: * Local_FindText () - Looks for the search string in the * ! 11: * active window. * ! 12: * * ! 13: * FindPrev () - Find previous occurence of search * ! 14: * string. * ! 15: * * ! 16: * FindNext () - Find next occurence of search string* ! 17: * * ! 18: * FindDlgProc () - Dialog function for Search/Find. * ! 19: * * ! 20: * Find () - Invokes FindDlgProc () * ! 21: * * ! 22: ***************************************************************************/ ! 23: #include "multipad.h" ! 24: ! 25: #undef HIWORD ! 26: #undef LOWORD ! 27: ! 28: #define HIWORD(l) (((WORD*)&(l))[1]) ! 29: #define LOWORD(l) (((WORD*)&(l))[0]) ! 30: ! 31: BOOL fCase = FALSE; /* Turn case sensitivity off */ ! 32: CHAR szSearch[160] = ""; /* Initialize search string */ ! 33: ! 34: //LPSTR WINAPI AnsiLower (LPSTR); ! 35: ! 36: /**************************************************************************** ! 37: * * ! 38: * FUNCTION : RealSlowCompare () * ! 39: * * ! 40: * PURPOSE : Compares subject string with the target string. This fn/ * ! 41: * is called repeatedly so that all substrings are compared, * ! 42: * which makes it O(n ** 2), hence it's name. * ! 43: * * ! 44: * RETURNS : TRUE - If pSubject is identical to pTarget. * ! 45: * FALSE - otherwise. * ! 46: * * ! 47: ****************************************************************************/ ! 48: ! 49: BOOL NEAR PASCAL RealSlowCompare ( ! 50: register PSTR pSubject, ! 51: register PSTR pTarget) ! 52: { ! 53: if (fCase){ ! 54: while (*pTarget) ! 55: if (*pTarget++ != *pSubject++) ! 56: return FALSE; ! 57: } ! 58: else{ ! 59: /* If case-insensitive, convert both subject and target to lowercase ! 60: * before comparing. ! 61: */ ! 62: AnsiLower ((LPSTR)pTarget); ! 63: while (*pTarget) ! 64: if (*pTarget++ != (CHAR)(DWORD)AnsiLower ((LPSTR)(DWORD)(BYTE)*pSubject++)) ! 65: return FALSE; ! 66: } ! 67: return TRUE; ! 68: } ! 69: ! 70: /**************************************************************************** ! 71: * * ! 72: * FUNCTION : Local_FindText () * ! 73: * * ! 74: * PURPOSE : Finds the search string in the active window according to * ! 75: * search direction (dch) specified ( -1 for reverse and 1 for* ! 76: * forward searches). * ! 77: * * ! 78: ****************************************************************************/ ! 79: VOID NEAR PASCAL Local_FindText(register INT dch) ! 80: { ! 81: register PSTR pText; ! 82: HANDLE hT; ! 83: LONG l; ! 84: WORD cch; ! 85: INT i; ! 86: ! 87: if (!*szSearch) ! 88: return; ! 89: ! 90: /* Find the current selection range */ ! 91: l = (LONG)SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0); ! 92: ! 93: /* Get the handle to the text buffer and lock it */ ! 94: hT = (HANDLE)SendMessage (hwndActiveEdit, EM_GETHANDLE, 0, 0L); ! 95: pText = LocalLock(hT); ! 96: ! 97: /* Get the length of the text */ ! 98: cch = (WORD)SendMessage (hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L); ! 99: ! 100: /* Start with the next char. in selected range ... */ ! 101: pText += LOWORD (l) + dch; ! 102: ! 103: /* Compute how many characters are before/after the current selection*/ ! 104: if (dch < 0) ! 105: i = LOWORD (l); ! 106: else ! 107: i = cch - LOWORD (l) + 1 - lstrlen (szSearch); ! 108: ! 109: /* While there are uncompared substrings... */ ! 110: while ( i > 0){ ! 111: LOWORD(l)+=dch; ! 112: ! 113: /* Does this substring match? */ ! 114: if (RealSlowCompare(pText,szSearch)){ ! 115: ! 116: /* Yes, unlock the buffer.*/ ! 117: LocalUnlock(hT); ! 118: ! 119: /* Select the located string */ ! 120: HIWORD(l) = LOWORD(l) + (WORD)lstrlen (szSearch); ! 121: SendMessage(hwndActiveEdit, EM_SETSEL, GET_EM_SETSEL_MPS(LOWORD(l), HIWORD(l))); ! 122: return; ! 123: } ! 124: i--; ! 125: ! 126: /* increment/decrement start position by 1 */ ! 127: pText += dch; ! 128: } ! 129: ! 130: /* Not found... unlock buffer. */ ! 131: LocalUnlock (hT); ! 132: ! 133: /* Give a message */ ! 134: MPError (hwndFrame, MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPSTR)szSearch); ! 135: ! 136: return; ! 137: } ! 138: ! 139: /**************************************************************************** ! 140: * * ! 141: * FUNCTION : FindPrev () * ! 142: * * ! 143: * PURPOSE : Finds the previous occurence of the search string. Calls * ! 144: * Local_FindText () with a negative search direction. * ! 145: * * ! 146: ****************************************************************************/ ! 147: VOID APIENTRY FindPrev() ! 148: { ! 149: Local_FindText(-1); ! 150: } ! 151: ! 152: /**************************************************************************** ! 153: * * ! 154: * FUNCTION : FindNext () * ! 155: * * ! 156: * PURPOSE : Finds the next occurence of search string. Calls * ! 157: * Local_FindText () with a positive search direction. * ! 158: * * ! 159: ****************************************************************************/ ! 160: VOID APIENTRY FindNext() ! 161: { ! 162: Local_FindText(1); ! 163: } ! 164: ! 165: /**************************************************************************** ! 166: * * ! 167: * FUNCTION : FindDlgProc(hwnd, message, wParam, lParam) * ! 168: * * ! 169: * PURPOSE : Dialog function for the Search/Find command. Prompts user * ! 170: * for target string, case flag and search direction. * ! 171: * * ! 172: ****************************************************************************/ ! 173: BOOL APIENTRY FindDlgProc( ! 174: HWND hwnd, ! 175: UINT msg, ! 176: UINT wParam, ! 177: LONG lParam) ! 178: { ! 179: switch (msg){ ! 180: case WM_INITDIALOG:{ ! 181: ! 182: /* Check/uncheck case button */ ! 183: CheckDlgButton (hwnd, (int)IDD_CASE, (WORD)fCase); ! 184: ! 185: /* Set default search string to most recently searched string */ ! 186: SetDlgItemText (hwnd, IDD_SEARCH, szSearch); ! 187: ! 188: /* Allow search only if target is nonempty */ ! 189: if (!lstrlen (szSearch)){ ! 190: EnableWindow (GetDlgItem (hwnd, IDOK), FALSE); ! 191: EnableWindow (GetDlgItem (hwnd, IDD_PREV), FALSE); ! 192: } ! 193: break; ! 194: } ! 195: ! 196: case WM_COMMAND: ! 197: { ! 198: ! 199: /* Search forward by default (see IDOK below) */ ! 200: INT i = 1; ! 201: ! 202: switch (LOWORD(wParam)){ ! 203: /* if the search target becomes non-empty, enable searching */ ! 204: case IDD_SEARCH: ! 205: if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE){ ! 206: if (!(WORD) SendDlgItemMessage (hwnd, ! 207: IDD_SEARCH, ! 208: WM_GETTEXTLENGTH, ! 209: 0, ! 210: 0L)) ! 211: i = FALSE; ! 212: else ! 213: i = TRUE; ! 214: EnableWindow (GetDlgItem (hwnd, IDOK), i); ! 215: EnableWindow (GetDlgItem (hwnd, IDD_PREV), i); ! 216: } ! 217: break; ! 218: ! 219: case IDD_CASE: ! 220: /* Toggle state of case button */ ! 221: CheckDlgButton (hwnd, ! 222: (int)IDD_CASE, ! 223: (WORD)!IsDlgButtonChecked (hwnd, (int)IDD_CASE)); ! 224: break; ! 225: ! 226: case IDD_PREV: ! 227: /* Set direction to backwards */ ! 228: i=-1; ! 229: /*** FALL THRU ***/ ! 230: ! 231: case IDOK: ! 232: /* Save case selection */ ! 233: fCase = IsDlgButtonChecked( hwnd, IDD_CASE); ! 234: ! 235: /* Get search string */ ! 236: GetDlgItemText (hwnd, IDD_SEARCH, szSearch, sizeof (szSearch)); ! 237: ! 238: /* Find the text */ ! 239: Local_FindText (i); ! 240: /*** FALL THRU ***/ ! 241: ! 242: /* End the dialog */ ! 243: case IDCANCEL: ! 244: EndDialog (hwnd, 0); ! 245: break; ! 246: ! 247: default: ! 248: return FALSE; ! 249: } ! 250: break; ! 251: } ! 252: default: ! 253: return FALSE; ! 254: } ! 255: return TRUE; ! 256: UNREFERENCED_PARAMETER(lParam); ! 257: } ! 258: ! 259: /**************************************************************************** ! 260: * * ! 261: * FUNCTION : Find() * ! 262: * * ! 263: * PURPOSE : Invokes the Search/Find dialog. * ! 264: * * ! 265: ****************************************************************************/ ! 266: ! 267: VOID APIENTRY Find() ! 268: { ! 269: DialogBox (hInst, IDD_FIND, hwndFrame, FindDlgProc); ! 270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.