|
|
/*
* misc notepad functions * Copyright (C) 1984-2000 Microsoft Corporation */
#include "precomp.h"
BOOL fCase = FALSE; // Flag specifying case sensitive search
BOOL fReverse = FALSE; // Flag for direction of search
extern HWND hDlgFind; // handle to modeless FindText window
LPTSTR ReverseScan( LPTSTR lpSource, LPTSTR lpLast, LPTSTR lpSearch, BOOL fCaseSensitive ) { TCHAR cLastCharU; TCHAR cLastCharL; INT iLen;
cLastCharU= (TCHAR) (INT_PTR) CharUpper( (LPTSTR)(INT_PTR)(*lpSearch) ); cLastCharL= (TCHAR) (INT_PTR) CharLower( (LPTSTR)(INT_PTR)(*lpSearch) );
iLen = lstrlen(lpSearch);
if (!lpLast) lpLast = lpSource + lstrlen(lpSource);
do { if (lpLast == lpSource) return NULL;
--lpLast;
if (fCaseSensitive) { if (*lpLast != *lpSearch) continue; } else { if( !( *lpLast == cLastCharU || *lpLast == cLastCharL ) ) continue; }
if (fCaseSensitive) { if (!_tcsncmp( lpLast, lpSearch, iLen)) break; } else { //
// compare whole string using locale specific comparison.
// do not use C runtime version since it may be wrong.
//
if( 2 == CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT | NORM_STOP_ON_NULL, lpLast, iLen, lpSearch, iLen) ) break; } } while (TRUE);
return lpLast; }
LPTSTR ForwardScan(LPTSTR lpSource, LPTSTR lpSearch, BOOL fCaseSensitive ) { TCHAR cFirstCharU; TCHAR cFirstCharL; int iLen = lstrlen(lpSearch);
cFirstCharU= (TCHAR) (INT_PTR) CharUpper( (LPTSTR)(INT_PTR)(*lpSearch) ); cFirstCharL= (TCHAR) (INT_PTR) CharLower( (LPTSTR)(INT_PTR)(*lpSearch) );
while (*lpSource) { if (fCaseSensitive) { if (*lpSource != *lpSearch) { lpSource++; continue; } } else { if( !( *lpSource == cFirstCharU || *lpSource == cFirstCharL ) ) { lpSource++; continue; } }
if (fCaseSensitive) { if (!_tcsncmp( lpSource, lpSearch, iLen)) break; } else { if( 2 == CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT | NORM_STOP_ON_NULL, lpSource, iLen, lpSearch, iLen) ) break; }
lpSource++; }
return *lpSource ? lpSource : NULL; }
// search forward or backward in the edit control text for the given pattern
// It is the responsibility of the caller to set the cursor
BOOL Search (TCHAR * szKey) { BOOL bStatus= FALSE; TCHAR * pStart, *pMatch; DWORD StartIndex, LineNum, EndIndex; DWORD SelStart, SelEnd, i; HANDLE hEText; // handle to edit text
UINT uSelState; HMENU hMenu; BOOL bSelectAll = FALSE;
if (!*szKey) return( bStatus );
SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&SelStart, (LPARAM)&SelEnd);
// when we finish the search, we highlight the text found, and continue
// the search after the end of the highlighted position (in forward
// case) or from the begining of the highlighted position in the reverse
// direction (in reverse case). this would break if the user has
// selected all text. this hack would take care of it. (this is consistent
// with VC editors' search too.
hMenu = GetMenu(hwndNP); uSelState = GetMenuState(GetSubMenu(hMenu, 1), M_SELECTALL, MF_BYCOMMAND); if (uSelState == MF_GRAYED) { bSelectAll = TRUE; SelStart = SelEnd =0; }
//
// get pointer to edit control text to search
//
hEText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0, 0 ); if( !hEText ) // silently return if we can't get it
{ return( bStatus ); } pStart= LocalLock( hEText ); if( !pStart ) { return( bStatus ); }
if (fReverse) { // Get current line number
LineNum= (DWORD)SendMessage(hwndEdit, EM_LINEFROMCHAR, SelStart, 0); // Get index to start of the line
StartIndex= (DWORD)SendMessage(hwndEdit, EM_LINEINDEX, LineNum, 0); // Set upper limit for search text
EndIndex= SelStart; pMatch= NULL;
// Search line by line, from LineNum to 0
i = LineNum; while (TRUE) { pMatch= ReverseScan(pStart+StartIndex,pStart+EndIndex,szKey,fCase); if (pMatch) break; // current StartIndex is the upper limit for the next search
EndIndex= StartIndex;
if (i) { // Get start of the next line
i-- ; StartIndex = (DWORD)SendMessage(hwndEdit, EM_LINEINDEX, i, 0); } else break ; } } else { pMatch= ForwardScan(pStart+SelEnd, szKey, fCase); }
LocalUnlock(hEText);
if (pMatch == NULL) { //
// alert user on not finding any text unless it is replace all
//
if( !(FR.Flags & FR_REPLACEALL) ) { HANDLE hPrevCursor= SetCursor( hStdCursor ); AlertBox( hDlgFind ? hDlgFind : hwndNP, szNN, szCFS, szSearch, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION); SetCursor( hPrevCursor ); } } else { SelStart = (DWORD)(pMatch - pStart); SendMessage( hwndEdit, EM_SETSEL, SelStart, SelStart+lstrlen(szKey));
// since we are selecting the found text, enable SelectAll again.
if (bSelectAll) { EnableMenuItem(GetSubMenu(hMenu, 1), M_SELECTALL, MF_ENABLED); }
//
// show the selected text unless it is replace all
//
if( !(FR.Flags & FR_REPLACEALL) ) { SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0); } bStatus= TRUE; // found
}
return( bStatus ); }
// Recreate notepad edit window, get text from old window and put in new window.
// Called when user changes style from wrap on/off
//
// Called with the style of the new window
//
BOOL NpReCreate( long style ) { RECT rcT1; HWND hwndT1; HANDLE hT1; int cchTextNew; TCHAR* pchText; BOOL fWrapIsOn = ((style & WS_HSCROLL) != 0); HCURSOR hPrevCursor; BOOL bModified; // modify flag from old edit buffer
// if wordwrap, remove soft carriage returns
hPrevCursor= SetCursor( hWaitCursor ); // this may take some time...
if( fWrapIsOn ) { GotoAndScrollInView(1); // get around MLE bug
SendMessage(hwndEdit, EM_FMTLINES, FALSE, 0L); }
bModified= (SendMessage( hwndEdit, EM_GETMODIFY, 0,0 ) != 0);
cchTextNew= (int)SendMessage( hwndEdit, WM_GETTEXTLENGTH, 0, 0L ); hT1= LocalAlloc( LMEM_MOVEABLE, ByteCountOf(cchTextNew + 1) ); if( !hT1 ) { // failed, restore wordwrap; insert soft carriage returns
if( fWrapIsOn ) { SendMessage(hwndEdit, EM_FMTLINES, TRUE, 0L); } SetCursor( hPrevCursor ); return FALSE; }
GetClientRect( hwndNP, (LPRECT)&rcT1 );
//
// save the current edit control text.
//
pchText= LocalLock (hT1); SendMessage( hwndEdit, WM_GETTEXT, cchTextNew+1, (LPARAM)pchText ); hwndT1= CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("Edit"), TEXT(""), // pchText
style, 0, 0, rcT1.right, rcT1.bottom, hwndNP, (HMENU)ID_EDIT, hInstanceNP, NULL ); if( !hwndT1 ) { SetCursor( hPrevCursor ); if( fWrapIsOn ) // restore wordwrap
{ SendMessage( hwndEdit, EM_FMTLINES, TRUE, 0L ); } LocalUnlock(hT1); LocalFree(hT1); return FALSE; }
//
// The user can "add" styles to the edit window after it is
// created (like WS_EX_RTLREADING) when language packs are installed.
// Preserve these styles when changing the word wrap.
//
SetWindowLong( hwndT1 , GWL_EXSTYLE , GetWindowLong( hwndEdit , GWL_EXSTYLE )|WS_EX_CLIENTEDGE ) ;
// Set font before set text to save time calculating
SendMessage( hwndT1, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0) );
if (!SendMessage (hwndT1, WM_SETTEXT, 0, (LPARAM) pchText)) { SetCursor( hPrevCursor ); if( fWrapIsOn ) // restore wordwrap
{ SendMessage( hwndEdit, EM_FMTLINES, TRUE, 0L ); } DestroyWindow( hwndT1 ); LocalUnlock( hT1 ); LocalFree( hT1 ); return FALSE; } LocalUnlock(hT1);
DestroyWindow( hwndEdit ); // out with the old
hwndEdit = hwndT1; // in with the new
// free the earlier allocated memory in hEdit
if (hEdit) LocalFree(hEdit);
hEdit = hT1;
// limit text for safety's sake.
PostMessage( hwndEdit, EM_LIMITTEXT, (WPARAM)CCHNPMAX, 0L );
ShowWindow(hwndNP, SW_SHOW); SendMessage( hwndEdit, EM_SETMODIFY, bModified, 0L ); SetFocus(hwndEdit);
SetCursor( hPrevCursor ); // restore cursor
// redraw the status bar
if( fStatus ) { RECT rcClient; GetClientRect(hwndNP, &rcClient); NPSize(rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); ShowWindow( hwndStatus, SW_SHOW ); }
return TRUE; }
|