📄 tailview.cpp
字号:
/*
* Tail for Win32 - a Windows version of the UNIX 'tail -f' command.
*
* Author: Paul Perkins (paul@objektiv.org.uk)
*
* Copyright(c)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: TailView.cpp,v 1.28 2003/11/25 08:48:28 paulperkins Exp $
*
*/
#include "stdafx.h"
#include <io.h>
#include <stdio.h>
#include "Tail.h"
#include "TailDoc.h"
#include "TailView.h"
#include "keywordlist.h"
#include "Plugin.h"
#include "PluginConfig.h"
#include "hotlistdisplay.h"
#include "commdlg.h"
#include "tallywindow.h"
#include "utils.h"
#include "settings.h"
#include "workspacedlg.h"
#include "eventlogthread.h"
#include "filereaderthread.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define KEYWORD_FILE "keywords.cfg"
#define LINE_PAD (256)
UINT ReaderThread (LPVOID pParams);
extern CTailApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CTailView
IMPLEMENT_DYNCREATE(CTailView, CView)
BEGIN_MESSAGE_MAP(CTailView, CView)
//{{AFX_MSG_MAP(CTailView)
ON_WM_CREATE()
ON_WM_SIZE()
ON_COMMAND(IDM_IGNORE_STARTUP, OnIgnoreStartup)
ON_COMMAND(IDM_DISPLAY_HOTLIST, OnDisplayHotlist)
ON_COMMAND(IDM_SETFONT, OnSetfont)
ON_COMMAND(IDM_CONFIG_PLUGINS, OnConfigPlugins)
ON_COMMAND(IDM_TALLY, OnTally)
ON_UPDATE_COMMAND_UI(IDM_IGNORE_STARTUP, OnUpdateIgnoreStartup)
ON_COMMAND(ID_VIEW_GO, OnViewGo)
ON_COMMAND(ID_VIEW_STOP, OnViewStop)
ON_COMMAND(IDM_HIGLIGHT_LINE, OnHiglightLine)
ON_UPDATE_COMMAND_UI(IDM_HIGLIGHT_LINE, OnUpdateHiglightLine)
ON_COMMAND(IDM_WORDWRAP, OnWordwrap)
ON_UPDATE_COMMAND_UI(IDM_WORDWRAP, OnUpdateWordwrap)
ON_WM_DESTROY()
ON_COMMAND(IDM_SET_BACKGROUND, OnSetBackground)
ON_COMMAND(IDM_SET_HIGHLIGHT_COLOUR, OnSetHighlightColour)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/*IMPLEMENT_DYNCREATE(CViewThread, CWinThread)
BEGIN_MESSAGE_MAP(CViewThread, CWinThread)
//{{AFX_MSG_MAP(CVCiewThread)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP() */
/////////////////////////////////////////////////////////////////////////////
// CTailView construction/destruction
/////////////////////////////////////////////////////////////////////////////
//
//
CTailView::CTailView()
{
CTailEmailEvent* pEvent = NULL;
m_hThread = NULL;
m_pThread = NULL;
m_bUseTimeout = FALSE;
m_ppszList = NULL;
m_lNumKeywords = 0;
m_bEventsVisible = FALSE;
m_bPaused = FALSE;
m_bTallyVisible = FALSE;
m_pTallyWindow = NULL;
memset (&m_szTailFile[0], 0, sizeof (m_szTailFile));
memset (&m_szDieEvent[0], 0, sizeof (m_szDieEvent));
m_pSettings = theApp.GetSettings ();
LoadKeywords ();
}
/////////////////////////////////////////////////////////////////////////////
//
//
CTailView::~CTailView()
{
CTailApp* pApp = (CTailApp*) AfxGetApp ();
if (m_ppszList)
{
for (int i = 0; i < m_lNumKeywords; i++)
{
if (m_ppszList[i])
{
free (m_ppszList[i]);
m_ppszList[i] = NULL;
}
}
free (m_pstKeywordList);
m_pstKeywordList = NULL;
free (m_ppszList);
m_ppszList = NULL;
// Warlock, added bTallyVisible check
if (m_bTallyVisible)
{
if (AfxIsValidAddress (m_pTallyWindow, sizeof (TallyWindow)) && m_pTallyWindow->GetSafeHwnd ())
{
delete m_pTallyWindow;
}
}
}
}
BOOL CTailView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTailView drawing
void CTailView::OnDraw(CDC* pDC)
{
CTailDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CTailView diagnostics
#ifdef _DEBUG
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::AssertValid() const
{
CView::AssertValid();
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
/////////////////////////////////////////////////////////////////////////////
//
//
CTailDoc* CTailView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTailDoc)));
return (CTailDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTailView message handlers
/////////////////////////////////////////////////////////////////////////////
//
//
int CTailView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
RECT rc;
CHARFORMAT cf;
CTailApp* theApp = (CTailApp*) AfxGetApp ();
int aiBarParts[] = {120, 360, 360, -1};
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
GetClientRect (&rc);
rc.top = 100;
m_ctlStatusBar.Create (WS_CHILD | WS_VISIBLE, rc, this, 2);
m_ctlStatusBar.SetParts (4, &aiBarParts[0]);
m_ctlStatusBar.SetText ("Loaded.", 0, 0);
GetClientRect (&rc);
rc.top -= 100;
m_ctlEdit.Create ( WS_CHILD | WS_VISIBLE |
ES_MULTILINE | ES_READONLY |
ES_AUTOVSCROLL | ES_AUTOHSCROLL |
WS_VSCROLL | WS_HSCROLL,
rc, this, 1);
if (!m_pSettings->GetGotFont())
{
// Set up some defaults.
m_ctlEdit.GetDefaultCharFormat (cf);
strcpy (cf.szFaceName, "Courier New");
cf.dwMask |= CFM_FACE | CFM_BOLD;
cf.dwEffects = cf.dwEffects & ~CFE_BOLD ;
m_ctlEdit.SetDefaultCharFormat (cf);
}
else
{
SetViewFont (&m_pSettings->GetLogFont());
}
m_ctlEdit.SetBackgroundColor (FALSE, m_pSettings->GetBackGroundColour());
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::SetViewFont (
LOGFONT* pstLogFont)
{
CHARFORMAT stFormat;
int nPoint; // Warlock
m_ctlEdit.GetDefaultCharFormat (stFormat);
// Warlock, added font size changing capability
nPoint = -MulDiv( 72, pstLogFont->lfHeight, m_ctlEdit.GetDC()->GetDeviceCaps(LOGPIXELSY) );
stFormat.yHeight= MulDiv( nPoint, 1440, 72 ); // Twips
stFormat.bCharSet = pstLogFont->lfCharSet;
stFormat.bPitchAndFamily = pstLogFont->lfPitchAndFamily;
strcpy (stFormat.szFaceName, pstLogFont->lfFaceName);
stFormat.dwMask |= CFM_UNDERLINE | CFM_BOLD | CFM_ITALIC | CFM_FACE;
if (pstLogFont->lfUnderline)
{
stFormat.dwEffects |= CFE_UNDERLINE;
}
else
{
stFormat.dwEffects &= ~CFE_UNDERLINE;
}
if (pstLogFont->lfItalic)
{
stFormat.dwEffects |= CFE_ITALIC;
}
else
{
stFormat.dwEffects &= ~CFE_ITALIC;
}
if (pstLogFont->lfWeight > 500)
{
stFormat.dwEffects |= CFE_BOLD;
}
else
{
stFormat.dwEffects &= ~CFE_BOLD;
}
m_ctlEdit.SetDefaultCharFormat (stFormat);
m_pSettings->SetGotFont (TRUE);
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
m_ctlEdit.MoveWindow (0, 0, cx, cy - 20);
m_ctlStatusBar.MoveWindow (0, cy - 20, cx, 20);
ScrollToBottom (m_ctlEdit.GetSafeHwnd ());
m_ctlEdit.SetTargetDevice (NULL, m_pSettings->GetWordWrap() ? 0 : 1);
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CTailDoc* pDoc = NULL;
memset (&m_stParams, 0, sizeof (READER_PARAMS));
memset (&m_stELParams, 0, sizeof (EVENT_LOG_THREAD_PARAMS));
pDoc = (CTailDoc*) GetDocument ();
sprintf (m_szDieEvent, "%s%08ld", DIE_EVENT_NAME, (DWORD)(void*) this);
strcpy (m_szTailFile, pDoc->m_strTailFile);
strcpy (m_stParams.szFileName, m_szTailFile);
m_stParams.hEdit = m_ctlEdit.GetSafeHwnd ();
m_stParams.bUseTimeout = m_bUseTimeout;
m_stParams.nTimeout = m_pSettings->GetTimeout ();
m_stParams.bIgnoreHotStartup = m_pSettings->GetIgnoreHotStartup ();
m_stParams.pView = this;
m_stParams.bDebug = m_pSettings->GetDebug ();
strcpy (m_stParams.szDieEvent, m_szDieEvent);
strcpy (m_stParams.szReloadEvent, RELOAD_EVENT_NAME);
m_stParams.bPaused = FALSE;
/* strcpy (m_stELParams.szFileName, pDoc->m_strTailFile);
m_stELParams.hEdit = m_ctlEdit.GetSafeHwnd ();
m_stELParams.bUseTimeout = m_bUseTimeout;
m_stELParams.nTimeout = pSettings->GetTimeout ();
m_stELParams.bIgnoreHotStartup = pSettings->GetIgnoreHotStartup ();
m_stELParams.pView = this;
m_stELParams.bDebug = pSettings->GetDebug ();
strcpy (m_stELParams.szDieEvent, m_szDieEvent);
m_stELParams.bPaused = FALSE; */
if (!m_pThread && !pDoc->m_strTailFile.IsEmpty ())
{
m_pThread = AfxBeginThread ((AFX_THREADPROC) ReaderThread, (LPVOID) &m_stParams);
// Comment out the above line and uncomment the following line to see event log monitoring in action.
// m_pThread = AfxBeginThread ((AFX_THREADPROC) EventLogThread, (LPVOID) &m_stELParams);
}
// Add ourself to the workpace dialog.
// The NULL parameter concerns me here, as it'll try to add itself to
// the default workspace.
theApp.m_pWorkspace->AddWorkspaceFile (m_stParams.szFileName, this, NULL);
SetWindowText (m_szTailFile);
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::Update (
void)
{
}
/////////////////////////////////////////////////////////////////////////////
//
//
void CTailView::Refresh ()
{
HANDLE hFile = NULL;
DWORD dwSize = 0;
char* pszBuffer;
DWORD dwBytesRead;
BOOL bReadOK = FALSE;
char szMsg[1024] = "";
memset (&m_stParams, 0, sizeof (READER_PARAMS));
if (!pDoc->m_strTailFile || pDoc->m_strTailFile == "")
{
::MessageBox (AfxGetMainWnd()->GetSafeHwnd(), "PANIC: Document has no file!", "Tail for Win32", MB_OK | MB_ICONSTOP);
return;
}
hFile = CreateFile (m_szTailFile,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING, //OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_POSIX_SEMANTICS,
NULL);
int i = GetLastError ();
if (hFile == INVALID_HANDLE_VALUE)
{
sprintf (szMsg, "Could not open '%s'.", m_szTailFile);
::MessageBox (AfxGetMainWnd()->GetSafeHwnd(), szMsg, "Tail for Win32", MB_OK | MB_ICONSTOP);
return;
}
dwSize = GetFileSize (hFile, NULL);
dwSize++;
pszBuffer = (char*) malloc (dwSize);
ASSERT (pszBuffer);
memset ((void*) pszBuffer, 0, dwSize);
bReadOK = ReadFile (hFile, (LPVOID) pszBuffer, dwSize - 1, &dwBytesRead, NULL);
CloseHandle (hFile);
if (bReadOK)
{
m_ctlEdit.SetWindowText (pszBuffer);
ScrollToBottom (m_ctlEdit.GetSafeHwnd ());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -