windows-nt/Source/XPSP1/NT/base/cluster/utils/cluslog/capplicationwindow.cpp

3155 lines
81 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// CApplicationWindow.CPP
//
// Application Window Class
//
#include "stdafx.h"
#include <commctrl.h>
#include <shellapi.h>
#include "commdlg.h"
#include "resource.h"
#include "CApplicationWindow.h"
#include "CFindDialog.h"
#define CAPPLICATIONWINDOWCLASS TEXT("CApplicationWindowClass")
#define WINDOWMENU 1
BOOL g_fCApplicationWindowClassRegistered = FALSE;
BOOL g_fCApplicationWindowDestroyed = FALSE;
// these are used to track the next occurrence of the phrases
LPTSTR g_pszDispatch;
LPTSTR g_pszDispatch2;
LPTSTR g_pszCompleted;
//
// Constructor
//
CApplicationWindow::CApplicationWindow( )
{
BOOL b;
LPTSTR psz;
LONG sx = GetSystemMetrics( SM_CXFULLSCREEN );
LPTSTR lpCmdLine;
Cleanup( TRUE );
if ( !g_fCApplicationWindowClassRegistered )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)CApplicationWindow::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_hInstance;
wcex.hIcon = LoadIcon(g_hInstance, (LPCTSTR) IDI_CLUSLOG );
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH) COLOR_GRAYTEXT; //NULL;
wcex.lpszMenuName = (LPCSTR)IDC_SOL;
wcex.lpszClassName = CAPPLICATIONWINDOWCLASS;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR) IDI_SMALL );
RegisterClassEx(&wcex);
}
HANDLE hFile;
hFile = CreateFile( "filter.txt",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( hFile != INVALID_HANDLE_VALUE )
{
LONG nLength = GetFileSize( hFile, NULL );
nLength++; // one for NULL
g_pszFilters = (LPTSTR) LocalAlloc( LPTR, nLength );
if ( g_pszFilters )
{
DWORD dwRead; // dummy
ReadFile( hFile, g_pszFilters, nLength, &dwRead, NULL );
g_pszFilters[nLength-1] = 0;
CloseHandle( hFile );
g_nComponentFilters = 0;
psz = g_pszFilters;
while ( psz < &g_pszFilters[nLength-1] )
{
LPTSTR pszStart = psz;
while ( *psz && *psz != 13 )
{
psz++;
}
psz += 2;
g_nComponentFilters++;
}
g_pfSelectedComponent = (BOOL*) LocalAlloc( LPTR, g_nComponentFilters * sizeof(BOOL) );
}
}
_hWnd = CreateWindowEx( WS_EX_ACCEPTFILES,
CAPPLICATIONWINDOWCLASS,
TEXT("Cluster Log Analyzer"),
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
g_hInstance,
(LPVOID) this);
if (!_hWnd)
{
return;
}
_hMenu = CreatePopupMenu( );
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING | MIIM_STATE | MIIM_ID;
mii.fState = MFS_CHECKED;
mii.wID = IDM_FIRST_CS_FILTER ;
psz = g_pszFilters;
if ( psz )
{
while ( *psz && mii.wID < IDM_LAST_CS_FILTER )
{
mii.dwTypeData = psz;
while ( *psz && *psz != 13 )
{
psz++;
}
if ( *psz == 13 )
{
*psz = 0;
psz++;
if ( *psz )
{
psz++;
}
}
mii.wID++;
mii.cch = (UINT)(psz - mii.dwTypeData);
b = InsertMenuItem( _hMenu, -1, TRUE, &mii );
}
}
HMENU hMenu = GetSubMenu( GetMenu( _hWnd ), 2 );
b = AppendMenu( hMenu, MF_POPUP, (UINT_PTR) _hMenu, "&Cluster Service" );
DrawMenuBar( _hWnd );
ShowWindow( _hWnd, SW_SHOW );
UpdateWindow( _hWnd );
lpCmdLine = GetCommandLine( );
if ( lpCmdLine )
{
if ( lpCmdLine[0] == '\"' )
{
lpCmdLine++;
while ( *lpCmdLine && *lpCmdLine != '\"' )
{
lpCmdLine++;
}
if ( *lpCmdLine )
{
lpCmdLine++;
}
if ( *lpCmdLine )
{
lpCmdLine++;
}
}
else
{
while ( *lpCmdLine && *lpCmdLine != 32 )
{
lpCmdLine++;
}
if ( *lpCmdLine )
{
lpCmdLine++;
}
}
while ( lpCmdLine[0] )
{
LPSTR psz = strchr( lpCmdLine, 32 );
if ( psz )
{
*psz = 0;
}
if ( lpCmdLine[1] != ':'
&& lpCmdLine[1] != '\\' )
{
LPTSTR pszFilename = (LPTSTR)
LocalAlloc( LMEM_FIXED, MAX_PATH * sizeof(TCHAR) );
if ( pszFilename )
{
DWORD dwRead;
dwRead = GetCurrentDirectory( MAX_PATH, pszFilename );
if ( dwRead >= MAX_PATH )
{
LocalFree( pszFilename );
pszFilename = (LPTSTR)
LocalAlloc( LMEM_FIXED,
( dwRead + MAX_PATH ) * sizeof(TCHAR) );
if ( pszFilename )
{
dwRead = GetCurrentDirectory( MAX_PATH, pszFilename );
}
}
if ( pszFilename
&& dwRead != 0 )
{
strcat( pszFilename, TEXT("\\") );
strcat( pszFilename, lpCmdLine );
_LoadFile( pszFilename );
}
}
else
{
break;
}
}
if ( *lpCmdLine )
{
_LoadFile( lpCmdLine );
}
lpCmdLine += lstrlen( lpCmdLine );
if ( psz )
{
lpCmdLine++;
*psz = 32;
}
}
}
}
//
// Destructor
//
CApplicationWindow::~CApplicationWindow( )
{
Cleanup( );
ShowWindow( _hWnd, SW_HIDE );
}
//
//
//
HRESULT
CApplicationWindow::Cleanup(
BOOL fInitializing // = FALSE
)
{
if ( !fInitializing )
{
for( ULONG nFile = 0; nFile < _nFiles; nFile++ )
{
LocalFree( _pFiles[ nFile ] );
LocalFree( _pszFilenames[ nFile ] );
LocalFree( _pNodes[ nFile ] );
}
}
_nFiles = 0;
_cTotalLineCount = 0;
_fVertSBVisible = FALSE;
_uStartSelection = 0;
_uEndSelection = 0;
_uPointer = 0;
_pLines = 0;
ZeroMemory( &_LineFinder, sizeof(_LineFinder) );
_uFinderLength = 0;
ShowScrollBar( _hWnd, SB_VERT, FALSE );
return S_OK;
}
//
// _CalculateOffset( )
//
HRESULT
CApplicationWindow::_CalculateOffset(
FILETIME * pftOper1,
FILETIME * pftOper2,
INT * pnDir,
FILETIME * pftOffset
)
{
*pnDir = CompareFileTime( pftOper1, pftOper2 );
if ( *pnDir > 0 )
{
pftOffset->dwHighDateTime = pftOper1->dwHighDateTime - pftOper2->dwHighDateTime;
pftOffset->dwLowDateTime = pftOper1->dwLowDateTime - pftOper2->dwLowDateTime;
if ( pftOper1->dwLowDateTime < pftOper2->dwLowDateTime )
{
pftOffset->dwHighDateTime++;
}
}
else if ( *pnDir < 0 )
{
pftOffset->dwHighDateTime = pftOper2->dwHighDateTime - pftOper1->dwHighDateTime;
pftOffset->dwLowDateTime = pftOper2->dwLowDateTime - pftOper1->dwLowDateTime;
if ( pftOper1->dwLowDateTime > pftOper2->dwLowDateTime )
{
pftOffset->dwHighDateTime--;
}
}
return S_OK;
}
//
// _FindSequencePoint( )
//
BOOL
CApplicationWindow::_FindSequencePoint(
LPTSTR * ppszSequence,
ULONG * pnSequence
)
{
while( *ppszSequence )
{
if ( *ppszSequence > g_pszDispatch )
{
g_pszDispatch = strstr( *ppszSequence, "dispatching seq " ) - 1;
}
if ( *ppszSequence > g_pszCompleted )
{
g_pszCompleted = strstr( *ppszSequence, "completed update seq " ) - 1;
}
if ( *ppszSequence > g_pszDispatch2 )
{
g_pszDispatch2 = strstr( *ppszSequence, "Dispatching seq " ) - 1;
}
if ( g_pszDispatch < g_pszCompleted )
{
(*ppszSequence) = g_pszDispatch + sizeof("dispatching seq ") - 1;
if ( pnSequence )
{
*pnSequence = atol ( *ppszSequence );
(*pnSequence) *= 3;
}
break;
}
if ( g_pszDispatch2 < g_pszCompleted )
{
(*ppszSequence) = g_pszDispatch2 + sizeof("Dispatching seq ") - 1;
if ( pnSequence )
{
*pnSequence = atol ( *ppszSequence );
(*pnSequence) *= 3;
(*pnSequence)++;
}
break;
}
if ( g_pszCompleted + 1 != NULL )
{
(*ppszSequence) = g_pszCompleted + sizeof("completed update seq ") - 1;
if ( pnSequence )
{
*pnSequence = atol ( *ppszSequence );
(*pnSequence) *= 3;
(*pnSequence)++;
(*pnSequence)++;
}
break;
}
*ppszSequence = NULL;
return FALSE;
}
return TRUE;
}
//
// _RetrieveTimeDate( )
//
HRESULT
CApplicationWindow::_RetrieveTimeDate(
LPTSTR pszCurrent,
SYSTEMTIME * pst,
LPTSTR * ppszFinal
)
{
if ( ppszFinal )
{
*ppszFinal = pszCurrent;
}
// Find the thread and process IDs
while ( *pszCurrent && *pszCurrent != ':' && *pszCurrent != 10 )
{
pszCurrent++;
}
if ( *pszCurrent != ':' )
return S_FALSE;
pszCurrent++;
if ( *pszCurrent != ':' )
return S_FALSE;
pszCurrent++;
// Find Time/Date stamp which is:
// ####/##/##-##:##:##.###<space>
pst->wYear = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent == '-' )
{
//
// The "year" we got above should really be the day.
// We'll replace the year with zero and the month with one.
//
pst->wDay = pst->wYear;
pst->wYear = 0;
pst->wMonth = 1;
goto SkipDate;
}
if ( *pszCurrent != '/' )
return S_FALSE;
pszCurrent++;
pst->wMonth = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent != '/' )
return S_FALSE;
pszCurrent++;
pst->wDay = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent != '-' )
return S_FALSE;
SkipDate:
pszCurrent++;
pst->wHour = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent != ':' )
return S_FALSE;
pszCurrent++;
pst->wMinute = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent != ':' )
return S_FALSE;
pszCurrent++;
pst->wSecond = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( *pszCurrent != '.' )
return S_FALSE;
pszCurrent++;
pst->wMilliseconds = (WORD) atol( pszCurrent );
while ( *pszCurrent >= '0' && *pszCurrent <= '9' )
{
pszCurrent++;
}
if ( ppszFinal )
{
*ppszFinal = pszCurrent;
}
return S_OK;
}
//
// _GetFilename( )
//
HRESULT
CApplicationWindow::_GetFilename(
LPTSTR pszFilename,
LPTSTR pszFilenameOut,
LONG * pcch
)
{
LONG cch = 0;
if ( g_fShowServerNames && pszFilename[ 0 ] == '\\' && pszFilename[ 1 ] == '\\' )
{
LPTSTR psz = &pszFilename[ 2 ];
while ( *psz && *psz != '\\' )
{
psz++;
cch++;
}
psz--;
cch += 2;
}
else if ( strchr( pszFilename, '\\' ) )
{
pszFilename = pszFilename + lstrlen( pszFilename );
while ( *pszFilename != '\\' )
{
pszFilename--;
cch++;
}
pszFilename++;
cch--;
}
else
{
cch = lstrlen( pszFilename );
}
if ( pszFilenameOut )
{
if ( !pcch )
return E_POINTER;
if ( cch >= *pcch )
{
cch = *pcch - 1;
}
strncpy( pszFilenameOut, pszFilename, cch );
pszFilenameOut[ cch ] = 0;
}
if ( pcch )
{
*pcch = cch;
}
return S_OK;
}
//
// _StatusWndProc( )
//
LRESULT CALLBACK
CApplicationWindow::_StatusWndProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
return 0;
}
//
// _CombineFiles( )
//
HRESULT
CApplicationWindow::_CombineFiles( )
{
HRESULT hr; // general purpose HRESULT and return code
BOOL b; // general purpose return BOOL
ULONG nFileLineCount; // counter of the lines in the file
ULONG nSequence; // ID of current sequence
ULONG nNextSequence; // ID of the next squence
LPTSTR pszSequence; // next sequence location
LPTSTR pszCurrent; // current parse location within file
BOOL fSyncPoint; // flag indicating a sync point was encountered
SYSTEMTIME st; // used to convert "line time" to a filetime.
FILETIME ft; // current lines filetime
FILETIME ftOffset; // current filetime offset
INT nDir; // offset direction
MSG msg; // message pumping
HWND hwndProcessing; // processing window handle
HWND hwndStatus; // progress bar window handle
SCROLLINFO si; // verticle scroll bar
LINEPOINTER * pLastSyncPoint; // last place a sync point in other files was encountered
LINEPOINTER * pInsertionPoint; // next place a node will be inserted
LINEPOINTER * pNewLine; // next structure to be used as a node
CWaitCursor Wait; // show the hour glass
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
GetScrollInfo( _hWnd, SB_VERT, &si );
si.fMask = SIF_RANGE;
ZeroMemory( &ftOffset, sizeof(ftOffset) );
nDir = 0;
g_pszDispatch = NULL;
g_pszDispatch2 = NULL;
g_pszCompleted = NULL;
// scan to figure out the line count of the new file
nFileLineCount = 0;
pszCurrent = _pFiles[ _nFiles ];
while ( *pszCurrent )
{
if ( *pszCurrent == 10 )
{
nFileLineCount++;
}
pszCurrent++;
}
if ( !_pLines )
{
// add one more for the root node
nFileLineCount++;
}
// allocate all the memory up front to avoid fragmenting memory as well as
// descreasing the number of heap calls
_pNodes[ _nFiles ] = (LINEPOINTER *) LocalAlloc( LMEM_FIXED, nFileLineCount * sizeof(LINEPOINTER) );
if ( !_pNodes[ _nFiles ] )
{
return E_OUTOFMEMORY;
}
pNewLine = _pNodes[ _nFiles ];
if ( !_pLines )
{
_pLines = pNewLine;
ZeroMemory( _pLines, sizeof(LINEPOINTER) );
pNewLine++;
}
// Create wait modeless dialog
hwndProcessing = CreateDialog( g_hInstance,
MAKEINTRESOURCE(IDD_PROCESSING),
_hWnd,
(DLGPROC) CApplicationWindow::_StatusWndProc );
hwndStatus = GetDlgItem( hwndProcessing, IDC_P_STATUS );
SendMessage( hwndStatus, PBM_SETRANGE32, 0, nFileLineCount );
SendMessage( hwndStatus, PBM_SETPOS, 0, 0 );
SendMessage( hwndStatus, PBM_SETSTEP, 1, 0 );
SetWindowText( GetDlgItem( hwndProcessing, IDC_S_FILENAME ), _pszFilenames[ _nFiles ] );
// Find the first sync point
nNextSequence = nSequence = 0;
pszSequence = _pFiles[ _nFiles ];
if ( _FindSequencePoint( &pszSequence, &nNextSequence ) )
{
RetrySequencing:
if ( _nFiles )
{
LINEPOINTER * lp = _pLines;
while ( lp->pNext
&& nNextSequence != lp->uSequenceNumber )
{
lp = lp->pNext;
// pump some messages....
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( !IsDialogMessage( g_hwndFind, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
if ( g_fCApplicationWindowDestroyed )
{
return E_FAIL; // not break!
}
}
}
if ( nNextSequence == lp->uSequenceNumber )
{
pszCurrent = pszSequence;
while( pszCurrent >= _pFiles[ _nFiles ] && *pszCurrent != 10 )
{
pszCurrent--;
}
pszCurrent++;
hr = _RetrieveTimeDate( pszCurrent, &st, NULL );
b = SystemTimeToFileTime( &st, &ft );
_CalculateOffset( &ft, &lp->Time, &nDir, &ftOffset );
nSequence = nNextSequence - 1;
}
else
{
if ( _FindSequencePoint( &pszSequence, &nNextSequence ) )
goto RetrySequencing;
nNextSequence = nSequence = 0;
}
}
else
{
nSequence = nNextSequence - 1;
}
}
nFileLineCount = 1;
pszCurrent = _pFiles[ _nFiles ];
pInsertionPoint = _pLines;
while ( *pszCurrent )
{
LPTSTR pszStart = pszCurrent;
// this will parse past the PID.TID and Time/Date
hr = _RetrieveTimeDate( pszCurrent, &st, &pszCurrent );
b = SystemTimeToFileTime( &st, &ft );
// skip spaces
while ( *pszCurrent == 32)
{
pszCurrent++;
}
// fill in preliminary info
pNewLine->fFiltered = FALSE;
pNewLine->nFile = _nFiles;
pNewLine->nLine = nFileLineCount;
pNewLine->psLine = pszStart;
// note warning level of line
//
if ( _stricmp( "INFO", pszCurrent ))
{
pNewLine->WarnLevel = WarnLevelInfo;
}
else if ( _stricmp( "WARN", pszCurrent ))
{
pNewLine->WarnLevel = WarnLevelWarn;
}
else if ( _stricmp( "ERR ", pszCurrent ))
{
pNewLine->WarnLevel = WarnLevelError;
}
else
{
pNewLine->WarnLevel = WarnLevelUnknown;
}
if ( pNewLine->WarnLevel != WarnLevelUnknown )
{
// skip chars, then spaces only if we found the tag
while ( *pszCurrent != 32)
{
pszCurrent++;
}
while ( *pszCurrent == 32)
{
pszCurrent++;
}
}
// [OPTIONAL] Cluster component which looks like:
// [<id...>]
if ( *pszCurrent == '[' )
{
LPTSTR pszComponentTag = pszCurrent;
while ( *pszCurrent && *pszCurrent != ']' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent < 32 )
{
pszCurrent = pszComponentTag;
goto NoComponentTryResouce;
}
pszCurrent++;
// found component
USHORT nFilterId = 0;
LONG nLen = (LONG)(pszCurrent - pszComponentTag - 2);
LPTSTR psz = g_pszFilters;
while ( nFilterId < g_nComponentFilters )
{
if ( nLen == lstrlen( psz )
&& _strnicmp( pszComponentTag + 1, psz, nLen ) == 0 )
{
pNewLine->nFilterId = nFilterId + 1;
if ( g_pfSelectedComponent[ nFilterId ] )
{
pNewLine->fFiltered = TRUE;
}
break;
}
while ( *psz )
{
psz++;
}
psz += 2;
nFilterId++;
}
}
else
{
// [OPTIONAL] If not a component, see if there is a res type
NoComponentTryResouce:
LPTSTR pszResType = pszCurrent;
while ( *pszCurrent && *pszCurrent != ':' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent >= 32 )
{
pszCurrent++;
// found a restype
pNewLine->nFilterId = g_nComponentFilters + 1; // TODO: make more dynamic
if ( g_fResourceNoise )
{
pNewLine->fFiltered = TRUE;
}
}
}
// Find the beggining of the next line
while ( *pszCurrent && *pszCurrent != 10 )
{
pszCurrent++;
}
if ( *pszCurrent )
{
pszCurrent++;
}
// See if we just past a sync point
if ( pszSequence && pszCurrent > pszSequence )
{
fSyncPoint = TRUE;
nSequence = nNextSequence;
// find the next sync point
_FindSequencePoint( &pszSequence, &nNextSequence );
if ( _nFiles )
{
// if we are out of sync, move the insertion point ahead
if ( pInsertionPoint->pNext != NULL
&& nSequence >= pInsertionPoint->uSequenceNumber )
{
for( pLastSyncPoint = pInsertionPoint; pLastSyncPoint->pNext; pLastSyncPoint = pLastSyncPoint->pNext )
{
if ( pLastSyncPoint->nFile != _nFiles
&& ( nSequence < pLastSyncPoint->uSequenceNumber
|| ( pLastSyncPoint->fSyncPoint
&& nSequence == pLastSyncPoint->uSequenceNumber ) ) )
{
break;
}
}
if ( pLastSyncPoint
&& pLastSyncPoint->pNext
&& nSequence == pLastSyncPoint->uSequenceNumber )
{
pInsertionPoint = pLastSyncPoint;
_CalculateOffset( &ft, &pInsertionPoint->Time, &nDir, &ftOffset );
}
}
}
}
else
{
fSyncPoint = FALSE;
}
// adjust time to compensate for time deviations
if ( nDir > 0 )
{ // if we are ahead, subtract
if ( ft.dwLowDateTime - ftOffset.dwLowDateTime > ft.dwLowDateTime )
{
ft.dwHighDateTime--;
}
ft.dwLowDateTime -= ftOffset.dwLowDateTime;
ft.dwHighDateTime -= ftOffset.dwHighDateTime;
}
else if ( nDir < 0 )
{ // if we are behind, add
if ( ft.dwLowDateTime + ftOffset.dwLowDateTime < ft.dwLowDateTime )
{
ft.dwHighDateTime++;
}
ft.dwLowDateTime += ftOffset.dwLowDateTime;
ft.dwHighDateTime += ftOffset.dwHighDateTime;
}
// else if nDir == 0, nothing to do
#if defined(_DEBUG) && defined(VERIFY_SYNC_POINTS)
if ( fSyncPoint && _nFiles != 0 )
{
INT n = CompareFileTime( &ft, &pInsertionPoint->Time );
if ( n != 0 )
{
DebugBreak( );
}
}
#endif // defined(_DEBUG) && defined(VERIFY_SYNC_POINTS)
// Find the place to insert it
while( pInsertionPoint->pNext )
{
if ( nSequence < pInsertionPoint->pNext->uSequenceNumber
&& pInsertionPoint->pNext->nFile != _nFiles )
{
break;
}
INT n = CompareFileTime( &ft, &pInsertionPoint->pNext->Time );
if ( n < 0 )
break;
pInsertionPoint = pInsertionPoint->pNext;
}
// fill-in rest of the LINEPOINTER structure
pNewLine->Time = ft;
pNewLine->fSyncPoint = fSyncPoint;
pNewLine->uSequenceNumber = nSequence;
// insert node into line list
pNewLine->pNext = pInsertionPoint->pNext;
pNewLine->pPrev = pInsertionPoint;
if ( pInsertionPoint->pNext != NULL )
{
pInsertionPoint->pNext->pPrev = pNewLine;
}
pInsertionPoint->pNext = pNewLine;
pInsertionPoint = pNewLine;
pNewLine++;
// dump line counts
nFileLineCount++;
_cTotalLineCount++;
// synchonize the scroll bar, don't redraw it
if ( _cTotalLineCount > 100 && _cTotalLineCount > si.nPage )
{
si.nMax = _cTotalLineCount;
SetScrollInfo( _hWnd, SB_VERT, &si, FALSE );
}
SendMessage( hwndStatus, PBM_STEPIT, 0, 0 );
#if defined(_DEBUG) && defined(SLOW_FILL)
if ( _nFiles )
{
InvalidateRect( _hWnd, NULL, TRUE );
for( ULONG a = 0; a < 999999 ; a++ )
{
#endif // defined(_DEBUG) && defined(SLOW_FILL)
// pump some messages....
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( !IsDialogMessage( g_hwndFind, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
if ( g_fCApplicationWindowDestroyed )
{
return E_FAIL; // not break!
}
}
#if defined(_DEBUG) && defined(SLOW_FILL)
}
}
#endif // defined(_DEBUG) && defined(SLOW_FILL)
}
DestroyWindow( hwndProcessing );
_nFiles++;
if ( !_fVertSBVisible
&& _yWindow < (LONG)(_cTotalLineCount * _tm.tmHeight) )
{
_fVertSBVisible = TRUE;
EnableScrollBar( _hWnd, SB_VERT, ESB_ENABLE_BOTH );
ShowScrollBar( _hWnd, SB_VERT, TRUE );
}
else if ( _fVertSBVisible
&& _yWindow >= (LONG)(_cTotalLineCount * _tm.tmHeight) )
{
_fVertSBVisible = FALSE;
//EnableScrollBar( _hWnd, SB_VERT, ESB_ENABLE_BOTH );
ShowScrollBar( _hWnd, SB_VERT, FALSE );
}
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE;
si.nMin = 0;
si.nMax = _cTotalLineCount;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
InvalidateRect( _hWnd, NULL, TRUE );
return S_OK;
}
//
// _LoadFile( )
//
HRESULT
CApplicationWindow::_LoadFile(
LPTSTR pszFilename )
{
HRESULT hr;
DWORD dwRead;
HANDLE hFile;
ULONG nLength;
LONG xMargin;
_pszFilenames[ _nFiles ] = (LPTSTR) LocalAlloc( LMEM_FIXED, ( lstrlen( pszFilename ) + 1 ) * sizeof(TCHAR) );
if ( !_pszFilenames[ _nFiles ] )
{
hr = E_OUTOFMEMORY;
goto Error;
}
strcpy( _pszFilenames[ _nFiles ], pszFilename );
_GetFilename( _pszFilenames[ _nFiles ], NULL, &xMargin );
xMargin += 7 + 2; // line number and file number
xMargin *= _xSpace;
if ( xMargin > _xMargin )
{
_xMargin = xMargin;
}
hFile = CreateFile( _pszFilenames[ _nFiles ],
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
hr = HRESULT_FROM_WIN32( GetLastError( ) );
goto Error;
}
nLength = GetFileSize( hFile, NULL );
if ( nLength == 0xFFFFffff && GetLastError( ) != NO_ERROR )
{
hr = HRESULT_FROM_WIN32( GetLastError( ) );
goto Error;
}
nLength++; // one for NULL
#if defined(_DEBUG)
_pFiles[ _nFiles ] = (LPTSTR) LocalAlloc( LPTR, nLength );
#else
_pFiles[ _nFiles ] = (LPTSTR) LocalAlloc( LMEM_FIXED, nLength );
#endif
if ( !_pFiles[ _nFiles ] )
{
hr = E_OUTOFMEMORY;
goto Error;
}
if ( !ReadFile( hFile, _pFiles[ _nFiles ], nLength, &dwRead, NULL ) )
{
hr = HRESULT_FROM_WIN32( GetLastError( ) );
goto Error;
}
hr = _CombineFiles( );
Cleanup:
if ( hFile != INVALID_HANDLE_VALUE )
CloseHandle( hFile );
return hr;
Error:
if ( _pFiles[ _nFiles ] )
{
LocalFree( _pFiles[ _nFiles ] );
_pFiles[ _nFiles ] = NULL;
}
MessageBox( _hWnd, pszFilename, TEXT("File Error"), MB_ICONEXCLAMATION | MB_OK );
goto Cleanup;
}
//
// _PaintLine( )
//
HRESULT
CApplicationWindow::_PaintLine(
PAINTSTRUCT * pps,
LINEPOINTER * pCurrent,
LONG wxStart,
LONG wy,
COLORREF crText,
COLORREF crDark,
COLORREF crNormal,
COLORREF crHightlite
)
{
LPTSTR pszStartLine; // beginning of line (PID/TID)
LPTSTR pszStartTimeDate; // beginning of time/data stamp
LPTSTR pszStartComponent; // beginning of component name
LPTSTR pszStartResType; // beginning of a resource component
LPTSTR pszStartText; // beginning of text
LPTSTR pszCurrent; // current position and beginning of text
TCHAR szFilename[ 40 ];
LONG cchFilename;
SIZE size;
RECT rect;
RECT rectResult;
LONG wx = wxStart;
LONG wxTextStart;
if ( pCurrent->psLine )
{
pszCurrent = pCurrent->psLine;
// draw node number
SetRect( &rect,
wx,
wy,
wx + _xSpace * 2,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
TCHAR szBuf[ 2 ];
SetBkColor( pps->hdc, GetSysColor( COLOR_WINDOW ) );
SetTextColor( pps->hdc, GetSysColor( COLOR_WINDOWTEXT ) );
DrawText( pps->hdc,
szBuf,
wsprintf( szBuf, TEXT("%1u "), pCurrent->nFile ),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += 2 * _xSpace;
// Draw Filename
cchFilename = sizeof(szFilename)/sizeof(szFilename[0]);
_GetFilename( _pszFilenames[ pCurrent->nFile ], szFilename, &cchFilename );
SetRect( &rect,
wx,
wy,
_xMargin,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
HBRUSH hBrush;
hBrush = CreateSolidBrush( crNormal );
FillRect( pps->hdc, &rect, hBrush );
DeleteObject( hBrush );
DrawText( pps->hdc,
szFilename,
cchFilename,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += _xMargin - ( 7 * _xSpace - 2 * _xSpace );
// draw line number
SetRect( &rect,
wx,
wy,
wx + 7 * _xSpace,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
TCHAR szBuf[ 8 ];
SetTextColor( pps->hdc, crText );
SetBkColor( pps->hdc, crDark );
DrawText( pps->hdc,
szBuf,
wsprintf( szBuf, TEXT("%07.7u"), pCurrent->nLine ),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += 7 * _xSpace;
SetRect( &rect,
wx,
wy,
wx + _xSpace,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
" ",
1,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += _xSpace;
//
// KB: This is what a typical cluster log line looks like.
// 000003fc.00000268::1999/07/19-19:14:45.548 [EVT] Node up: 2, new UpNodeSet: 0002
// 000003fc.00000268::1999/07/19-19:14:45.548 [EVT] EvOnline : calling ElfRegisterClusterSvc
// 000003fc.00000268::1999/07/19-19:14:45.548 [GUM] GumSendUpdate: queuing update type 2 context 19
// 000003fc.00000268::1999/07/19-19:14:45.548 [GUM] GumSendUpdate: Dispatching seq 2585 type 2 context 19 to node 1
// 000003fc.00000268::1999/07/19-19:14:45.548 [NM] Received update to set extended state for node 1 to 0
// 000003fc.00000268::1999/07/19-19:14:45.548 [NM] Issuing event 0.
// 000003fc.00000268::1999/07/19-19:14:45.548 [GUM] GumSendUpdate: completed update seq 2585 type 2 context 19
// 0000037c.000003a0::1999/07/19-19:14:45.548 Physical Disk: AddVolume : \\?\Volume{99d8d508-39fa-11d3-a200-806d6172696f}\ 'C', 7 (11041600)
// 0000037c.000003a0::1999/07/19-19:14:45.558 Physical Disk: AddVolume: GetPartitionInfo(\??\Volume{99d8d503-39fa-11d3-a200-806d6172696f}), error 170
// 0000037c.000003a0::1999/07/19-19:14:45.568 Physical Disk: AddVolume: GetPartitionInfo(\??\Volume{99d8d504-39fa-11d3-a200-806d6172696f}), error 170
// 0000037c.000003a0::1999/07/19-19:14:45.568 Physical Disk: AddVolume: GetPartitionInfo(\??\Volume{99d8d505-39fa-11d3-a200-806d6172696f}), error 170
// 0000037c.000003a0::1999/07/19-19:14:45.578 Physical Disk: AddVolume: GetPartitionInfo(\??\Volume{99d8d506-39fa-11d3-a200-806d6172696f}), error 170
// 0000037c.000003a0::1999/07/19-19:14:45.578 Physical Disk: AddVolume: GetPartitionInfo(\??\Volume{99d8d501-39fa-11d3-a200-806d6172696f}), error 1
//
pszStartResType =
pszStartComponent = NULL;
pszStartLine =
pszStartText =
pszStartTimeDate =
pszCurrent = pCurrent->psLine;
// Find the thread and process IDs
while ( *pszCurrent && *pszCurrent != ':' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent < 32 )
{
goto DrawRestOfLine;
}
pszCurrent++;
if ( *pszCurrent != ':' )
{
goto DrawRestOfLine;
}
pszCurrent++;
// Find Time/Date stamp which is:
// ####/##/##-##:##:##.###<space>
pszStartTimeDate = pszCurrent;
while ( *pszCurrent && *pszCurrent != ' ' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent < 32 )
{
goto DrawRestOfLine;
}
pszCurrent++;
if ( pCurrent->WarnLevel != WarnLevelUnknown )
{
// skip warn/info/err tag
//
while ( *pszCurrent != 32)
{
pszCurrent++;
}
while ( *pszCurrent == 32)
{
pszCurrent++;
}
}
pszStartText = pszCurrent;
// [OPTIONAL] Cluster component which looks like:
// [<id...>]
if ( *pszCurrent == '[' )
{
while ( *pszCurrent && *pszCurrent != ']' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent < 32 )
{
goto NoComponentTryResouce;
}
pszCurrent++;
pszStartComponent = pszStartText;
pszStartText = pszCurrent;
}
else
{
// [OPTIONAL] If not a component, see if there is a res type
NoComponentTryResouce:
pszCurrent = pszStartText;
while ( *pszCurrent && *pszCurrent != ':' && *pszCurrent >= 32 )
{
pszCurrent++;
}
if ( *pszCurrent >= 32 )
{
pszCurrent++;
pszStartResType = pszStartText;
pszStartText = pszCurrent;
}
}
// Draw PID and TID
GetTextExtentPoint32( pps->hdc,
pszStartLine,
(int)(pszStartTimeDate - pszStartLine - 2),
&size );
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
pszStartLine,
(int)(pszStartTimeDate - pszStartLine - 2),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += size.cx;
GetTextExtentPoint32( pps->hdc,
"::",
2,
&size );
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
"::",
2,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += size.cx;
// Draw Time/Date
pszCurrent = ( pszStartComponent ?
pszStartComponent :
( pszStartResType ?
pszStartResType :
pszStartText )
) - 1;
GetTextExtentPoint32( pps->hdc,
pszStartTimeDate,
(int)(pszCurrent - pszStartTimeDate),
&size );
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crDark );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
pszStartTimeDate,
(int)(pszCurrent - pszStartTimeDate),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += size.cx;
SetRect( &rect,
wx,
wy,
wx + _xSpace,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
" ",
1,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += _xSpace;
#ifdef _DEBUG
// draw sequence number
SetRect( &rect,
wx,
wy,
wx + 7 * _xSpace,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
TCHAR szBuf[ 8 ];
SetTextColor( pps->hdc, crText );
SetBkColor( pps->hdc, crNormal );
DrawText( pps->hdc,
szBuf,
wsprintf( szBuf, TEXT("#%7u%s"),
pCurrent->uSequenceNumber,// / 2,
pCurrent->fSyncPoint ? "*" : " " ),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += 9 * _xSpace;
#endif
// Draw component
if ( pszStartComponent )
{
SetRect( &rect,
wx,
wy,
wx + 10 * _xSpace,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
" ",
10,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
GetTextExtentPoint32( pps->hdc,
pszStartComponent,
(int)(pszStartText - pszStartComponent),
&size );
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
pszStartComponent,
(int)(pszStartText - pszStartComponent),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += 10 * _xSpace;
}
if ( pszStartResType )
{
GetTextExtentPoint32( pps->hdc,
pszStartResType,
(int)(pszStartText - pszStartResType),
&size );
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
DrawText( pps->hdc,
pszStartResType,
(int)(pszStartText - pszStartResType),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
wx += size.cx;
}
DrawRestOfLine:
pszCurrent = pszStartText;
wxTextStart = wx;
while ( *pszCurrent && *pszCurrent != 13 )
{
pszCurrent++;
}
SetRect( &rect,
wx,
wy,
_xWindow,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
HBRUSH hBrush;
hBrush = CreateSolidBrush( crNormal );
FillRect( pps->hdc, &rect, hBrush );
DeleteObject( hBrush );
DrawText( pps->hdc,
pszStartText,
(int)(pszCurrent - pszStartText),
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_EXPANDTABS );
}
// See if "Finder" needs to paint on this line
if ( pCurrent->nFile == _LineFinder.nFile
&& pCurrent->nLine == _LineFinder.nLine )
{
wx = wxTextStart;
if ( pszStartResType )
{
GetTextExtentPoint32( pps->hdc,
pszStartResType,
(int)(_LineFinder.psLine - pszStartResType),
&size );
wx += size.cx;
}
else
{
GetTextExtentPoint32( pps->hdc,
pszStartText,
(int)(_LineFinder.psLine - pszStartText),
&size );
wx += size.cx;
}
GetTextExtentPoint32( pps->hdc,
_LineFinder.psLine,
_uFinderLength,
&size
);
SetRect( &rect,
wx,
wy,
wx + size.cx,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crHightlite );
SetTextColor( pps->hdc, ~crHightlite );
DrawText( pps->hdc,
_LineFinder.psLine,
_uFinderLength,
&rect,
DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE );
}
}
wx = _xWindow;
}
// fill in the rest of the line
SetRect( &rect,
wx,
wy,
_xWindow,
wy + _tm.tmHeight );
if ( IntersectRect( &rectResult, &pps->rcPaint, &rect ) )
{
SetBkColor( pps->hdc, crNormal );
SetTextColor( pps->hdc, crText );
HBRUSH hBrush;
hBrush = CreateSolidBrush( crNormal );
FillRect( pps->hdc, &rect, hBrush );
DeleteObject( hBrush );
}
return S_OK;
}
//
// _OnPaint( )
//
LRESULT
CApplicationWindow::_OnPaint(
WPARAM wParam,
LPARAM lParam )
{
HDC hdc;
LONG wxStart;
LONG wy;
RECT rect;
RECT rectResult;
ULONG nLineCount;
LINEPOINTER * pCurrent;
SCROLLINFO si;
PAINTSTRUCT ps;
static COLORREF crBkColor[ MAX_OPEN_FILES ] = {
0xFFE0E0,
0xE0FFE0,
0xE0E0FF,
0xFFFFE0,
0xE0FFFF,
0xFFE0FF,
0xE0E0E0,
0xC0C0C0,
0x909090,
0x000000
};
static COLORREF crBkColorDarker[ MAX_OPEN_FILES ] = {
0xFFC0C0,
0xC0FFC0,
0xC0C0FF,
0xFFFFC0,
0xC0FFFF,
0xFFC0FF,
0xC0C0C0,
0xA0A0A0,
0x707070,
0x101010
};
static COLORREF crBkColorHighlite[ MAX_OPEN_FILES ] = {
0xFF0000,
0x00FF00,
0x0000FF,
0xFFFF00,
0x00FFFF,
0xFF00FF,
0x101010,
0x404040,
0x606060,
0xFFFFFF
};
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo( _hWnd, SB_HORZ, &si );
wxStart = si.nPos;
si.cbSize = sizeof(si);
si.fMask = SIF_POS | SIF_PAGE;
GetScrollInfo( _hWnd, SB_VERT, &si );
hdc = BeginPaint( _hWnd, &ps);
if ( !_pLines )
goto EndPaint;
SetBkMode( hdc, OPAQUE );
SelectObject( hdc, g_hFont );
nLineCount = 0;
pCurrent = _pLines;
while ( pCurrent && nLineCount < (ULONG) si.nPos )
{
if ( !pCurrent->fFiltered )
{
nLineCount++;
}
pCurrent = pCurrent->pNext;
}
wy = 0;
while ( pCurrent
&& nLineCount <= si.nPos + si.nPage + 1 )
{
// ignore filtered lines
if ( pCurrent->fFiltered )
{
pCurrent = pCurrent->pNext;
continue;
}
if ( nLineCount >= _uStartSelection
&& nLineCount <= _uEndSelection )
{
_PaintLine( &ps,
pCurrent,
-wxStart,
wy,
GetSysColor( COLOR_WINDOWTEXT ),
crBkColorHighlite[ pCurrent->nFile ],
crBkColorHighlite[ pCurrent->nFile ],
crBkColorDarker[ pCurrent->nFile ]
);
}
else
{
_PaintLine( &ps,
pCurrent,
-wxStart,
wy,
GetSysColor( COLOR_WINDOWTEXT ),
crBkColorDarker[ pCurrent->nFile ],
crBkColor[ pCurrent->nFile ],
crBkColorHighlite[ pCurrent->nFile ]
);
}
wy += _tm.tmHeight;
nLineCount++;
pCurrent = pCurrent->pNext;
}
// Fill the rest with normal background color
SetRect( &rect,
0,
wy,
_xWindow,
_yWindow );
if ( IntersectRect( &rectResult, &ps.rcPaint, &rect ) )
{
HBRUSH hBrush;
hBrush = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
FillRect( hdc, &rect, hBrush );
DeleteObject( hBrush );
}
EndPaint:
EndPaint(_hWnd, &ps);
return 0;
}
//
// _FindNext( )
//
LRESULT
CApplicationWindow::_FindNext(
WPARAM wParam,
LPARAM lParam
)
{
SCROLLINFO si;
LPTSTR pszSearch;
LPTSTR psz;
ULONG n; // general counter
LPTSTR pszSearchString = (LPTSTR) lParam; // NEEDS TO BE FREEd!!!
WPARAM wFlags = wParam;
CWaitCursor Wait;
_uFinderLength = lstrlen( pszSearchString );
if( wFlags & FIND_UP )
{
//
// TODO: Make a better "up" search
//
if ( _LineFinder.pPrev )
{
CopyMemory( &_LineFinder, _LineFinder.pPrev, sizeof(LINEPOINTER) );
}
else
{
LINEPOINTER * lpLast;
LINEPOINTER * lp = _pLines;
while( lp )
{
lpLast = lp;
lp = lp->pNext;
}
CopyMemory( &_LineFinder, lpLast, sizeof(LINEPOINTER) );
}
}
else // find down
{
if ( _LineFinder.psLine )
{
// see if there is another instance on the same line
psz = _LineFinder.psLine;
for( n = 0; n < _uFinderLength; n++ )
{
if ( !*psz || *psz == 10 )
break;
psz++;
}
if ( *psz && *psz != 10 )
goto ResumeSearch;
}
}
if ( _LineFinder.psLine == NULL )
{
CopyMemory( &_LineFinder, _pLines->pNext, sizeof(LINEPOINTER) );
}
for(;;)
{
psz = _LineFinder.psLine;
if ( !psz )
break;
// skip PID/TID and time/date
while ( *psz && *psz != 10 )
{
if ( *psz == ':' )
{
psz++;
if ( *psz == ':' )
{
break;
}
}
psz++;
}
while ( *psz && *psz != 10 )
{
if ( *psz == 32 )
{
psz++;
break;
}
psz++;
}
if ( _LineFinder.WarnLevel != WarnLevelUnknown )
{
// skip info/warn/err tag
while ( *psz != 32)
{
psz++;
}
while ( *psz == 32)
{
psz++;
}
}
// skip components
if ( *psz == '[' )
{
while ( *psz && *psz != ']' )
{
psz++;
}
}
if ( *psz == 10 )
goto NextLine;
if ( !*psz )
break;
ResumeSearch:
pszSearch = pszSearchString;
while ( *psz != 10 )
{
if ( ( wFlags & FIND_MATCHCASE )
&& *psz != *pszSearch )
{
goto ResetMatch;
}
if ( toupper( *psz ) == toupper( *pszSearch ) )
{
pszSearch++;
if ( !*pszSearch )
{
ULONG cLine;
LINEPOINTER * lp;
if ( wFlags & FIND_WHOLE_WORD
&& isalnum( psz[ 1 ] ) )
{
psz++; // need to bump
goto ResetMatch;
}
_LineFinder.psLine = psz - _uFinderLength + 1;
// find the line
lp = _pLines;
cLine = 0;
while( lp )
{
if ( lp->nFile == _LineFinder.nFile
&& lp->nLine == _LineFinder.nLine )
{
break;
}
if ( !lp->fFiltered )
{
cLine++;
}
lp = lp->pNext;
}
_uPointer = _uStartSelection = _uEndSelection = cLine;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE;
GetScrollInfo( _hWnd, SB_VERT, &si );
si.fMask = SIF_POS;
si.nPos = cLine - si.nPage / 2;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
InvalidateRect( _hWnd, NULL, FALSE );
LocalFree( pszSearchString );
return 1;
}
}
else
{
ResetMatch:
psz -= ( pszSearch - pszSearchString );
pszSearch = pszSearchString;
}
if ( !*psz )
break;
psz++;
}
NextLine:
if ( wFlags & FIND_UP )
{
if ( _LineFinder.pPrev != NULL )
{
CopyMemory( &_LineFinder, _LineFinder.pPrev, sizeof(LINEPOINTER) );
}
else
{
break; // end of search
}
}
else // find down
{
if ( _LineFinder.pNext != NULL )
{
CopyMemory( &_LineFinder, _LineFinder.pNext, sizeof(LINEPOINTER) );
}
else
{
break; // end of search
}
}
}
// not found
ZeroMemory( &_LineFinder, sizeof(LINEPOINTER) );
if ( wFlags & FIND_UP )
{
_LineFinder.nLine = 0;
}
else
{
_LineFinder.nLine = _cTotalLineCount;
}
LocalFree( pszSearchString );
return 0;
}
//
// _MarkAll( )
//
LRESULT
CApplicationWindow::_MarkAll(
WPARAM wParam,
LPARAM lParam
)
{
WPARAM wFlags = wParam;
LPTSTR pszSearchString = (LPTSTR) lParam;
LocalFree( pszSearchString );
return 0;
}
//
// _OnSize( )
//
LRESULT
CApplicationWindow::_OnSize(
LPARAM lParam )
{
HDC hdc;
SIZE size;
HGDIOBJ hObj;
TCHAR szSpace[ 1 ] = { TEXT(' ') };
SCROLLINFO si;
_xWindow = LOWORD( lParam );
_yWindow = HIWORD( lParam );
hdc = GetDC( _hWnd );
hObj = SelectObject( hdc, g_hFont );
GetTextMetrics( hdc, &_tm );
GetTextExtentPoint32( hdc, szSpace, 1, &size );
_xSpace = size.cx;
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = _cTotalLineCount;
si.nPage = _yWindow / _tm.tmHeight;
SetScrollInfo( _hWnd, SB_VERT, &si, FALSE );
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = 1000;
si.nPage = _xWindow / _tm.tmHeight;
SetScrollInfo( _hWnd, SB_HORZ, &si, FALSE );
// cleanup the HDC
SelectObject( hdc, hObj );
ReleaseDC( _hWnd, hdc );
return 0;
}
//
// _OnMouseWheel( )
//
LRESULT
CApplicationWindow::_OnMouseWheel( SHORT iDelta )
{
if ( iDelta > 0 )
{
SendMessage( _hWnd, WM_VSCROLL, SB_LINEUP, 0 );
SendMessage( _hWnd, WM_VSCROLL, SB_LINEUP, 0 );
SendMessage( _hWnd, WM_VSCROLL, SB_LINEUP, 0 );
}
else if ( iDelta < 0 )
{
SendMessage( _hWnd, WM_VSCROLL, SB_LINEDOWN, 0 );
SendMessage( _hWnd, WM_VSCROLL, SB_LINEDOWN, 0 );
SendMessage( _hWnd, WM_VSCROLL, SB_LINEDOWN, 0 );
}
return 0;
}
//
// _OnVerticalScroll( )
//
LRESULT
CApplicationWindow::_OnVerticalScroll(
WPARAM wParam,
LPARAM lParam )
{
SCROLLINFO si;
RECT rect;
INT nScrollCode = LOWORD(wParam); // scroll bar value
INT nPos;
//INT nPos = HIWORD(wParam); // scroll box position
//HWND hwndScrollBar = (HWND) lParam; // handle to scroll bar
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo( _hWnd, SB_VERT, &si );
nPos = si.nPos;
switch( nScrollCode )
{
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_THUMBPOSITION:
si.nPos = nPos;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_LINEDOWN:
si.nPos += 1;
break;
case SB_LINEUP:
si.nPos -= 1;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
InvalidateRect( _hWnd, NULL, FALSE );
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
InvalidateRect( _hWnd, NULL, FALSE );
break;
}
si.fMask = SIF_POS;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
GetScrollInfo( _hWnd, SB_VERT, &si );
if ( si.nPos != nPos )
{
ScrollWindowEx( _hWnd,
0,
(nPos - si.nPos) * _tm.tmHeight,
NULL,
NULL,
NULL,
NULL,
SW_INVALIDATE );
SetRect( &rect, 0, ( _uPointer - si.nPos - 1 ) * _tm.tmHeight, _xWindow, ( _uPointer - si.nPos + 2 ) * _tm.tmHeight );
InvalidateRect( _hWnd, &rect, FALSE );
}
return 0;
}
//
// _OnHorizontalScroll( )
//
LRESULT
CApplicationWindow::_OnHorizontalScroll(
WPARAM wParam,
LPARAM lParam )
{
SCROLLINFO si;
INT nScrollCode = LOWORD(wParam); // scroll bar value
INT nPos;
//INT nPos = HIWORD(wParam); // scroll box position
//HWND hwndScrollBar = (HWND) lParam; // handle to scroll bar
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo( _hWnd, SB_HORZ, &si );
nPos = si.nPos;
switch( nScrollCode )
{
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_THUMBPOSITION:
si.nPos = nPos;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_LINEDOWN:
si.nPos += 1;
break;
case SB_LINEUP:
si.nPos -= 1;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
}
si.fMask = SIF_POS;
SetScrollInfo( _hWnd, SB_HORZ, &si, TRUE );
GetScrollInfo( _hWnd, SB_HORZ, &si );
if ( si.nPos != nPos )
{
ScrollWindowEx( _hWnd,
(nPos - si.nPos),
0,
NULL,
NULL,
NULL,
NULL,
SW_INVALIDATE );
}
return 0;
}
//
// _FillClipboard( )
//
HRESULT
CApplicationWindow::_FillClipboard( )
{
HANDLE hClip;
LPTSTR pszClip;
LPTSTR psz;
ULONG dwSize;
ULONG nLine;
TCHAR szFilename[ 40 ];
LONG cchFilename;
LINEPOINTER * pCurLine;
LINEPOINTER * pSelectionStart;
LONG cchMargin = ( _xMargin / _xSpace ) + 2;
//0 cluster1.log 0000006 5c4.57c::1999/07/26-21:56:24.682 [EP] Initialization...
static TCHAR szHeader[] = " Log/Nodename";
static TCHAR szHeader2[] = "Line### PIDxxxxx.TIDxxxxx Year/MM/DD-HH-MM-SS.HsS Log Entry\n\n";
if ( cchMargin < sizeof(szHeader) + 8 )
{
cchMargin = sizeof(szHeader) + 8;
}
//
// Find the start of the line
//
pSelectionStart = _pLines;
for( nLine = 0; nLine < _uStartSelection; nLine++ )
{
pSelectionStart = pSelectionStart->pNext;
}
//
// Tally up the line sizes
//
dwSize = cchMargin - 8;
dwSize += sizeof(szHeader2) - 1;
pCurLine = pSelectionStart;
for( ; nLine <= _uEndSelection; nLine++ )
{
psz = pCurLine->psLine;
if ( psz == NULL )
break;
while( *psz && *psz != 10 )
{
psz++;
}
if ( *psz )
{
psz++; // inlude LF
}
dwSize += (ULONG)(psz - pCurLine->psLine);
pCurLine = pCurLine->pNext;
}
// Add file and line number for every line
dwSize += ( _uEndSelection - _uStartSelection + 1 ) * cchMargin;
dwSize++; // add one for NULL terminator
hClip = (LPTSTR) GlobalAlloc( LMEM_MOVEABLE | GMEM_DDESHARE, dwSize * sizeof(*pszClip) );
if ( !hClip )
return E_OUTOFMEMORY;
pszClip = (LPTSTR) GlobalLock( hClip );
for ( LONG n = 0; n < cchMargin; n++ )
{
pszClip[ n ] = 32;
}
CopyMemory( pszClip, szHeader, sizeof(szHeader) - 1 );
pszClip += cchMargin - 8;
CopyMemory( pszClip, szHeader2, sizeof(szHeader2) - 1 );
pszClip += sizeof(szHeader2) - 1;
pCurLine = pSelectionStart;
for( nLine = _uStartSelection; nLine <= _uEndSelection; nLine++ )
{
for ( LONG n = 0; n < cchMargin; n++ )
{
pszClip[ n ] = 32;
}
// file number
_snprintf( pszClip, 1, "%1u", pCurLine->nFile );
pszClip += 2;
// filename
cchFilename = cchMargin - 10;
_GetFilename( _pszFilenames[ pCurLine->nFile ], szFilename, &cchFilename );
_snprintf( pszClip, cchFilename, "%s", szFilename );
pszClip += cchMargin - 10;
// line number
_snprintf( pszClip, 7, "%07.7u", pCurLine->nLine );
pszClip += 7;
pszClip++;
psz = pCurLine->psLine;
if ( psz == NULL )
break;
while( *psz && *psz != 10 )
{
psz++;
}
if ( *psz )
{
psz++; // inlude LF
}
CopyMemory( pszClip, pCurLine->psLine, psz - pCurLine->psLine );
pszClip += psz - pCurLine->psLine;
pCurLine = pCurLine->pNext;
}
*pszClip = 0; // terminate
GlobalUnlock( hClip );
if ( OpenClipboard( _hWnd ) )
{
SetClipboardData( CF_TEXT, hClip );
CloseClipboard( );
}
return S_OK;
}
//
// _ApplyFilters( )
//
HRESULT
CApplicationWindow::_ApplyFilters( )
{
SCROLLINFO si;
ULONG nLineCount = 0;
LINEPOINTER * lp = _pLines;
while( lp )
{
lp->fFiltered = FALSE;
if ( lp->nFilterId == g_nComponentFilters + 1 )
{
if ( g_fResourceNoise )
{
lp->fFiltered = TRUE;
}
}
else if ( lp->nFilterId !=0
&& lp->nFilterId <= g_nComponentFilters )
{
if ( g_pfSelectedComponent[ lp->nFilterId - 1 ] )
{
lp->fFiltered = TRUE;
}
}
if ( ! lp->fFiltered )
{
nLineCount++;
}
lp = lp->pNext;
}
InvalidateRect( _hWnd, NULL, FALSE );
// Update scroll bar
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE;
GetScrollInfo( _hWnd, SB_VERT, &si );
si.nMax = nLineCount;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
return S_OK;
}
//
// _OnCommand( )
//
LRESULT
CApplicationWindow::_OnCommand(
WPARAM wParam,
LPARAM lParam )
{
INT wmId = LOWORD(wParam);
INT wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox( g_hInstance, (LPCTSTR)IDD_ABOUTBOX, _hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
{
DestroyWindow( _hWnd );
}
break;
case IDM_FILE_REFRESH:
{
ULONG n;
ULONG nFiles = _nFiles;
LPTSTR pszFilenames[ MAX_OPEN_FILES ];
for( n = 0; n < nFiles; n++ )
{
pszFilenames[ n ] = _pszFilenames[ n ];
_pszFilenames[ n ] = NULL;
}
Cleanup( );
for( n = 0; n < nFiles; n++ )
{
_LoadFile( pszFilenames[ n ] );
LocalFree( pszFilenames[ n ] );
}
}
break;
case IDM_NEW_FILE:
{
Cleanup( );
InvalidateRect( _hWnd, NULL, TRUE );
}
break;
case IDM_OPEN_FILE:
{
LPTSTR psz;
TCHAR szFilters[ MAX_PATH ];
TCHAR szFilename[ MAX_PATH ];
LPTSTR pszFilenameBuffer
= (LPTSTR) LocalAlloc( LPTR, 8 * MAX_PATH );
ZeroMemory( szFilters, sizeof(szFilters) );
ZeroMemory( _szOpenFileNameFilter, sizeof(_szOpenFileNameFilter) );
LoadString( g_hInstance, IDS_OPEN_FILE_FILTERS, szFilters, MAX_PATH );
for ( psz = szFilters; *psz; psz++ )
{
if ( *psz == TEXT(',') )
{
*psz = TEXT('\0');
}
}
OPENFILENAME ofn;
ZeroMemory( &ofn, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = _hWnd;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilters;
// ofn.lpfnHook = NULL;
ofn.Flags = OFN_ENABLESIZING
| OFN_FILEMUSTEXIST
| OFN_EXPLORER
| OFN_ALLOWMULTISELECT;
// ofn.lCustData = 0;
ofn.lpstrCustomFilter = _szOpenFileNameFilter;
// ofn.lpstrDefExt = NULL;
ofn.lpstrFile = pszFilenameBuffer;
// ofn.lpstrFileTitle = NULL;
// ofn.lpstrInitialDir = NULL;
// ofn.lpstrTitle = NULL;
// ofn.lpTemplateName = NULL;
// ofn.nFileExtension = 0;
// ofn.nFileOffset = 0;
// ofn.nFilterIndex = 1;
ofn.nMaxCustFilter = MAX_PATH;
ofn.nMaxFile = 8 * MAX_PATH;
// ofn.nMaxFileTitle = 0;
if ( GetOpenFileName( &ofn ) )
{
LPTSTR pszFilename = pszFilenameBuffer + ofn.nFileOffset;
strcpy( szFilename, pszFilenameBuffer );
szFilename[ ofn.nFileOffset - 1] = '\\';
while ( *pszFilename )
{
strcpy( &szFilename[ ofn.nFileOffset ], pszFilename );
_LoadFile( szFilename );
pszFilename += lstrlen( pszFilename ) + 1;
}
}
else
{
DWORD dwErr = GetLastError( );
}
LocalFree( pszFilenameBuffer );
}
break;
case IDM_ALL_ON:
{
ULONG nItems = GetMenuItemCount( _hMenu );
for( ULONG n = 0; n < nItems; n++ )
{
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fState = MFS_CHECKED;
SetMenuItemInfo( _hMenu, n, TRUE, &mii );
g_pfSelectedComponent[ n ] = FALSE;
}
LINEPOINTER * lp = _pLines;
while( lp )
{
lp->fFiltered = FALSE;
lp = lp->pNext;
}
_ApplyFilters( );
}
break;
case IDM_EDIT_COPY:
{
_FillClipboard( );
}
break;
case IDM_FILTER_SHOWSERVERNAME:
{
HMENU hMenu = GetSubMenu( GetMenu( _hWnd ), 2 );
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
GetMenuItemInfo( hMenu, IDM_FILTER_SHOWSERVERNAME, FALSE, &mii );
g_fShowServerNames = ( ( mii.fState & MFS_CHECKED ) == MFS_CHECKED );
mii.fState = g_fShowServerNames ? 0 : MFS_CHECKED;
SetMenuItemInfo( hMenu, IDM_FILTER_SHOWSERVERNAME, FALSE, &mii );
}
break;
case IDM_FILTER_RESOURCENOISE:
{
HMENU hMenu = GetSubMenu( GetMenu( _hWnd ), 2 );
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
GetMenuItemInfo( hMenu, IDM_FILTER_RESOURCENOISE, FALSE, &mii );
g_fResourceNoise = ( ( mii.fState & MFS_CHECKED ) == MFS_CHECKED );
mii.fState = g_fResourceNoise ? 0 : MFS_CHECKED;
SetMenuItemInfo( hMenu, IDM_FILTER_RESOURCENOISE, FALSE, &mii );
_ApplyFilters( );
}
break;
case IDM_EDIT_FIND:
if ( !g_hwndFind )
{
new CFindDialog( _hWnd );
}
else
{
ShowWindow( g_hwndFind, SW_SHOW );
}
break;
case IDM_ALL_OFF:
{
ULONG nItems = GetMenuItemCount( _hMenu );
for( ULONG n = 0; n < nItems; n++ )
{
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fState = 0;
SetMenuItemInfo( _hMenu, n, TRUE, &mii );
g_pfSelectedComponent[ n ] = TRUE;
}
_ApplyFilters( );
}
break;
default:
if ( wmId >= IDM_FIRST_CS_FILTER && wmId <= IDM_LAST_CS_FILTER )
{
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(mii) );
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
GetMenuItemInfo( _hMenu, wmId, FALSE, &mii );
g_pfSelectedComponent[ wmId - IDM_FIRST_CS_FILTER - 1 ] = ( ( mii.fState & MFS_CHECKED ) == MFS_CHECKED );
mii.fState = g_pfSelectedComponent[ wmId - IDM_FIRST_CS_FILTER - 1 ] ? 0 : MFS_CHECKED;
SetMenuItemInfo( _hMenu, wmId, FALSE, &mii );
_ApplyFilters( );
}
break;
}
return 0;
}
//
// _OnDestroyWindow( )
//
LRESULT
CApplicationWindow::_OnDestroyWindow( )
{
g_fCApplicationWindowDestroyed = TRUE;
PostQuitMessage(0);
delete this;
return 0;
}
//
// _OnCreate( )
//
LRESULT
CApplicationWindow::_OnCreate(
HWND hwnd,
LPCREATESTRUCT pcs )
{
_hWnd = hwnd;
SetWindowLongPtr( _hWnd, GWLP_USERDATA, (LONG_PTR)this );
return 0;
}
//
// _OnKeyDown( )
//
// Returns FALSE is the default window proc should also
// take a crack at it.
//
// Returns TRUE to stop processing the message.
//
BOOL
CApplicationWindow::_OnKeyDown( WPARAM wParam, LPARAM lParam )
{
RECT rect;
SCROLLINFO si;
ULONG uOldPointer = _uPointer;
BOOL lResult = FALSE;
si.cbSize = sizeof(si);
si.fMask = SIF_POS | SIF_PAGE;
GetScrollInfo( _hWnd, SB_VERT, &si );
SetRect( &rect, 0, ( _uPointer - si.nPos ) * _tm.tmHeight, _xWindow, ( _uPointer - si.nPos + 1 ) * _tm.tmHeight );
if ( wParam == VK_PRIOR
|| wParam == VK_UP
|| wParam == VK_HOME
|| wParam == VK_END
|| wParam == VK_NEXT
|| wParam == VK_DOWN )
{
if ( _fSelection )
{
if ( GetKeyState( VK_SHIFT ) >= 0 )
{
_fSelection = FALSE;
InvalidateRect( _hWnd, NULL, FALSE );
}
}
else
{
if ( GetKeyState( VK_SHIFT ) < 0 )
{
_fSelection = TRUE;
InvalidateRect( _hWnd, NULL, FALSE );
}
}
}
switch ( wParam )
{
case VK_PRIOR:
_uPointer -= si.nPage - 1;
case VK_UP:
_uPointer--;
if ( _uPointer >= _cTotalLineCount )
{
_uPointer = _cTotalLineCount - 1;
}
if ( GetKeyState( VK_SHIFT ) < 0 )
{
if ( uOldPointer == _uStartSelection )
{
_uStartSelection = _uPointer;
}
else
{
_uEndSelection = _uPointer;
}
InvalidateRect( _hWnd, NULL, FALSE );
}
else
{
_uStartSelection = _uEndSelection = _uPointer;
if ( _uPointer < (ULONG) si.nPos )
{
if ( wParam == VK_UP )
{
SendMessage( _hWnd, WM_VSCROLL, SB_LINEUP, 0 );
GetScrollInfo( _hWnd, SB_VERT, &si );
}
}
else
{
rect.top -= _tm.tmHeight;
InvalidateRect( _hWnd, &rect, FALSE );
}
}
if ( wParam == VK_PRIOR )
{
SendMessage( _hWnd, WM_VSCROLL, SB_PAGEUP, 0 );
}
else if ( _uPointer < (ULONG) si.nPos )
{
si.fMask = SIF_POS;
si.nPos = _uPointer;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
InvalidateRect( _hWnd, NULL, FALSE );
}
lResult = TRUE;
break;
case VK_NEXT:
_uPointer += si.nPage - 1;
case VK_DOWN:
_uPointer++;
if ( _uPointer >= _cTotalLineCount )
{
_uPointer = _cTotalLineCount - 1;
}
if ( GetKeyState( VK_SHIFT ) < 0 )
{
if ( uOldPointer == _uEndSelection )
{
_uEndSelection = _uPointer;
}
else
{
_uStartSelection = _uPointer;
}
InvalidateRect( _hWnd, NULL, FALSE );
}
else
{
_uStartSelection = _uEndSelection = _uPointer;
if ( _uPointer > si.nPos + si.nPage )
{
if ( wParam == VK_DOWN )
{
SendMessage( _hWnd, WM_VSCROLL, SB_LINEDOWN, 0 );
GetScrollInfo( _hWnd, SB_VERT, &si );
}
}
else
{
rect.bottom += _tm.tmHeight;
InvalidateRect( _hWnd, &rect, FALSE );
}
}
if ( wParam == VK_NEXT )
{
SendMessage( _hWnd, WM_VSCROLL, SB_PAGEDOWN, 0 );
}
else if ( _uPointer > si.nPos + si.nPage )
{
si.fMask = SIF_POS;
si.nPos = _uPointer;
SetScrollInfo( _hWnd, SB_VERT, &si, TRUE );
InvalidateRect( _hWnd, NULL, FALSE );
}
lResult = TRUE;
break;
case VK_HOME:
_LineFinder.nLine = 0;
_LineFinder.psLine = NULL;
_uPointer = 0;
if ( GetKeyState( VK_SHIFT ) < 0 )
{
if ( uOldPointer == _uEndSelection )
{
_uEndSelection = _uStartSelection;
}
_uStartSelection = 0;
}
else
{
_uEndSelection = _uStartSelection = _uPointer;
}
if ( uOldPointer < si.nPage )
{
InvalidateRect( _hWnd, &rect, FALSE );
SetRect( &rect, 0, ( _uPointer - si.nPos ) * _tm.tmHeight, _xWindow, ( _uPointer - si.nPos + 1 ) * _tm.tmHeight );
InvalidateRect( _hWnd, &rect, FALSE );
}
else
{
SendMessage( _hWnd, WM_VSCROLL, SB_TOP, 0 );
}
lResult = TRUE;
break;
case VK_END:
_LineFinder.nLine = _cTotalLineCount;
_LineFinder.psLine = NULL;
_uPointer = _cTotalLineCount - 1;
if ( GetKeyState( VK_SHIFT ) < 0 )
{
if ( uOldPointer == _uStartSelection )
{
_uStartSelection = _uEndSelection;
}
_uEndSelection = 0;
}
else
{
_uEndSelection = _uStartSelection = _uPointer;
}
if ( uOldPointer > _cTotalLineCount - si.nPage )
{
InvalidateRect( _hWnd, &rect, FALSE );
SetRect( &rect, 0, ( _uPointer - si.nPos ) * _tm.tmHeight, _xWindow, ( _uPointer - si.nPos + 1 ) * _tm.tmHeight );
InvalidateRect( _hWnd, &rect, FALSE );
}
else
{
SendMessage( _hWnd, WM_VSCROLL, SB_BOTTOM, 0 );
}
lResult = TRUE;
break;
case VK_LEFT:
SendMessage( _hWnd, WM_HSCROLL, SB_PAGEUP, 0 );
break;
case VK_RIGHT:
SendMessage( _hWnd, WM_HSCROLL, SB_PAGEDOWN, 0 );
break;
case VK_F5: // refresh
PostMessage( _hWnd, WM_COMMAND, IDM_FILE_REFRESH, 0 );
break;
case 'F':
if ( GetKeyState( VK_CONTROL ) < 0 )
{
PostMessage( _hWnd, WM_COMMAND, IDM_EDIT_FIND, 0 );
}
break;
case 'A':
if ( GetKeyState( VK_CONTROL ) < 0 )
{
PostMessage( _hWnd, WM_COMMAND, IDM_OPEN_FILE, 0 );
}
break;
case 'C':
if ( GetKeyState( VK_CONTROL ) < 0 )
{
PostMessage( _hWnd, WM_COMMAND, IDM_EDIT_COPY, 0 );
}
break;
}
return lResult;
}
//
// _OnLeftButtonDown( )
//
LRESULT
CApplicationWindow::_OnLeftButtonDown(
WPARAM wParam,
LPARAM lParam
)
{
SCROLLINFO si;
DWORD fwKeys = (DWORD) wParam;
DWORD x = GET_X_LPARAM( lParam );
DWORD y = GET_Y_LPARAM( lParam );
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo( _hWnd, SB_VERT, &si );
_uPointer = si.nPos + y / _tm.tmHeight;
InvalidateRect( _hWnd, NULL, FALSE );
if ( fwKeys & MK_SHIFT )
{
if ( _uPointer < _uStartSelection )
{
_uStartSelection = _uPointer;
}
else if ( _uPointer > _uEndSelection )
{
_uEndSelection = _uPointer;
}
}
else
{
_uStartSelection = _uEndSelection = _uPointer;
}
return FALSE;
}
//
// WndProc( )
//
LRESULT CALLBACK
CApplicationWindow::WndProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
CApplicationWindow * paw = (CApplicationWindow *) GetWindowLongPtr( hWnd, GWLP_USERDATA );
if ( paw != NULL )
{
switch( uMsg )
{
case WM_COMMAND:
return paw->_OnCommand( wParam, lParam );
case WM_PAINT:
return paw->_OnPaint( wParam, lParam );
case WM_DESTROY:
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)NULL );
return paw->_OnDestroyWindow( );
case WM_SIZE:
return paw->_OnSize( lParam );
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if ( paw->_OnKeyDown( wParam, lParam ) )
return 0;
break; // do default as well
case WM_VSCROLL:
return paw->_OnVerticalScroll( wParam, lParam );
case WM_HSCROLL:
return paw->_OnHorizontalScroll( wParam, lParam );
case WM_MOUSEWHEEL:
return paw->_OnMouseWheel( HIWORD(wParam) );
case WM_FIND_NEXT:
return paw->_FindNext( wParam, lParam );
case WM_MARK_ALL:
return paw->_MarkAll( wParam, lParam );
case WM_ERASEBKGND:
goto EraseBackground;
case WM_LBUTTONDOWN:
return paw->_OnLeftButtonDown( wParam, lParam );
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
if ( uMsg == WM_CREATE )
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT) lParam;
paw = (CApplicationWindow *) pcs->lpCreateParams;
return paw->_OnCreate( hWnd, pcs );
}
if ( uMsg == WM_ERASEBKGND )
{
EraseBackground:
RECT rectWnd;
HBRUSH hBrush;
HDC hdc = (HDC) wParam;
GetClientRect( hWnd, &rectWnd );
#if defined(DEBUG_PAINT)
hBrush = CreateSolidBrush( 0xFF00FF );
#else
hBrush = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
#endif
FillRect( hdc, &rectWnd, hBrush );
DeleteObject( hBrush );
return TRUE;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
// Mesage handler for about box.
LRESULT CALLBACK
CApplicationWindow::About(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}