windows-nt/Source/XPSP1/NT/net/snmp/subagent/snmpevnt/evntwin/lcsource.cpp

634 lines
16 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "stdafx.h"
#include "source.h"
#include "lcsource.h"
#include "regkey.h"
#include "source.h"
#include "utils.h"
#include "globals.h"
#include "busy.h"
#include "trapreg.h"
/////////////////////////////////////////////////////////////////////////////
// CLcSource
CLcSource::CLcSource()
{
}
CLcSource::~CLcSource()
{
}
//***************************************************************************
//
// CLcSource::AddMessage
//
// Add a message to the list control. This sets the text for each column in
// the list view and sets the lParam field of the list-view item to pMessage.
//
//
// Parameters:
// CMessage* pMessage
//
// Returns:
// Nothing.
//
// Status:
//
//***************************************************************************
void CLcSource::AddMessage(CXMessage* pMessage)
{
CString sText;
pMessage->GetShortId(sText);
// Insert a new item into this list control.
LV_ITEM lvitem;
lvitem.mask = LVIF_TEXT | LVIF_PARAM;
lvitem.iSubItem = ICOL_LcSource_EVENTID;
lvitem.cchTextMax = MAX_STRING;
lvitem.lParam = (LPARAM)pMessage;
lvitem.pszText = (LPTSTR)(LPCTSTR)sText;
int nItem = InsertItem(&lvitem);
if (nItem >= 0)
{
CXEventSource* pEventSource = pMessage->m_pEventSource;
// Now set the string value for each sub-item.
pMessage->GetSeverity(sText);
SetItemText(nItem, ICOL_LcSource_SEVERITY, (LPTSTR)(LPCTSTR) sText);
pMessage->IsTrapping(sText);
SetItemText(nItem, ICOL_LcSource_TRAPPING, (LPTSTR)(LPCTSTR)sText);
SetItemText(nItem, ICOL_LcSource_DESCRIPTION, (LPTSTR)(LPCTSTR) pMessage->m_sText);
}
}
//*******************************************************************
// CXMessageArray::SetDescriptionWidth
//
// Set the width of the description field so that it is wide enough to
// hold the widest message.
//
// Parameters:
// CXMessageArray& aMessages
// The message array that will be used to fill the list control.
//
// Returns:
// Nothing.
//
//*******************************************************************
void CLcSource::SetDescriptionWidth(CXMessageArray& aMessages)
{
LONG cxWidestMessage = CX_DEFAULT_DESCRIPTION_WIDTH;
LONG nMessages = aMessages.GetSize();
for (LONG iMessage = 0; iMessage < nMessages; ++iMessage) {
CXMessage* pMessage = aMessages[iMessage];
int cx = GetStringWidth(pMessage->m_sText);
if (cx > cxWidestMessage) {
cxWidestMessage = cx;
}
}
// Set the column width to the width of the widest string plus a little extra
// space for slop and to make it obvious to the user that the complete string
// is displayed.
SetColumnWidth(ICOL_LcSource_DESCRIPTION, cxWidestMessage + CX_DESCRIPTION_SLOP);
}
//***************************************************************************
//
// CLcSource::LoadMessages
//
// Load the messages from the message library module and insert them into
// this list control.
//
// Parameters:
// CMessage* pMessage
//
// Returns:
// Nothing.
//
// Status:
//
//***************************************************************************
SCODE CLcSource::SetEventSource(CXEventSource* pEventSource)
{
CBusy busy;
DeleteAllItems();
if (pEventSource == NULL) {
return S_OK;
}
UpdateWindow();
//!!!CR: Should do something with the return code in case the
//!!!CR: messages weren't loaded.
SCODE sc = pEventSource->LoadMessages();
// Iterate through each of the messages and insert them into
// the list control.
CXMessageArray& aMessages = pEventSource->m_aMessages;
// Set the width of the description field so that it is wide enough to contain
// the widest message.
SetDescriptionWidth(aMessages);
LONG nMessages = aMessages.GetSize();
for (LONG iMessage=0; iMessage < nMessages; ++iMessage) {
if ((iMessage < 40 && (iMessage % 10 == 9)) ||
(iMessage % 100 == 99)) {
// Update the window often for the first few messages and less frequently
// thereafter for a good response time.
UpdateWindow();
}
AddMessage(aMessages[iMessage]);
}
SortItems(ICOL_LcSource_EVENTID);
SetRedraw(TRUE);
UpdateWindow();
EnsureVisible(0, FALSE);
if (GetSize())
SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
return S_OK;
}
BEGIN_MESSAGE_MAP(CLcSource, CListCtrl)
//{{AFX_MSG_MAP(CLcSource)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLcSource message handlers
//***************************************************************************
//
// CLcSource::CreateWindowEpilogue()
//
// This method is called after a window has been created for this list
// control. Final initialization is done here.
//
// Parameters:
// None.
//
// Returns:
// SCODE
// S_OK if the initialization was successful, otherwise E_FAIL.
//
// Status:
//
//***************************************************************************
SCODE CLcSource::CreateWindowEpilogue()
{
ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_FULLROWSELECT);
SetColumnHeadings();
return S_OK;
}
//***************************************************************************
//
// CLcSource::SetColumnHeadings
//
// Define's the columns for this list control. The column title, width, and
// order is defined here.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
// Status:
//
//***************************************************************************
void CLcSource::SetColumnHeadings()
{
static UINT auiResColumnTitle[ICOL_LcSource_MAX] = {
IDS_LcSource_TITLE_EVENT_ID,
IDS_LcSource_TITLE_SEVERITY,
IDS_LcSource_TITLE_TRAPPING,
IDS_LcSource_TITLE_DESCRIPTION
};
static int aiColWidth[ICOL_LcSource_MAX] = {60, 75, 60, CX_DEFAULT_DESCRIPTION_WIDTH};
// Build the columns in the AllEventsList control.
LV_COLUMN lvcol;
lvcol.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for (int iCol=0; iCol<ICOL_LcSource_MAX; ++iCol)
{
CString sColTitle;
sColTitle.LoadString(auiResColumnTitle[iCol]);
lvcol.pszText = sColTitle.GetBuffer(sColTitle.GetLength());
lvcol.iSubItem = iCol;
lvcol.cx = aiColWidth[iCol];
InsertColumn(iCol, &lvcol);
sColTitle.ReleaseBuffer();
}
}
//******************************************************************
// CLcSource::Find
//
// Find the specified event source in this list control.
//
// Parameters:
// CString& sText
// A string containing the text to search for.
//
// BOOL bWholeWord
// TRUE if this is a "whole word" search. False if it
// is OK to match a partial word.
//
// BOOL bMatchCase
// TRUE if a case-sensitive comparison should be used.
//
// Returns:
// BOOL
// TRUE if the string was found, FALSE otherwise. If the specified
// text is found, then the selection is set on the corresponding
// list control item, the item is scrolled into view and the focus
// is set on the item.
//
//******************************************************************
BOOL CLcSource::Find(CString sText, BOOL bWholeWord, BOOL bMatchCase)
{
// Don't do anything if the list is empty.
if (GetSize() == 0)
return FALSE;
if (!bMatchCase)
sText.MakeUpper();
// Get the selected item.
LONG iItem = GetNextItem(-1, LVNI_SELECTED);
// Nothing selected; start from the top of the list.
if (iItem == -1)
iItem = 0;
// Iterate through all of the items starting at one item past
// the currently selected item.
CXMessage* pMessage;
CString sDescription;
BOOL bFound = FALSE;
LONG nItems = GetSize();
LONG iItemStart = iItem;
for (long i=0; !bFound && i<nItems; ++i) {
// Bump the item index to the next one and wrap it if its past the
// last item.
iItem = (iItem + 1) % nItems;
// Get the message description for this item.
pMessage = GetAt(iItem);
sDescription = pMessage->m_sText;
if (!bMatchCase)
sDescription.MakeUpper();
if (bWholeWord) {
// Compare the whole word.
bFound = (FindWholeWord(sText, sDescription) != -1);
}
else {
// Look for a substring.
if (sDescription.Find(sText) >= 0)
bFound = TRUE;
}
}
// Found a match.
if (bFound)
{
// Unselect the selected item and select the found item.
SetItemState(iItemStart, 0, LVIS_SELECTED | LVIS_FOCUSED);
SetItemState(iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
EnsureVisible(iItem, FALSE);
return TRUE;
}
return FALSE;
}
//***************************************************************************
//
// fnCompareCLcSource
//
// This the item comparison callback method that is called from CLcSource::SortItems.
//
// Parameters:
// LPARAM lParam1
// This is the lparam for the first item to compare. This is a pointer to
// the associated CMessage object.
//
// LPARAM lParam2
// This is the lparam for the second item to compare. This is a pointer to
// the associated CMessage object.
//
// LPARAM lColumn
// This is the second parameter that was passed to CListCtrl::SortItems. This
// happens to be the list control column index.
//
// Returns:
// Nothing.
//
// Status:
//
//***************************************************************************
int CALLBACK fnCompareCLcSource(LPARAM lParam1, LPARAM lParam2, LPARAM lColumn)
{
// !!!CR: The LPARAM parameters are not event pointers in all cases because
// !!!CR: each subitem has its own LPARAM. What should I do?
CXMessage *pmsg1 = (CXMessage *)lParam1;
CXMessage *pmsg2 = (CXMessage *)lParam2;
int nResult = 0;
CString s1, s2;
if (pmsg1 && pmsg2)
{
switch( lColumn)
{
case ICOL_LcSource_EVENTID:
nResult = ((LONG) pmsg1->GetShortId()) - ((LONG)pmsg2->GetShortId());
break;
case ICOL_LcSource_SEVERITY:
pmsg1->GetSeverity(s1);
pmsg2->GetSeverity(s2);
nResult = lstrcmpi(s1, s2);
break;
case ICOL_LcSource_TRAPPING:
pmsg1->IsTrapping(s1);
pmsg2->IsTrapping(s2);
nResult = lstrcmpi(s1, s2);
break;
case ICOL_LcSource_DESCRIPTION:
nResult = lstrcmpi(pmsg1->m_sText, pmsg2->m_sText);
break;
default:
ASSERT(FALSE);
nResult = 0;
break;
}
}
if (!g_abLcSourceSortAscending[lColumn]) {
if (nResult > 0) {
nResult = -1;
}
else if (nResult < 0) {
nResult = 1;
}
}
return(nResult);
}
//***************************************************************************
//
// CLcSource::SortItems
//
// Sort the items in this list control given the column index. This method
// hides all details about the sort implementation from this class's clients.
//
// Parameters:
// DWORD dwColumn
// The column to use as the sort key.
//
// Returns:
// Nothing.
//
// Status:
//
//***************************************************************************
void CLcSource::SortItems(DWORD dwColumn)
{
CListCtrl::SortItems(fnCompareCLcSource, dwColumn);
}
//***************************************************************************
//
// CLcSource::GetSelectedMessages
//
// Fill a message array with pointers to the messages that correspond to
// the selected items in this list control.
//
// Note: This list control continues to own the returned pointers. The
// caller should not delete them.
//
// Parameters:
// CMessageArray& amsg
// The message array where the pointers to the selected messages are
// returned.
//
// Returns:
// The message array is filled with pointers to the selected messages. Do
// not delete them, because they are owned by this object.
//
// Status:
//
//***************************************************************************
void CLcSource::GetSelectedMessages(CXMessageArray& amsg)
{
// Clear the message array
amsg.RemoveAll();
// Setup the LV_ITEM structure to retrieve the lparam field.
// This field contains the CMessage pointer.
LV_ITEM lvitem;
lvitem.mask = LVIF_PARAM;
lvitem.iSubItem = ICOL_LcSource_EVENTID;
// Loop to find all the selected items.
int nItem = -1;
while (TRUE) {
nItem = GetNextItem(nItem, LVNI_SELECTED);
if (nItem == -1) {
break;
}
// Get the CMessage pointer for this item and add it to the
// array.
lvitem.iItem = nItem;
GetItem(&lvitem);
CXMessage* pmsg = (CXMessage*) (void*) lvitem.lParam;
amsg.Add(pmsg);
}
}
//***************************************************************************
//
// CLcSource::FindItem
//
// Search through this list-controls's items to find the one with the
// specified message ID.
//
// Parameters:
// DWORD dwMessageId
// The message ID to search for.
//
// Returns:
// The index of the item with the specified message ID. If no such message ID
// was found, -1 is returned.
//
// Status:
//
//***************************************************************************
LONG CLcSource::FindItem(DWORD dwMessageId)
{
LONG nItems = GetItemCount();
for (LONG iItem = 0; iItem < nItems; ++iItem) {
CXMessage* pMessage = GetAt(iItem);
if (pMessage->m_dwId == dwMessageId) {
return iItem;
}
}
return -1;
}
//***************************************************************************
//
// CLcSource::RefreshItem
//
// This method is called when some aspect of the message has changed and
// the display needs to be updated. This occurs when the trapping status
// of an event changes.
//
// Parameters:
// DWORD dwMessageId
// The message ID to search for.
//
// Returns:
// The index of the item with the specified message ID. If no such message ID
// was found, -1 is returned.
//
// Status:
//
//***************************************************************************
void CLcSource::RefreshItem(LONG iItem)
{
CXMessage* pMessage = GetAt(iItem);
CString sText;
// Now set the text value for each column in the list control.
pMessage->GetSeverity(sText);
SetItemText(iItem, ICOL_LcSource_SEVERITY, (LPTSTR)(LPCTSTR) sText);
// Check if we are trapping this event.
pMessage->IsTrapping(sText);
SetItemText(iItem, ICOL_LcSource_TRAPPING, (LPTSTR)(LPCTSTR)sText);
SetItemText(iItem, ICOL_LcSource_DESCRIPTION, (LPTSTR)(LPCTSTR)pMessage->m_sText);
}
//***************************************************************************
//
// CLcSource::GetAt
//
// This method returns the message pointer located at the given item index.
// This allows CLcSource to be used much as an array.
//
// Parameters:
// LONG iItem
// The item index.
//
// Returns:
// A pointer to the CMessage stored at the specified index.
//
// Status:
//
//***************************************************************************
CXMessage* CLcSource::GetAt(LONG iItem)
{
// Setup the LV_ITEM structure to retrieve the lparam field.
// This field contains the CMessage pointer.
LV_ITEM lvitem;
lvitem.mask = LVIF_PARAM;
lvitem.iSubItem = ICOL_LcSource_EVENTID;
lvitem.iItem = iItem;
GetItem(&lvitem);
CXMessage* pMessage = (CXMessage*) (void*) lvitem.lParam;
return pMessage;
}
//***************************************************************************
// CLcSource::NotifyTrappingChange
//
// This method is called when a message's trapping status changes. A message
// is considered trapped if it appears in the CLcEvents listbox.
//
// Parameters:
// DWORD dwMessageId
// The ID of the message who's trapping status is changing.
//
// BOOL bIsTrapping
// TRUE if the message is being trapped, FALSE otherwise.
//
// Returns:
// Nothing.
//
//***************************************************************************
void CLcSource::NotifyTrappingChange(DWORD dwMessageId, BOOL bIsTrapping)
{
LONG iItem = FindItem(dwMessageId);
ASSERT(iItem != -1);
if (iItem != -1) {
CString sTrapping;
sTrapping.LoadString(bIsTrapping ? IDS_IS_TRAPPING : IDS_NOT_TRAPPING);
SetItemText(iItem, ICOL_LcSource_TRAPPING, (LPTSTR)(LPCTSTR)sTrapping);
}
}