⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tailview.cpp

📁 Ever wanted to just type tail -f error_log on Windows?Envious of your Unix friends who can track cha
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -