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