windows-nt/Source/XPSP1/NT/base/win32/fusion/tools/sxspad/sxspadmisc.c
2020-09-26 16:20:57 +08:00

361 lines
9.3 KiB
C

/*
* misc functions
* Copyright (C) 1984-2000 Microsoft Inc.
*/
#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(hwndSP);
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 : hwndSP,
szNN,
szCFS,
szSearch,
MB_APPLMODAL | MB_OK | MB_ICONASTERISK);
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 sxspad edit window, get text from old window and put in
new window. Called when user changes style from wrap on/off */
BOOL FAR NpReCreate( long style )
{
RECT rcT1;
HWND hwndT1;
HANDLE hT1;
int cchTextNew;
TCHAR* pchText;
BOOL fWrap = ((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 (!fWrap)
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, was wordwrap; insert soft carriage returns */
if (!fWrap)
SendMessage(hwndEdit, EM_FMTLINES, TRUE, 0L);
SetCursor( hPrevCursor );
return FALSE;
}
GetClientRect( hwndSP, (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,
hwndSP,
(HMENU)ID_EDIT,
hInstanceSP, NULL );
if( !hwndT1 )
{
SetCursor( hPrevCursor );
if (!fWrap)
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 (!fWrap)
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
/*
* Win32s does not support the EM_SETHANDLE message, so just do
* the assignment. hT1 already contains the edit control text.
*/
/* free the earlier allocated memory in hEdit */
if (hEdit)
LocalFree(hEdit);
hEdit = hT1;
/* limit text for safety's sake. */
PostMessage( hwndEdit, EM_LIMITTEXT, (WPARAM)CCHSPMAX, 0L );
ShowWindow(hwndSP, SW_SHOW);
SetTitle( fUntitled ? szUntitled : szFileName );
SendMessage( hwndEdit, EM_SETMODIFY, bModified, 0L );
SetFocus(hwndEdit);
SetCursor( hPrevCursor ); // restore cursor
return TRUE;
}